title: Starting a service in ASP.NET/C# with the right permissions
body: <p>on my website (written in ASP.NET/C#) I want the moderaters to be able to start a certain service. The code I have for this is:</p>
  
  <pre><code>    ServiceController svcController = new ServiceController("InvidualFileConversion");
  
      if (svcController != null)
      {
          try
          {
              svcController.Stop();
              svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
              svcController.Start();
          }
          catch (Exception ex)
          {
              // error
          }
      }
  </code></pre>
  
  <p>Now when I run this I get the error "Cannot open InvidualFileConversion service on computer", with the additional message: "Acces is denied".</p>
  
  <p>I know this is a problem with permissions, but <strong>how do I give myself the proper permissions?</strong>
  Don't come with the answer where I should write: , cause I have tried it and it didn't work. Also I think that is not really the best way to set this up for the whole website when I just need it for these few lines of code.</p>
  
  <p><strong>EDIT:</strong> I've added this in my code and it still doesn't work, I get the same exception at the same place. Now it looks like this:</p>
  
  <pre><code>protected void ConvertLink_OnClick(object sender, EventArgs e)
  {
      //convert();
      try
      {
          //--need to impersonate with the user having appropriate rights to start the service
          Impersonate objImpersonate = new Impersonate(domainName, userName, userPassword);
          if (objImpersonate.impersonateValidUser())
          {
              //--write code to start/stop the window service
              startWindowsService();
              objImpersonate.undoImpersonation();
          }
      }
      catch (Exception Ex)
      { Response.Write(Ex.Message + Ex.InnerException.Message); }
  }
  
  private void startWindowsService()
  {
      ServiceController svcController = new ServiceController("InvidualFileConversion");
  
      if (svcController != null)
      {
          try
          {
              svcController.Stop();
              svcController.WaitForStatus(ServiceControllerStatus.Stopped, TimeSpan.FromSeconds(10));
              svcController.Start();
          }
          catch (Exception ex)
          {
              // error
          }
      }
  }
  </code></pre>
  
  <p>I have a Impersonate class that looks like this:</p>
  
  <pre><code>using System;
  using System.Data;
  using System.Configuration;
  using System.Linq;
  using System.Web;
  using System.Web.Security;
  using System.Web.UI;
  using System.Web.UI.HtmlControls;
  using System.Web.UI.WebControls;
  using System.Web.UI.WebControls.WebParts;
  using System.Xml.Linq;
  using System.Collections.Generic;
  using System.Security.Principal;
  using System.Runtime.InteropServices;
  
  /// &lt;summary&gt;
  /// Summary description for Impersonate
  /// &lt;/summary&gt;
  public class Impersonate
  {
  
  #region "Class Members"
  public const int LOGON32_LOGON_INTERACTIVE = 2;
  public const int LOGON32_PROVIDER_DEFAULT = 0;
  WindowsImpersonationContext impersonationContext;
  #endregion
  
  #region "Class Properties"
  public string domainName { get; set; }
  public string userName { get; set; }
  public string userPassword { get; set; }
  #endregion
  
  public Impersonate()
  {
      //
      // TODO: Add constructor logic here
      //
  }
  public Impersonate(string domainName, string userName, string userPassword)
  {
      this.domainName = domainName;
      this.userName = userName;
      this.userPassword = userPassword;
  }
  
  #region "Impersonation Code"
  [DllImport("advapi32.dll")]
  public static extern int LogonUserA(String lpszUserName,
      String lpszDomain,
      String lpszPassword,
      int dwLogonType,
      int dwLogonProvider,
      ref IntPtr phToken);
  
  [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  public static extern int DuplicateToken(IntPtr hToken,
      int impersonationLevel,
      ref IntPtr hNewToken);
  
  [DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
  public static extern bool RevertToSelf();
  
  [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
  public static extern bool CloseHandle(IntPtr handle);
  public bool impersonateValidUser()
  {
      WindowsIdentity tempWindowsIdentity;
      IntPtr token = IntPtr.Zero;
      IntPtr tokenDuplicate = IntPtr.Zero;
  
      if (RevertToSelf())
      {
          if (LogonUserA(this.userName, this.domainName, this.userPassword, LOGON32_LOGON_INTERACTIVE,
              LOGON32_PROVIDER_DEFAULT, ref token) != 0)
          {
              if (DuplicateToken(token, 2, ref tokenDuplicate) != 0)
              {
                  tempWindowsIdentity = new WindowsIdentity(tokenDuplicate);
                  impersonationContext = tempWindowsIdentity.Impersonate();
                  if (impersonationContext != null)
                  {
                      CloseHandle(token);
                      CloseHandle(tokenDuplicate);
                      return true;
                  }
              }
          }
      }
      if (token != IntPtr.Zero)
          CloseHandle(token);
      if (tokenDuplicate != IntPtr.Zero)
          CloseHandle(tokenDuplicate);
      return false;
  }
  
  public void undoImpersonation()
  {
      impersonationContext.Undo();
  }
  #endregion
  }
  </code></pre>
  
  <p>So the validation thing works but doesn't solve my problem.. I guess there is still the problem with the permissions.. What do I do to change this?</p>
  
  <p><strong>EDIT 2:</strong> The next steps I took involve this:</p>
  
  <ol>
  <li>Creating a app pool where the identity is set to a user (which is member of an administrator group).</li>
  <li>Set the service "log on" to the same user.</li>
  <li>After running the web app again, it still fails..</li>
  </ol>
  
  <p><em>However</em> If I put in the Administrator account as credentials in the code, it works.. (Even though I did not use the Administrator in the App Pool and on the service...)</p>
  
  <p>In other words, I can get what I want with the Administrator account, but not with an account I created myself and has the admin rights. I still want to make this work with a user I made myself as I think it is not so safe to put your Administrator credentials available.</p>
  
  <p>On a sidenote, on the server which I work on I have an account that has administrator privileges but is not the 'Administrator'-account.</p>
  
  <p><strong>EDIT 3:</strong> This is getting weird. I seems to work now BUT:
   - without the Impersonation method (it did not work).
   - I just did what Rob said. I have my own application pool with a user I defined. The windows service has that user specified as well. (The user received Log On As Service right)
   - With this, it seems to work.
   - But if debug through my website I still get acces denied. But if just acces my website through the browser and its ip I can start the service.</p>
  
  <p>To sum it up:
   - Impersonation method doesn't work.
   - Just using a self created app pool with the currect user works if the service has the user also specified. But it doesn't work in debug mode (still Acces Denied there).</p>
  
  <p>This post is getting to big and I wonder if any still really reads it.. But maybe still someone can provide me with any details? I'm afraid it will fail again somewhere in the future..</p>
  
  <p>Any comment will be appreciated!
  Floris</p>