简体   繁体   中英

Start browser from Windows service

I am a little new to the Microsoft world. I have read this answer and many other links and I'm aware that after Vista, it is not possible for windows service to interact with desktop.

However, I have kind of an emergency where I have to find a workaround quick. I need my windows service to somehow open a browser with a URL (any kind of an ugly hack will do for now). The answer states :

you need to write a separate agent application, which will be automatically started on user login, and with which your service will communicate. Then the agent can start the browser or do whatever else you need.

Can someone please explain to me how I could do this in a simple way? How would that service talk to this 'agent'? What is this 'agent' exactly?

Any links or suggestions would be highly appreciated.

EDIT: Currently. my service tries to run the following code: System.Diagnostics.Process.Start("www.google.com");

which, I found out later, does not work

There is no "quick way" to do this, I'm afraid. (And since the service can't interact with the user's desktop, even if it could launch the browser the user couldn't see it anyway.)

The "agent application" you've mentioned is a totally separate application which runs under the user's desktop on login. It would have to use some method of inter-process communication (named pipes, TCP/IP, etc.) to communicate with the service.

The reason that services don't interact with the desktop is for reasons of security. There's no "quick workaround" available, and there shouldn't be one. There's also no "simple way" to circumvent that change (and again, there shouldn't be - if you can bypass security in a simple way, it's not much security).

Yes, from a service you can run code on the desktop... The matter is on which desktop? because there may be various users logged at the same time (for example in a Windows Server there may be various users logged remotely).

If use Process.Start from a service as in your example:

System.Diagnostics.Process.Start("www.google.com");

The program will not appear in the desktop of any user, because the service is not associated with any of the desktops of the users.


The solution is to detect which user is logged locally and then execute the program as that user (and under the privileges of that user). For that I want to link you to another of my answers where I demonstrate how to invoke a program from a service. In that answer I present the code needed for this technique .

Note : That answer was about an screen capture, still the technique I describe is to call a program in the session of an user, and that method works from a service. So it applies to your problem.

You can use this method to execute the desired browser directly. As an alternative you can use it to invoke your service executable, where you can use System.Environment.UserInteractive to detect if the executable is not running as a service or not. If you pass the url as execution argument to your service executable then you can open it with the default browser using Process.Start just like your example above.

Note : The code was tested on Windows 7.

use shellexecute using pinvoke http://www.pinvoke.net/default.aspx/shell32.shellexecute

C# Signature:
public enum ShowCommands : int
{
    SW_HIDE         = 0,
    SW_SHOWNORMAL       = 1,
    SW_NORMAL       = 1,
    SW_SHOWMINIMIZED    = 2,
    SW_SHOWMAXIMIZED    = 3,
    SW_MAXIMIZE     = 3,
    SW_SHOWNOACTIVATE   = 4,
    SW_SHOW         = 5,
    SW_MINIMIZE     = 6,
    SW_SHOWMINNOACTIVE  = 7,
    SW_SHOWNA       = 8,
    SW_RESTORE      = 9,
    SW_SHOWDEFAULT      = 10,
    SW_FORCEMINIMIZE    = 11,
    SW_MAX          = 11
}

[DllImport("shell32.dll")]
static extern IntPtr ShellExecute(
IntPtr hwnd,
string lpOperation,
string lpFile,
string lpParameters,
string lpDirectory,
ShowCommands nShowCmd);





 // Asks default mail client to send an email to the specified address.
    ShellExecute( IntPtr.Zero, "open", "mailto:support@microsoft.com", "", "", ShowCommands.SW_SHOWNOACTIVATE    );

    // Asks default browser to visit the specified site.
    ShellExecute( IntPtr.Zero, "open", "http://channel9.msdn.com", "", "", ShowCommands.SW_SHOWNOACTIVATE );

    // Opens default HTML editing app to allow for edit of specified file
    ShellExecute( IntPtr.Zero, "edit", @"c:\file.html", "", "", ShowCommands.SW_SHOWNOACTIVATE );
   //Modified by Aljaz: Replaced the last zero in these calls with 4  otherwise it wouldn't show anything
   // 0 stands for SW_HIDE contant, which means execute but don't show the window which is probably not 
   // what we want.

If you need something urgent - I'd try to put message into MSMQ from the service, and write some simple client that is waiting for queue messages, and proceed them.
Update:
Actually, if you need something very quick - you can even write to some file, and write simple desktop (winforms?) application to read this file in pool (each 5 sec?), and open browser when required.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM