title: Launch a process under another user's credentials
body: <p>I want to launch a process under another username's credentials. 
  This is what I have now:</p>
  
  <pre><code>        /// &lt;summary&gt;
          /// Do actions under another username's credentials
          /// &lt;/summary&gt;
          /// &lt;param name="username"&gt;Username to inpersonate&lt;/param&gt;
          /// &lt;param name="domain"&gt;Domain/Machine&lt;/param&gt;
          /// &lt;param name="password"&gt;Password &lt;/param&gt;
          public static void Action(string username,string domain, string password )
          {
              try
              {
                  if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref hToken))
                  {
                      if (DuplicateToken(hToken, 2, ref hTokenDuplicate))
                      {
  
                          WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);
  
                          WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();
  
                          // Check the identity but it could do any other action under given username credentials
                        try
                          {
                              ProcessStartInfo info = new ProcessStartInfo("cmd.exe");
                              info.UseShellExecute = false;
                              info.RedirectStandardInput = true;
                              info.RedirectStandardError = true;
                              info.RedirectStandardOutput = true;
                              info.UserName = "dummy"; // see the link mentioned at the top
                              // Define the string value to assign to a new secure string.
                              char[] chars = { 'p', 'a', 's', 's','1','2','3','4','/' };
                              // Instantiate the secure string.
                              SecureString testString = new SecureString();
                              // Assign the character array to the secure string.
                              foreach (char ch in chars)
                                  testString.AppendChar(ch);
  
                              info.Password = testString;
  
                              Process.Start(info);
  
                          }
                          catch (Exception ex)
                          {
                              Console.WriteLine("Exception Occurred :{0},{1}",ex.Message, ex.StackTrace.ToString());
                          }
  
                          // Stop impersonating the user
                          impersonationContext.Undo();
                      }
                  }
                  // Free the tokens
                  if (hToken != IntPtr.Zero) 
                      CloseHandle(hToken);
                  if (hTokenDuplicate != IntPtr.Zero)
                      CloseHandle(hTokenDuplicate);
  
          }catch(Exception ex)
           {
               Console.WriteLine("Exception occurred. " + ex);
            }
  </code></pre>
  
  <p>It does not seem to work and I get an "Access denied". Any ideas of how to do it?
  If we ask for the credentials, we get the right ones, so it should execute any program under that credentials. i.e:</p>
  
  <pre><code>               if (DuplicateToken(hToken, 2, ref hTokenDuplicate))
                      {
  
                          WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate);                      
                          WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate();
  
                          // Check the identity but it could do any other action under given username credentials
                          Console.WriteLine("After impersonation: {0}", WindowsIdentity.GetCurrent().Name);
  
                          // Stop impersonating the user
                          impersonationContext.Undo();
                      }
  </code></pre>
  
  <p>And the answer is right, we get "dummy".</p>
  
  <p>We could make it even simpler:</p>
  
  <pre><code> public static void Run()
          {
              try
              {
                  const string file = "cmd.exe";
  
                  var sspw = new SecureString();
  
                  foreach (var c in "pass1234/")
                      sspw.AppendChar(c);
  
                  var proc = new Process();
  
                  proc.StartInfo.UseShellExecute = false;
  
                  proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(file);
  
                  proc.StartInfo.FileName = Path.GetFileName(file);
  
                  proc.StartInfo.Domain = "WIN08";
                  proc.StartInfo.Arguments = "";
                  proc.StartInfo.UserName = "dummy";
                  proc.StartInfo.Password = sspw;
                  proc.StartInfo.LoadUserProfile = false;
                  proc.Start();
              }catch(Exception e)
              {
                  Console.WriteLine(e);
               }
  </code></pre>
  
  <p>However, I still get exceptions...</p>