Link to home
Start Free TrialLog in
Avatar of depaa
depaa

asked on

Cannot start [service name] service from computer '.'. Access Denied

Hello All,
 I have a Windows Service(of Account- LocalSystem) which has to be started from a VB.NET Windows Application whose UAC level is set to "asInvoker". If i start the Service manually it works. If i launch the Windows Application through - launch option from Finish Dialog of Setup Installation Process(Run As Administrator)  also starts the Service.. But by programmatically, using mySPCObject.Start()  - throws an Error "Cannot start [service name] service from computer '.'. Access Denied."

Looks like Sufficient privilege is not there for that user..? If so how do i set the access rights programmatically to start the service ?

Any help appreciated...


Avatar of Deathrace
Deathrace
Flag of India image

You have to run the same code with admin previleges by using Impersonation concept.

try this
http://www.dotnetspider.com/resources/38277-Impersonation-prgrammatically.aspx
the above post help you to understand impersonation , use the same concept for you code
This code is C#, but you should be able to find a good VB.NET converter out there somewhere.   It also looks like I left some unnecessary references at the top.  I don't think the System.Web stuff is necessary.

using System;
using System.Data;
using System.Configuration;
using System.Web;
using System.Web.Security;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using System.Web.UI.HtmlControls;
using System.Security.Principal;
using System.Runtime.InteropServices;

/// <summary>
/// Summary description for Impersonator
/// </summary>
public class Impersonator : IDisposable
{
    private WindowsImpersonationContext impersonationContext;

    #region Dll Import Declarations

    public const int LOGON32_LOGON_INTERACTIVE = 2;
    public const int LOGON32_PROVIDER_DEFAULT = 0;

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

    #endregion

    public Impersonator(string userId, string password, string domain)
	{
        if (!impersonateValidUser(userId, domain, password)) {
            //throw new Exception("User impersonation failed for user: '" + userId + "'.");
            uint errorCode = WinSystem.GetLastError();
            throw new ApplicationException("User impersonation failed for user: '" + userId + "'.  " +
                                           WinSystem.GetMessage((int)errorCode));
        }
	}

    #region IDisposable Members

    void IDisposable.Dispose() {
        undoImpersonation();
    }

    #endregion

    private bool impersonateValidUser(string userName, string domain, string password) {
        WindowsIdentity tempWindowsIdentity;
        IntPtr token = IntPtr.Zero;
        IntPtr tokenDuplicate = IntPtr.Zero;

        if (RevertToSelf()) {
            if (LogonUserA(userName, domain, password, 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;
    }
    private void undoImpersonation() {
        impersonationContext.Undo();
    }

}

Open in new window


Once you get this converted and compiling, use the following to impersonate the user with appropriate authorizations:
using (new Impersonator(userId, pw, domain)) {
   // start the service here...
}

Open in new window

Avatar of nffvrxqgrcfqvvc
nffvrxqgrcfqvvc

Impersonation won't work with UAC enabled because you will just pickup the *user end of the split token.

1) Create a seperate executable manifested with requireAdministrator and add your service code inside this process.
2) Create elevated COM object for your main application (alot of work but the best option)
3) Create another service that runs under LocalSystem that manages all your work services this should be installed during setup. You can send commands to the service and have the service itself do the work.
Avatar of depaa

ASKER

thanks for all your replies.. I am busy with some other work, will get back soon
Avatar of depaa

ASKER

Hello All,

Excuse me for my ignorance, if any. I have tried impersonator. Did not work. What eql1044 had asked s really a bit too much work to make things slow.

What I did not mention clearly in my earlier question/comment is that - this code has to work with a product and will have to work when installed on users machine - first of all - the user may use any OS - XP / Vista / Win7 / Windows 2003 Server or Windows 2008 Server - with any version, any bit - 32 / 64 - but, my product should work fine.

The user is free to enable firewall, UAC, anti-virus - s/he should be totally free to anything s/he likes.

Given this new situation - please advise.

Regards
Avatar of depaa

ASKER

Hi

I have done all these.

Once again - I want to clarify that - the "Service" is to be started from a VB.NET windows application which was installed (Setup.exe) as "Admin" but, when it runs - it runs as "User"

The installer (setup.exe ) is supposed to Install the service on the user machine.

The VB.Net application is supposed to start the Windows service. Since this VB.Net application starts as "user" - it is not able to start the service which needs to be started as "admin"

Any help will be highly appreciated.

Thanks
Depaa
www.goace.com 
>Since this VB.Net application starts as "user" - it is not able to start the service which needs to be started as "admin"

And the solution for this is to request admin elevation before starting the service which is what was suggested.
Avatar of depaa

ASKER

I understand your frustration with my understanding..

But, if the application which start as "User" by common windows user, asks for an elevation as "Admin" - every time the user start this application - they have to call the administrator - which is not practical.

The service is a License watchdog without the knowledge of the user.

Is it possible to install the service ( install time - the administrator installs - so elevation is not an issue) in such a way that whenever it is invoked by the application which is started as "User", the service should be started as "Admin" ? That is the main question..
ASKER CERTIFIED SOLUTION
Avatar of Nasir Razzaq
Nasir Razzaq
Flag of United Kingdom of Great Britain and Northern Ireland image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of depaa

ASKER

I will try this on 9th or10th Jan and will get back to you.
Thanks
Avatar of depaa

ASKER

Thanks