title: C#: Start process as the "real" administrator with hard coded privileges
body: <p>I need to install different setups silently with administrator privileges.
  I have to hard code the privileges because the users don´t know username and password to install the setups themselfes.</p>
  
  <p>I have tried two different approaches.</p>
  
  <ol>
  <li>ProcessStartInfo with UserName, Password and UseShellExecute = false.</li>
  <li><p>User Impersonation with</p>
  
  <pre><code>[DllImport("advapi32.dll", SetLastError = true)]
  private static extern bool LogonUser(...);
  </code></pre></li>
  </ol>
  
  <p>In both scenarios <code>windowsPrincipal.IsInRole(WindowsBuiltInRole.Administrator)</code> returns false
  and my setups do not run because of insufficient rights.</p>
  
  <p>Strange behavior: LogonUser always returns true, even with invalid credentials.</p>
  
  <p>Here is the impersonation class:</p>
  
  <pre><code>namespace BlackBlade.Utilities
  {
      /// &lt;summary&gt;
      /// Quelle: http://www.blackbladeinc.com/en-us/community/blogs/archive/2009/08/10/runas-in-c.aspx
      /// &lt;/summary&gt;
      public class SecurityUtilities
      {
          [DllImport("advapi32.dll", SetLastError = true)]
          private static extern bool LogonUser(string lpszUserName, string lpszDomain, string lpszPassword, int dwLogonType, int dwLogonProvider, out IntPtr phToken);
  
          public delegate void RunAsDelegate();
  
          public static void RunAs(RunAsDelegate methodToRunAs, string username, string password)
          {
              string userName;
  
              string domain;
              if (username.IndexOf('\\') &gt; 0)
              {
                  //a domain name was supplied
                  string[] usernameArray = username.Split('\\');
                  userName = usernameArray[1];
                  domain = usernameArray[0];
              }
              else
              {
                  //there was no domain name supplied
                  userName = username;
                  domain = ".";
              }
              RunAs(methodToRunAs, userName, password, domain);
          }
  
          public static void RunAs(RunAsDelegate methodToRunAs, string username, string password, string domain)
          {
              IntPtr userToken;
              WindowsIdentity adminIdentity = null;
              WindowsImpersonationContext adminImpersonationContext = null;
  
              try
              {
                  if (LogonUser(username, string.IsNullOrEmpty(domain) ? "." : domain, password, 9, 0, out userToken))
                  {
                      //the impersonation suceeded
                      adminIdentity = new WindowsIdentity(userToken);
                      adminImpersonationContext = adminIdentity.Impersonate();
  
                      // todo: Entfernen.
                      WindowsPrincipal p = new WindowsPrincipal(adminIdentity);
                      MessageBox.Show(p.IsInRole(WindowsBuiltInRole.Administrator).ToString());
  
                      //run the delegate method
                      //methodToRunAs();
                  }
                  else
                      throw new Exception(string.Format("Could not impersonate user {0} in domain {1} with the specified password.", username, domain));
              }
              catch (Exception se)
              {
                  int ret = Marshal.GetLastWin32Error();
                  if (adminImpersonationContext != null)
                      adminImpersonationContext.Undo();
                  throw new Exception("Error code: " + ret.ToString(), se);
              }
              finally
              {
                  //revert to self
                  if (adminImpersonationContext != null)
                      adminImpersonationContext.Undo();
              }
          }
      }
  }
  </code></pre>