2010-03-29 22 views
13

This .NET API fonctionne bien si j'essaie d'ouvrir le Registre sur une machine qui est dans le même domaine que moi (et que mon utilisateur connecté a des droits d'administrateur sur la machine cible).Comment puis-je transmettre des informations d'identification à une machine afin que je puisse utiliser Microsoft.Win32.RegistryKey.OpenRemoteBaseKey() dessus?

Cela devient compliqué si c'est une machine hors domaine avec un utilisateur administrateur local différent (dont j'ai le mot de passe). J'ai essayé d'utiliser WNetUseConnection() (ce qui m'a bien servi dans le passé dans des situations où je voulais lire un fichier disque distant) avant d'appeler OpenRemoteBaseKey(), mais pas de dés - j'obtiens une exception d'accès refusé .

De toute évidence, je dois transmettre des informations d'identification d'une autre manière, mais comment?

Répondre

32

Ce que je l'ai utilisé avec succès pour accéder aux fichiers sur un ordinateur est le code suivant:

#region imports 
     [DllImport("advapi32.dll", SetLastError = true)] 
     private static extern bool LogonUser(string 
     lpszUsername, string lpszDomain, string lpszPassword, 
     int dwLogonType, int dwLogonProvider, ref 
IntPtr phToken); 


     [DllImport("kernel32.dll", CharSet = CharSet.Auto, 
     SetLastError = true)] 
     private static extern bool CloseHandle(IntPtr handle 
     ); 

     [DllImport("advapi32.dll", CharSet = CharSet.Auto, 
     SetLastError = true)] 
     public extern static bool DuplicateToken(IntPtr 
     existingTokenHandle, 
     int SECURITY_IMPERSONATION_LEVEL, ref IntPtr 
     duplicateTokenHandle); 
     #endregion 
     #region logon consts 
     // logon types 
     const int LOGON32_LOGON_INTERACTIVE = 2; 
     const int LOGON32_LOGON_NETWORK = 3; 
     const int LOGON32_LOGON_NEW_CREDENTIALS = 9; 

     // logon providers 
     const int LOGON32_PROVIDER_DEFAULT = 0; 
     const int LOGON32_PROVIDER_WINNT50 = 3; 
     const int LOGON32_PROVIDER_WINNT40 = 2; 
     const int LOGON32_PROVIDER_WINNT35 = 1; 
     #endregion 

Et puis à la signature en partie, il suffit d'utiliser:

 IntPtr token = IntPtr.Zero; 

     bool isSuccess = LogonUser("username", "domain", "password", 
     LOGON32_LOGON_NEW_CREDENTIALS, 
     LOGON32_PROVIDER_DEFAULT, ref token); 
     using (WindowsImpersonationContext person = new WindowsIdentity(token).Impersonate()) 
     { 
     //do your thing 
     person.Undo(); 
     } 

Comme vous pouvez le voir, "Undo()" fera que vous n'êtes plus connecté en tant qu'utilisateur. Donc, ne l'utilisez pas avant d'avoir terminé. Mais n'oubliez pas de l'utiliser!

+2

+1 C'est vraiment la seule façon de le faire. – Nate

+0

Puis-je garder la variable "token" autour d'un long moment, puis utiliser le bloc "using/Undo()" à différents points du même jeton? " – JCCyC

+0

Je pense que c'est l'Impersonate qui se connecte. Qu'est-ce que j'ai utilisé est un "GetImpersonation()" qui renvoie un WindowsImpersonationContext comme ci-dessus –