2011-01-07 19 views
17

Chcę rozpocząć proces z uprawnieniami administratora. Kiedy uruchomić poniższy kod Procesu narzeka mówiąc, że potrzebuje uprawnień administratora:Rozpocznij proces .Net jako inny użytkownik

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

Odpowiedz

33

można spróbować coś takiego: próbka Start a new Process as another user

Kod:

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 działa jak zaklęcie –

+2

Co się dzieje z UAC - czasownik runas? http://stackoverflow.com/questions/13838954/how-start-process-with-admin-rights-in-hide-mode – Kiquenet

+2

Nieprawidłowe użycie SecureString. Pokonałeś go w tym celu, zapisując go w 'password' – sotn

5

Poprawne użycie SecureString oraz kilka dodatków:

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

EDYCJA: Nie wiem, dlaczego ta odpowiedź jest głosowana poniżej 0, może potrzebne jest trochę więcej wyjaśnień. Jeśli użyjesz tego w nieinteraktywnym środowisku (takim jak aplikacja internetowa) i chcesz uruchomić proces z użytkownikiem, masz kilka opcji użycia hasła użytkownika. Możesz odczytać hasło z pamięci lub kodu. Lepszy sposób; możesz przechowywać to zaszyfrowane. Jeśli jednak planujesz użyć go w formie prostej (może tymczasowo lub po prostu do przetestowania czegoś itp.), Możesz użyć metody SecureString w sposób opisany przeze mnie. Przyjęta odpowiedź nie używa w odpowiedni sposób SecureString. Odczytywanie hasła na ciąg z konsoli, a następnie umieszczanie go w SecureString jest po prostu NIEPRAWIDŁOWE. Przyjęta odpowiedź NIE zabezpiecza tego ciągu lub czegoś, ale tylko oszukuje. To była główna motywacja do dodania tej odpowiedzi. Sprawdź link.

+3

Nie wiem, jak inteligentne jest kodowanie hasłem w kodzie. Jeśli nie jest na sztywno, skąd go masz? Czym różni się to od mojego przykładu? – HABJAN

+1

wow, zła odpowiedź trwa 25 trafień podczas gdy prawidłowa dostaje -1 :). nie dobrze .. Oto trochę więcej wyjaśnień; SecureString służy do hardcode tego rodzaju rzeczy (w optymalnym świata, nie należy przechowywać haseł rzeczy w kodzie tak, ale jeśli trzeba przynajmniej robić to dobrze.). Używanie SecureString było błędne i dlatego dodałem tę odpowiedź (ponieważ nie poprawiłeś swojego pytania (we właściwy sposób), aby to naprawić). – sotn

+2

mój przykład był po prostu POC. Nie rozumiem, dlaczego robisz z tego tak wielką sprawę. Niezależnie od tego, w jaki sposób hardcode swoje hasło (ciąg lub char przez char) można łatwo odczytać z dekompilowanych plików binarnych i pamięci. W pewnym momencie, kiedy twój kod działa w pamięci, daje instrukcje, co dodać do SecureString.Możesz łatwo umieścić punkt przerwania w WinDbg i przeczytać, co zostało przekazane. Mój ciąg będzie w końcu zbiorem śmieci i nie będzie na nim śladu. Znaki są również w pamięci, trudniej je połączyć. Będą także śmieciami zbieranymi później. – HABJAN

Powiązane problemy