I want to start a Process with Admin rights. When I run the code below the Process complains saying it needs Admin rights:
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);
}
Correct usage of SecureString and a few extras:
EDIT: I don't know why this answer is voted below 0, maybe a little more explanation is needed. If you'll use this in non-interactive environment (like a web application) and you want to run a process with a user, then you have a few options to use the user's password. You can either read password from a storage or from code. A better way; you can store it encrypted. However, if you plan to use it in plain form (maybe temporarily or just to test something etc.), you can use
SecureString
in a way I described. The accepted answer doesn't useSecureString
in a right way. Reading password into a string from console and then putting it into aSecureString
is simply WRONG. The accepted answer does NOT secure that string or something but only cheating it. That was the main motivation for me to add this answer. Check link.Can you try something like this: Start a new Process as another user
Code sample: