Obtenir SID de l'Utilisateur à Partir de l'ID de Connexion (Windows XP)

J'ai un service Windows qui a besoin d'accéder à ruches de registre sous la clé HKEY_USERS lorsque les utilisateurs se connectent, que ce soit en local ou via le Serveur Terminal server. Je suis à l'aide d'une requête WMI sur win32_logonsession pour recevoir des événements lorsque les utilisateurs se connectent, et l'une des propriétés que je reçois de cette requête est un LogonId. Pour savoir de quel ruche de registre j'ai besoin d'accéder, maintenant, j'ai besoin des utilisateurs de SID, qui est utilisé comme un nom de clé de registre sous la clé HKEY_USERS.

Dans la plupart des cas, je peux l'obtenir en faisant un RelatedObjectQuery comme (en C#):

RelatedObjectQuery relatedQuery = new RelatedObjectQuery( "associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent" );

où "logonID" est l'ouverture de session ID de session de la session de la requête. L'exécution de la RelatedObjectQuery généralement donnez-moi un SID de la propriété qui contient exactement ce dont j'ai besoin.

Il y a deux problèmes que j'ai avec cette. Premier et le plus important, le RelatedObjectQuery ne retourne aucun résultat pour un utilisateur de domaine qui se connecte avec mise en cache des informations d'identification, déconnecté du domaine. Deuxièmement, je ne suis pas satisfait de la performance de cette RelatedObjectQuery - - - - - cela peut prendre plusieurs secondes à s'exécuter.

Voici un moyen rapide et sale programme en ligne de commande j'ai jeté à expérimenter avec les requêtes. Plutôt que de fixer jusqu'à recevoir des événements, c'est juste énumère les utilisateurs sur la machine locale:

using System;
using System.Collections.Generic;
using System.Text;
using System.Management;
namespace EnumUsersTest
{
class Program
{
static void Main( string[] args )
{
ManagementScope scope = new ManagementScope( "\\\\.\\root\\cimv2" );
string queryString = "select * from win32_logonsession";                          //for all sessions
//string queryString = "select * from win32_logonsession where logontype = 2";     //for local interactive sessions only
ManagementObjectSearcher sessionQuery = new ManagementObjectSearcher( scope, new SelectQuery( queryString ) );
ManagementObjectCollection logonSessions = sessionQuery.Get();
foreach ( ManagementObject logonSession in logonSessions )
{
string logonID = logonSession["LogonId"].ToString();
Console.WriteLine( "=== {0}, type {1} ===", logonID, logonSession["LogonType"].ToString() );
RelatedObjectQuery relatedQuery = new RelatedObjectQuery( "associators of {Win32_LogonSession.LogonId='" + logonID + "'} WHERE AssocClass=Win32_LoggedOnUser Role=Dependent" );
ManagementObjectSearcher userQuery = new ManagementObjectSearcher( scope, relatedQuery );
ManagementObjectCollection users = userQuery.Get();
foreach ( ManagementObject user in users )
{
PrintProperties( user.Properties );
}
}
Console.WriteLine( "\nDone! Press a key to exit..." );
Console.ReadKey( true );
}
private static void PrintProperty( PropertyData pd )
{
string value = "null";
string valueType = "n/a";
if ( pd.Value != null )
{
value = pd.Value.ToString();
valueType = pd.Value.GetType().ToString();
}
Console.WriteLine( "  \"{0}\" = ({1}) \"{2}\"", pd.Name, valueType, value );
}
private static void PrintProperties( PropertyDataCollection properties )
{
foreach ( PropertyData pd in properties )
{
PrintProperty( pd );
}
}
}
}

Donc... est-il rapidement et de manière fiable obtenir le SID de l'utilisateur donné les informations que j'ai récupérer à partir de WMI, ou devrais-je être à la recherche à l'aide de quelque chose comme SENS à la place?

OriginalL'auteur Dave Ruske | 2010-04-28