Meinem ursprünglichen Kommentar zufolge scheint die SUSER_SID
Funktion nur die Seite zu erfassen, die beim Erstellen der Anmeldung aufgezeichnet wurde, und Active Directory nicht abzufragen (sinnvoll, da dies teuer sein kann - ich habe sogar versucht, den Serverdienst neu zu starten).
Hier ist eine C # -Konsolenanwendung, die die Aufgabe ausführt und es Ihnen ermöglicht, die Anmeldungen zu überwachen, die gelöscht werden, bevor sie tatsächlich gelöscht werden.
Für diese App ist .NET 3.5 oder höher erforderlich, und theoretisch kann sie in ein PowerShell-Skript eingefügt werden (ich bin mit der direkten Programmierung viel besser vertraut).
Um alle Anmeldungen lokaler / Computer-Benutzerkonten vom Server zu entfernen, müssen Sie diese Anwendung auf dem Server ausführen und die ContextType
Variable fest codieren (ich habe sie so zum Testen auf meinem Heimcomputer, der keiner Domäne angehört ). Andernfalls können Sie es von jedem Computer in derselben Domäne wie der Server ausführen, der auch Zugriff auf den Server hat.
Ich werde dies in meinem Blog veröffentlichen, nachdem ich die Parameter externalisiert und den Code ein wenig bereinigt habe. Wenn ich das mache, werde ich diesen Beitrag bearbeiten. Aber damit können Sie jetzt loslegen.
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.DirectoryServices.AccountManagement;
using System.Security.Principal;
using System.Text;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
string connectionString = @"Data Source=.\SQL2008R2DEV;Initial Catalog=master;Integrated Security=SSPI;";
ContextType domainContext = Environment.UserDomainName == Environment.MachineName ? ContextType.Machine : ContextType.Domain;
IList<string> deletedPrincipals;
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
deletedPrincipals = _GetDeletedPrincipalsFromServer(conn, domainContext);
}
if (deletedPrincipals.Count > 0)
{
Console.WriteLine("Logins that will be dropped:");
foreach (string loginName in deletedPrincipals)
Console.WriteLine(loginName);
Console.WriteLine();
Console.WriteLine("Press Enter to continue.");
Console.ReadLine();
}
else
Console.WriteLine("No logins with deleted principals.");
if (deletedPrincipals.Count > 0)
{
using (SqlConnection conn = new SqlConnection(connectionString))
{
conn.Open();
_DropDeletedPrincipalLoginsFromServer(conn, deletedPrincipals);
}
Console.WriteLine("Logins dropped successfully.");
}
Console.WriteLine();
Console.WriteLine("Press Enter to continue.");
Console.ReadLine();
}
private static void _DropDeletedPrincipalLoginsFromServer(IDbConnection conn, IList<string> loginNames)
{
if (loginNames.Count == 0)
return;
StringBuilder sb = new StringBuilder();
foreach (string loginName in loginNames)
sb.AppendFormat("DROP LOGIN {0};", loginName); // This was escaped on the way out of SQL Server
IDbTransaction transaction = conn.BeginTransaction();
IDbCommand cmd = conn.CreateCommand();
cmd.Transaction = transaction;
cmd.CommandText = sb.ToString();
try
{
cmd.ExecuteNonQuery();
transaction.Commit();
}
catch
{
try
{
transaction.Rollback();
}
catch { }
throw;
}
}
private static IList<string> _GetDeletedPrincipalsFromServer(IDbConnection conn, ContextType domainContext)
{
List<string> results = new List<string>();
IDbCommand cmd = conn.CreateCommand();
cmd.CommandText = "SELECT sid, QUOTENAME(loginname) AS LoginName FROM sys.syslogins WHERE isntname = 1;";
IDataReader dr = null;
try
{
dr = cmd.ExecuteReader(CommandBehavior.SingleResult);
while (dr.Read())
{
if (!_PrincipalExistsBySid((byte[])dr["sid"], domainContext))
results.Add((string)dr["LoginName"]);
}
}
finally
{
if ((dr != null) && !dr.IsClosed)
dr.Close();
}
return results;
}
private static bool _PrincipalExistsBySid(byte[] principalSid, ContextType domainContext)
{
SecurityIdentifier sid = new SecurityIdentifier(principalSid, 0);
if (sid.IsWellKnown) return true;
using (PrincipalContext pc = new PrincipalContext(domainContext))
{
return AuthenticablePrincipal.FindByIdentity(pc, IdentityType.Sid, sid.Value) != null;
}
}
}
}