2010-03-29 10 views
13

This .NET API funciona bien si intento abrir el Registro en una máquina que está en el mismo dominio que yo (y el usuario que inició la sesión tiene derechos de administrador en la máquina de destino).¿Cómo paso las credenciales a una máquina para que pueda usar Microsoft.Win32.RegistryKey.OpenRemoteBaseKey() en él?

Se vuelve complicado si se trata de una máquina fuera de dominio con un usuario administrativo local diferente (del que tengo la contraseña).

He intentado usar WNetUseConnection() (que me ha servido bien en el pasado en situaciones donde lo que quería era leer un archivo de disco remoto) antes de llamar a OpenRemoteBaseKey(), pero no hay dados - Obtengo una excepción de acceso denegado .

Claramente, debo pasar las credenciales de otra manera, pero ¿cómo?

Respuesta

32

Lo que he utilizado con éxito para acceder a archivos en un ordenador es el siguiente código:

#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 

Y luego de la firma, en parte, sólo tiene que utilizar:

 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(); 
     } 

Como se puede ver, "Deshacer()" hará que ya no inicie sesión como ese usuario. Entonces no lo use antes de que termine. ¡Pero no te olvides de usarlo!

+2

+1 Esta es realmente la única forma de hacerlo. – Nate

+0

¿Podría mantener la variable "token" durante un tiempo prolongado y luego usar el bloque "using/Undo()" en varios puntos de domesticación utilizando el mismo token? " – JCCyC

+0

Creo que sí. Es el Impersonate el que realmente inicia sesión. Lo que he usado es un "GetImpersonation()" que devuelve un WindowsImpersonationContext como el de arriba –

Cuestiones relacionadas