我对微软世界有点新意。我已经阅读了this回答和许多其他链接,我知道在Vista之后,Windows服务无法与桌面交互。
然而,我有一种紧急情况,我必须快速找到解决方法。我需要我的Windows服务以某种方式打开一个带有URL的浏览器(任何类型的丑陋黑客现在都会这样做)。 答案说明:
您需要编写一个单独的代理应用程序,该应用程序将在用户登录时自动启动,并与您的服务进行通信。然后,代理可以启动浏览器或执行您需要的任何其他操作。
有人可以向我解释如何以简单的方式做到这一点吗?该服务如何与这个“代理人”交谈?这个“代理人”究竟是什么?
任何链接或建议都将受到高度赞赏。
编辑:目前。我的服务尝试运行以下代码:System.Diagnostics.Process.Start("www.google.com");
,我后来发现,它不起作用
答案 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秒?),并在需要时打开浏览器。