3

在 Windows 7 中使用 .NET Windows 服务显示消息框

我们有一个 windows 服务,一旦用户在 windows xp 上扫描了他们的访问卡,我们就会显示一个确认消息框,但是一旦我们迁移到 windows 7,这个弹出功能就不再起作用了。正如这篇文章使用 .NET Windows 服务在 Windows 7 中显示消息框中所述,我已按照说明进行操作,当我将应用程序作为控制台应用程序运行时它可以工作,但是当我将其安装为 Windows 服务时它不起作用。下面是我的代码。结果变量也返回 false,err 变量返回 5。

class Class1
{
    public static IntPtr WTS_CURRENT_SERVER_HANDLE = IntPtr.Zero;
    public static int WTS_CURRENT_SESSION = -1;
    public void test()
    {
        bool result = false;
        string title = "Hello";
        int tlen = title.Length;
        string msg = "Terminal Service!";
        int mlen = msg.Length;
        int resp = 0;

        result = WTSSendMessage(WTS_CURRENT_SERVER_HANDLE, WTS_CURRENT_SESSION, title, tlen, msg, mlen, 0, 0, out resp, true);
        int err = Marshal.GetLastWin32Error();
        System.Console.WriteLine("result:{0}, errorCode:{1}, response:{2}", result, err, resp);

    }

    [DllImport("wtsapi32.dll", SetLastError = true)]
    static extern bool WTSSendMessage(
        IntPtr hServer,
        [MarshalAs(UnmanagedType.I4)] int SessionId,
        String pTitle,
        [MarshalAs(UnmanagedType.U4)] int TitleLength,
        String pMessage,
        [MarshalAs(UnmanagedType.U4)] int MessageLength,
        [MarshalAs(UnmanagedType.U4)] int Style,
        [MarshalAs(UnmanagedType.U4)] int Timeout,
        [MarshalAs(UnmanagedType.U4)] out int pResponse,
        bool bWait);

    [DllImport("Kernel32.dll", SetLastError = true)]
    static extern int WTSGetActiveConsoleSessionID();

}
4

2 回答 2

2

对 WTSSendMessage() 的调用指定 WTS_CURRENT_SESSION,这意味着“在当前会话中显示消息框”。当您作为服务运行时,您处于会话 0 上,该会话在 Windows 7 上是隔离的。你肯定不希望你的消息框出现在那里!

要显示在常规用户的会话中,您必须提供非零会话 ID。有关详细信息,请参阅WTSSendMessage() 文档

于 2013-09-11T05:38:21.360 回答
2

您已声明 WTSGetActiveConsoleSessionId 但从未调用它。该函数返回当前活动的会话 ID。这是您必须传递给 WTSSendMessage 的会话 ID。

您当前的代码正在尝试在服务会话会话 0 中显示消息。这不是您想要的。

但是,在调用该函数之前,您必须更正其声明。你拼写错误。它被命名为 WTSGetActiveConsoleSessionId。

我相信字符串长度参数需要考虑零终止符。将 1 添加到您传递的值。如果您切换到 Unicode API,那么您必须将这些值乘以 2,因为它们是以字节而不是字符来衡量的。

还有一点。仅当 API 调用失败时才询问错误代码。因此,在您的代码中,您必须仅在结果为 false 时调用 Marshal.GetLastWin32Error。

于 2013-09-11T06:10:16.577 回答