从Windows服务启动浏览器

时间:2013-03-24 06:30:23

标签: c# .net windows windows-services

我对微软世界有点新意。我已经阅读了this回答和许多其他链接,我知道在Vista之后,Windows服务无法与桌面交互。

然而,我有一种紧急情况,我必须快速找到解决方法。我需要我的Windows服务以某种方式打开一个带有URL的浏览器(任何类型的丑陋黑客现在都会这样做)。 答案说明:

  

您需要编写一个单独的代理应用程序,该应用程序将在用户登录时自动启动,并与您的服务进行通信。然后,代理可以启动浏览器或执行您需要的任何其他操作。

有人可以向我解释如何以简单的方式做到这一点吗?该服务如何与这个“代理人”交谈?这个“代理人”究竟是什么?

任何链接或建议都将受到高度赞赏。

编辑:目前。我的服务尝试运行以下代码:System.Diagnostics.Process.Start("www.google.com");

,我后来发现,它不起作用

4 个答案:

答案 0 :(得分:4)

我担心没有“快捷方式”这样做。 (并且由于该服务无法与用户的桌面交互,即使它可以启动浏览器,用户也无法看到它。)

您提到的“代理应用程序”是一个完全独立的应用程序,它在登录时在用户桌面下运行。它必须使用一些进程间通信方法(命名管道,TCP / IP等)与服务进行通信。

服务不与桌面交互的原因是出于安全考虑。没有“快速解决方法”可用,也不应该有。也没有“简单的方法”来规避这种变化(同样,不应该 - 如果你能以简单的方式绕过安全,那就没有太大的安全性了。)

答案 1 :(得分:4)

是的,从服务中你可以在桌面上运行代码......问题出在桌面上?因为可能会同时记录各种用户(例如,在Windows Server中可能会有远程登录的各种用户)。

如果在示例中使用来自服务的Process.Start

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

该程序不会出现在任何用户的桌面上,因为该服务与用户的任何桌面都没有关联。


解决方案是检测哪个用户在本地登录,然后以该用户(并在该用户的权限下)执行该程序。为此,我想将您链接到another of my answers,在那里我将演示如何从服务中调用程序。 that answer中,我展示了此技术所需的代码

注意:答案是关于屏幕截图,我描述的技术仍然是在用户的会话中调用程序,并且该方法适用于服务。所以它适用于你的问题。

您可以使用此方法直接执行所需的浏览器。作为替代方案,您可以使用它来调用服务可执行文件,您可以使用System.Environment.UserInteractive来检测可执行文件是否未作为服务运行。如果您将url作为执行参数传递给服务可执行文件,那么您可以使用Process.Start使用默认浏览器将其打开,就像上面的示例一样。

注意:代码在Windows 7上进行了测试。

答案 2 :(得分:2)

使用shellexecute使用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.

答案 3 :(得分:1)

如果你需要紧急的东西 - 我会尝试从服务中将消息放入MSMQ,并编写一个等待队列消息的简单客户端,然后继续它们。
更新
实际上,如果你需要一些非常快的东西 - 你甚至可以写一些文件,并编写简单的桌面(winforms?)应用程序来读取池中的这个文件(每5秒?),并在需要时打开浏览器。