views:

135

answers:

2

I have created an windows service. I want to open some windows based application from this service.

But my windows service is unable to start desktop applications. To enable the access I had to do the following steps:

  1. Opened the administrative tool "Services"

  2. Right clicked on my service and had to select "properties"

  3. Then in the "Log On" tab, selected "Allow service to interact with desktop".

After that my service can open desired windows based processes.

Can I configure my windows service in the code (C#) to access the desktop so that I won't have to change the access permission manually after installation?

+1  A: 

In .NET you can override the OnCommited method of the service installer class to configure the service to access the desktop. The code will look as follows:

[RunInstaller(true)]
public partial class ProjectInstaller : Installer
{
    private ServiceProcessInstaller serviceProcessInstaller;
    private ServiceInstaller serviceInstaller;

    public ProjectInstaller()
    {
        InitializeComponent();

        // adjust configuration to whatever is needed
        serviceInstaller = new ServiceInstaller();
        serviceInstaller.ServiceName = "My Service";
        serviceInstaller.DisplayName = "My Service";
        serviceInstaller.StartType = ServiceStartMode.Manual;
        this.Installers.Add(serviceInstaller);

        serviceProcessInstaller = new ServiceProcessInstaller();
        serviceProcessInstaller.Account = 
            System.ServiceProcess.ServiceAccount.LocalSystem;
        serviceProcessInstaller.Password = null;
        serviceProcessInstaller.Username = null;
        this.Installers.Add(serviceProcessInstaller);
    }

    protected override void OnCommitted(IDictionary savedState)
    {
        base.OnCommitted(savedState);

        // The following code sets the flag to allow desktop interaction 
        // for the service
        //
        using (RegistryKey ckey = 
            Registry.LocalMachine.OpenSubKey(
                @"SYSTEM\CurrentControlSet\Services\My Service", true))
        {
            if (ckey != null && ckey.GetValue("Type") != null)
            {
                ckey.SetValue("Type", (((int)ckey.GetValue("Type")) | 256));
            }
        }
    }
}
0xA3
Thanks Divo....
Pankaj
Re right / wrong; see "important" here: http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx
Marc Gravell
Thanks Marc Gravell.Nice article and also easy way to implement the requirement. but right now my senior is not allow me to change the structure that's why i am trying to fix this issue.
Pankaj
Now I explain you how my service worked so that you can understand my requirement. My application process the documents.To do this task i am using some 3rd party tool like adobe and Zprint.Some time we get the files which can not handle by these 3rd party tools so my application gone hanged in that condition. What my service do it will monitor the process, If application hanged then service close the application and start again. So here my service intersection with with my application on this way.
Pankaj
+2  A: 

Just... don't. That isn't the job of a service. For this job you should be using a user app (perhaps in their startup) that (if necessary) talks to a service via IPC. I'm believe the plan is to make the UI unavailable from services at some point (Vista onwards? I stopped doing service<=>desktop a long time ago).

For considerations:

  • what if you have multiple users logged in (fast user switching)?
  • what if you have multiple RDP sessions?

What you are proposing only really scales to 1, and possibly not event that if you consider that "session 0" is reserved for admin use on some systems (so the interactive user isn't necessarily on session 0).

Marc Gravell
I don't agree. When automating applications via a service the flag to allow desktop access must be set for certain applications (e.g. when the only way to interact is via clipboard). Surely, scaling might be a problem, but a solution that doesn't scale is often better than no solution at all (as scalability is not always a requirement).
0xA3
Then: don't automate applications via a service. Use an app in the user's session that *talks* to the service. I said this in the answer above. It might be a slightly more *complex* solution, but it is the *right* solution.
Marc Gravell
I wouldn't go as fast as saying that one thing is right and the other wrong. Think about services that use existing applications for doing tasks like automated printing/conversion of documents. Usually you can't make the app (MS Office, OpenOffice, legacy WordPerfect etc) listen to a service. When everything is controlled by your service, you can even create multiple sessions in parallel without the need for an interactive user at all so that it is perfectly suitable to run on a server. Of course command line tools are better suited for such jobs but you simply don't always have the choice.
0xA3
I would: see "important" here: http://msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx
Marc Gravell
But that's about services displaying a user interface. That's another story and obviously is a dont.
0xA3
To make it more clear: If you want to automate e.g. Word from a service (it might not be recommended but it works stable if you handle issues like popups and the like and there is no other option until SharePoint 2010 is out) it actually requires you to set the *Allow service to interact with desktop* option although you would never display an interactive user interface.
0xA3