2011-01-07 6 views
17

Desidero avviare un processo con diritti di amministratore. Quando eseguo il codice qui sotto il processo si lamenta dicendo che ha bisogno di privilegi di amministratore:Avviare un processo .Net come un altro utente

public class ImpersonationHelper : IDisposable 
{ 
    IntPtr m_tokenHandle = new IntPtr(0); 
    WindowsImpersonationContext m_impersonatedUser; 

    #region Win32 API Declarations 

    const int LOGON32_PROVIDER_DEFAULT = 0; 
    const int LOGON32_LOGON_INTERACTIVE = 2; //This parameter causes LogonUser to create a primary token. 

    [DllImport("advapi32.dll", SetLastError = true)] 
    public static extern bool LogonUser(String lpszUsername, String lpszDomain, String lpszPassword, 
    int dwLogonType, int dwLogonProvider, ref IntPtr phToken); 

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)] 
    public extern static 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 

    /// <summary> 
    /// Constructor. Impersonates the requested user. Impersonation lasts until 
    /// the instance is disposed. 
    /// </summary> 
    public ImpersonationHelper(string domain, string user, string password) 
    { 
     // Call LogonUser to obtain a handle to an access token. 
     bool returnValue = LogonUser(user, domain, password, 
      LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, 
      ref m_tokenHandle); 
     if (false == returnValue) 
     { 
      int ret = Marshal.GetLastWin32Error(); 
      throw new System.ComponentModel.Win32Exception(ret); 
     } 

     // Impersonate 
     m_impersonatedUser = new WindowsIdentity(m_tokenHandle).Impersonate(); 
    } 

    #region IDisposable Pattern 

    /// <summary> 
    /// Revert to original user and cleanup. 
    /// </summary> 
    protected virtual void Dispose(bool disposing) 
    { 
     if (disposing) 
     { 
      // Revert to original user identity 
      if (m_impersonatedUser != null) 
       m_impersonatedUser.Undo(); 
     } 

     // Free the tokens. 
     if (m_tokenHandle != IntPtr.Zero) 
      CloseHandle(m_tokenHandle); 
    } 

    /// <summary> 
    /// Explicit dispose. 
    /// </summary> 
    public void Dispose() 
    { 
     Dispose(true); 
     GC.SuppressFinalize(this); 
    } 

    /// <summary> 
    /// Destructor 
    /// </summary> 
    ~ImpersonationHelper() 
    { 
     Dispose(false); 
    } 

    #endregion 
} 

using (new ImpersonationHelper("xxx.blabla.com", "xxxx", "xxxx")) 
{ 
    if (!string.IsNullOrEmpty(txtFilename.Text)) 
     Process.Start(txtFilename.Text); 
} 

risposta

33

Potete provare qualcosa di simile: Start a new Process as another user

codice di esempio:

System.Diagnostics.Process proc = new System.Diagnostics.Process(); 
System.Security.SecureString ssPwd = new System.Security.SecureString(); 
proc.StartInfo.UseShellExecute = false; 
proc.StartInfo.FileName = "filename"; 
proc.StartInfo.Arguments = "args..."; 
proc.StartInfo.Domain = "domainname"; 
proc.StartInfo.UserName = "username"; 
string password = "user entered password"; 
for (int x = 0; x < password.Length; x++) 
{ 
    ssPwd.AppendChar(password[x]); 
} 
passowrd = ""; 
proc.StartInfo.Password = ssPwd; 
proc.Start(); 
+3

thanx funziona come un fascino –

+2

Cosa c'è in giro UAC - Verb runas? http://stackoverflow.com/questions/13838954/how-start-process-with-admin-rights-in-hide-mode – Kiquenet

+2

ERRATO utilizzo di SecureString. Hai sconfitto lo scopo di tutto memorizzandolo in 'password' – sotn

5

utilizzo corretto del SecureString e un alcuni extra:

//You should use SecureString like the following 
SecureString password = new SecureString(); 
password.AppendChar('p'); 
password.AppendChar('a'); 
password.AppendChar('s'); 
password.AppendChar('s'); 

Process process = new Process(); 
process.StartInfo.UseShellExecute = false; 
//Set the working directory if you don't execute something like calc or iisreset but your own exe in which you want to access some files etc.. 
process.StartInfo.WorkingDirectory = "workingDirectory"; 
//Full path (e.g. it can be @"C:\Windows\System32\iisreset.exe" OR you can use only file name if the path is included in Environment Variables..) 
process.StartInfo.FileName = @"fileName"; 
process.StartInfo.Domain = "domain"; 
process.StartInfo.UserName = "userName"; 
process.StartInfo.Password = password; 
process.Start(); 

EDIT: Non so perché questa risposta è votata sotto 0, forse è necessaria una spiegazione in più. Se lo utilizzerai in un ambiente non interattivo (come un'applicazione web) e desideri eseguire un processo con un utente, avrai a disposizione alcune opzioni per utilizzare la password dell'utente. Puoi leggere la password da una memoria o dal codice. Un modo migliore; puoi archiviarlo crittografato. Tuttavia, se si prevede di utilizzarlo in forma semplice (forse temporaneamente o solo per testare qualcosa ecc.), È possibile utilizzare SecureString in un modo che ho descritto. La risposta accettata non utilizza SecureString in modo corretto. Leggere la password in una stringa dalla console e quindi inserirla in un SecureString è semplicemente ERRATA. La risposta accettata NON protegge quella stringa o qualcosa ma la tradisce solo. Questa è stata la motivazione principale per me per aggiungere questa risposta. Controllare link.

+3

Non sei sicuro di quanto sia intelligente la password hardcode nel codice. Se non è codificato a macchina, da dove viene preso? In che modo differisce dal mio esempio? – HABJAN

+1

wow, la risposta sbagliata richiede 25 colpi mentre quella corretta diventa -1 :). non va bene .. Ecco un po 'più di spiegazione; SecureString è usato per codificare questo tipo di cose (in un mondo ottimale, non dovresti memorizzare le password nel codice sì ma se devi almeno farlo nel modo giusto). Il tuo utilizzo di SecureString era sbagliato ed è per questo che ho aggiunto questa risposta (perché non hai modificato la tua domanda (nel modo giusto) per risolvere anche questo ..) – sotn

+2

il mio esempio era solo un POC. Non capisco perché stai facendo un grosso problema. Qualunque sia il modo in cui hardcode la tua password (stringa o char in char), può essere facilmente letta anche dai binari e dalla memoria decompilati. A un certo punto, quando il codice viene eseguito in memoria, fornisce istruzioni su cosa aggiungere a SecureString.È possibile inserire facilmente un punto di interruzione in WinDbg e leggere ciò che è passato. La mia stringa verrà raccolta e non verrà tracciata. Anche i caratteri sono in memoria, è solo più difficile metterli insieme. Saranno raccolti anche in seguito. – HABJAN