2010-03-29 14 views
13

This .NET API funziona bene se sto cercando di aprire il Registro di sistema in una macchina che è nello stesso dominio come lo sono io (e il mio utente connesso dispone dei diritti di amministratore sul computer di destinazione).Come si trasmettono le credenziali a una macchina in modo da poter utilizzare Microsoft.Win32.RegistryKey.OpenRemoteBaseKey() su di essa?

Diventa difficile se si tratta di una macchina fuori-di-dominio con un altro utente, locali amministrativi (di cui io ho la password).

Ho provato a utilizzare WNetUseConnection() (che mi ha servito molto bene in passato in situazioni in cui quello che volevo era leggere un file del disco remoto) prima di chiamare OpenRemoteBaseKey(), ma nessun dado - Ricevo un'eccezione di accesso negata .

Chiaramente, devo passare le credenziali in qualche altro modo, ma come?

risposta

32

Quello che ho usato con successo per accedere ai file su un computer è il seguente codice:

#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 

E poi per la firma in parte, basta usare:

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

Come si può vedere, "Undo()" farà in modo che tu non sia più registrato come quell'utente. Quindi non usarlo prima che tu abbia finito. Ma non dimenticare di usarlo!

+2

+1 Questo è davvero l'unico modo per farlo. – Nate

+0

Potrei tenere la variabile "token" intorno a un lungo periodo di tempo, e quindi utilizzare il "/ Annulla() utilizzando" blocco in vari punti nel domare utilizzando lo stesso motivo?" – JCCyC

+0

Credo di sì. E 'la Rappresenta che effettivamente segni. Quello che ho usato è un "GetImpersonation()" che restituisce un WindowsImpersonationContext come sopra –