5

I have this following simple service program:

using System.Diagnostics;
using System.ServiceProcess;

namespace BasicService
{
    public partial class Service1 : ServiceBase
    {
        public Service1()
        {
            InitializeComponent();
        }

        protected override void OnStart(string[] args)
        {
            ProcessStartInfo processStartInfo = new ProcessStartInfo
                                                    {
                                                        Verb = "runas",
                                                        UserName = "jdoe",
                                                        Password = "XXXXXXX".ConvertToSecureString(),
                                                        Domain = "abc.com",
                                                        UseShellExecute =false,
                                                        FileName = "notepad.exe"
                                                    };
            Process.Start(processStartInfo);
        }

        protected override void OnStop()
        {
        }
    }
}

And I'm using this as my service installer:

using System.ComponentModel;
using System.Configuration.Install;
using System.ServiceProcess;

namespace BasicService
{
    [RunInstaller(true)]
    public class ProjectInstaller : Installer
    {
        private readonly ServiceProcessInstaller _process;
        private readonly ServiceInstaller _service;

        public ProjectInstaller()
        {
            _process = new ServiceProcessInstaller {Account = ServiceAccount.LocalSystem};
            _service = new ServiceInstaller
                           {
                               ServiceName = "BasicService",
                               Description = "Just a testing service.",
                               StartType = ServiceStartMode.Automatic,
                           };

            Installers.Add(_process);
            Installers.Add(_service);
        }
    }
}

If I run this service without a verb, username, password, domain and useshellexecute specified, everything runs just dandy. As soon as I specify these values as seen above, I get the following:

Service cannot be started. System.ComponentModel.Win32Exception (0x80004005): Access is denied at System.Diagnostics.Process.StartWithCreateProcess(ProcessStartInfo startInfo) at System.Diagnostics.Process.Start() at System.Diagnostics.Process.Start(ProcessStartInfo startInfo) at BasicService.Service1.OnStart(String[] args) in C:\BasicService\BasicService\Service1.cs:line 24 at System.ServiceProcess.ServiceBase.ServiceQueuedMainCallback(Object state)

Any ideas?

ymerej
  • 727
  • 1
  • 8
  • 21

1 Answers1

3

Since Windows Vista, services cannot simply display ui or interact with a user.
http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx

Thus, to run a GUI app from your service, you'll need to use CreateProcessAsUser, which is not directly available in .NET. So you'll have to rely on Pinvoke, somewhat similar as it is described here

http://blogs.msdn.com/b/alejacma/archive/2007/12/20/how-to-call-createprocesswithlogonw-createprocessasuser-in-net.aspx

user1234883
  • 1,675
  • 10
  • 18
  • Are you sure? Services can no longer interact with the user from a service account, but I don't know how Windows could know that `notepad.exe` is interactive unless it actually ran it. In which case, the process would have to be started. – ta.speot.is Feb 27 '12 at 08:24
  • 1
    @ta.speot.is - yes, I strongly believe that CreateProcessAsUser is the right way to create user visible GUI apps from service. What exactly causes "Access is denied" above, I am not sure, but from the call stack you see that Windows actually runs it. How Windows knows... probably by inspecting Entry-Point Symbol set by '/SUBSYSTEM' VS switch. – user1234883 Feb 27 '12 at 10:07
  • 2
    AFAIK this was the only way I was able to do it. I had to combine CreateProcessAsUser and LogonUser to get this to work properly. – ymerej Feb 29 '12 at 18:56
  • @user1234883, Process.Execute take A ProcessStartInfo which has a UserName and a Password as properties. Why it wouldn't work? – Eric Ouellet Jan 30 '17 at 18:10