2011-01-07 22 views
17

Deseo iniciar un proceso con derechos de administrador. Cuando ejecuto el código debajo de la apófisis se queja diciendo que necesita derechos de administrador:Iniciar un proceso .Net como un usuario diferente

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

Respuesta

33

Se puede tratar algo como esto: muestra Start a new Process as another user

Código:

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 funciona como un encanto –

+2

¿Qué hay de UAC - Verb runas? http://stackoverflow.com/questions/13838954/how-start-process-with-admin-rights-in-hide-mode – Kiquenet

+2

Uso INCORRECTO de SecureString. Derrotaste todo el propósito de ello al guardarlo en 'password' – sotn

5

El uso correcto de SecureString y una algunos extras:

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

EDITAR: No sé por qué esta respuesta se vota por debajo de 0, tal vez se necesita un poco más de explicación. Si va a usar esto en un entorno no interactivo (como una aplicación web) y desea ejecutar un proceso con un usuario, entonces tiene algunas opciones para usar la contraseña del usuario. Puede leer la contraseña desde un almacenamiento o desde el código. Una mejor manera; puedes almacenarlo encriptado Sin embargo, si planea usarlo en forma simple (quizás temporalmente o simplemente para probar algo, etc.), puede usar SecureString de la manera que describí. La respuesta aceptada no usa SecureString de una manera correcta. Leer la contraseña en una cadena desde la consola y ponerla en un SecureString es simplemente INCORRECTO. La respuesta aceptada NO asegura esa cadena o algo, sino que solo lo engaña. Esa fue la principal motivación para agregar esta respuesta. Compruebe link.

+3

No estoy seguro de qué tan inteligente es codificar la contraseña en el código. Si no está codificado, ¿de dónde lo obtienes? ¿Cómo esto difiere de mi ejemplo? – HABJAN

+1

guau, la respuesta incorrecta toma 25 visitas mientras que la correcta obtiene -1 :). no es bueno ... Aquí hay un poco más de explicación; SecureString se utiliza para codificar este tipo de cosas (en un mundo óptimo, no debe almacenar cosas de contraseña en el código, sí, pero si necesita al menos hacerlo bien). Su uso de SecureString fue incorrecto y es por eso que agregué esta respuesta (porque no editó su pregunta (de manera correcta) para arreglarla también ...) – sotn

+2

mi ejemplo era solo un POC. No entiendo por qué estás haciendo una gran cosa con eso. Independientemente de la forma en que codifique su contraseña (cadena o char por char), también se puede leer fácilmente desde los binarios descompilados y la memoria. En cierto punto, cuando su código se ejecuta en la memoria, le da instrucciones sobre qué adjuntar a SecureString.Puede poner fácilmente un punto de interrupción en WinDbg y leer lo que pasó. Mi cadena finalmente será recogida de basura y no habrá rastro de ella. Tus caracteres también están en la memoria, es más difícil juntarlos. Serán recogidos también más tarde. – HABJAN

Cuestiones relacionadas