2

我对微软世界有点陌生。我已阅读答案和许多其他链接,并且我知道在 Vista 之后,Windows 服务无法与桌面交互。

但是,我有一种紧急情况,我必须快速找到解决方法。我需要我的 Windows 服务以某种方式打开一个带有 URL 的浏览器(现在任何一种丑陋的 hack 都可以)。答案是:

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

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

任何链接或建议将不胜感激。

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

我后来发现,这不起作用

4

4 回答 4

5

是的,您可以通过一项服务在桌面上运行代码……问题是在哪个桌面上?因为可能有不同的用户同时登录(例如在 Windows Server 中可能有不同的用户远程登录)。

如果Process.Start在您的示例中使用服务:

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

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


解决方案是检测本地登录的用户,然后以该用户的身份(并在该用户的权限下)执行程序。为此,我想将您链接到我的另一个答案,我在其中演示如何从服务调用程序。那个答案中,我介绍了这种技术所需的代码

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

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

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

于 2013-03-24T06:41:40.887 回答
4

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).

于 2013-03-24T06:36:21.023 回答
2

使用http://www.pinvoke.net/default.aspx/shell32.shellexecuteshellexecute _pinvoke

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.
于 2013-03-24T06:50:08.873 回答
1

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

于 2013-03-24T06:39:28.177 回答