【发布时间】:2015-09-10 19:11:02
【问题描述】:
我在我的应用程序中构建了一个终止开关,以便一次只能在一台计算机上运行一个实例。我通过在正在运行的应用程序的进程和应用程序的新实例的进程之间发布消息来实现这一点:
[DllImport("user32.dll", EntryPoint = "PostMessageA", CharSet = CharSet.Ansi, SetLastError = true, ExactSpelling = true)]
private static extern int PostMessage(int hwnd, int wMsg, int wParam, int lParam);
我不能使用 Process.Kill,因为如果另一个用户正在运行应用程序并且当前用户没有足够的权限,我会遇到问题。
在同一用户帐户下运行 2 个实例时,我没有任何问题。消息被正确发送和正确接收。但是,当从一个用户帐户运行一个实例,然后切换用户并运行第二个实例时,我的第一个实例没有收到消息。
这是我订阅窗口消息的逻辑:
var wih = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(wih.Handle);
var hwndSourceHook = new HwndSourceHook(HookHandler);
if (hwndSource != null)
hwndSource.AddHook(hwndSourceHook);
这是我的钩子处理程序:
private IntPtr HookHandler(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
{
handled = false;
switch (msg)
{
case 0x400: // interprocess message received
App.InterprocessManager.BuildString(lParam);
break;
}
return IntPtr.Zero;
}
这是发送消息的逻辑:
private void SendString()
{
//create byte array
byte[] ba = null;
//encode string to byte array
if (object.ReferenceEquals(enc, Encoding.UTF8))
{
ba = Encoding.UTF8.GetBytes(lParam);
}
else if (object.ReferenceEquals(enc, Encoding.Unicode))
{
ba = Encoding.Unicode.GetBytes(lParam);
}
else if (object.ReferenceEquals(enc, Encoding.ASCII))
{
ba = Encoding.ASCII.GetBytes(lParam);
}
else
{
ba = Encoding.Default.GetBytes(lParam);
}
int i = 0;
for (i = 0; i <= ba.Length - 1; i++)
{
//start post message
PostMessage(hwnd, wMsg, wParam, ba[i]);
}
//post a terminator message to destination window
PostMessage(hwnd, wMsg, wParam, 0);
}
PostMessage 函数未设置 Win32 错误。我似乎找不到任何有关跨用户帐户在进程之间发布消息的文档。这是不是真的做不到?
【问题讨论】:
-
另一个用户在他自己的会话中使用自己的桌面堆运行程序。鉴于您无法从会话中找到它,您使用正确窗口句柄的几率相当低。通过使用命名互斥体的常用方法取得成功。在其名称前加上 `Global` 前缀,以便在会话中可见。请记住,用户将完全不知道为什么他无法启动程序并且不知道如何修复它。鉴于这是多么充满敌意,当然最好不要这样做。
-
我使用 Process.MainWindowHandle 检索句柄,所以我不确定为什么我们不会得到正确的句柄,除非系统此时只是设置了任意句柄。我已经使用互斥锁来确定另一个实例是否正在运行,但是我们正在使用的场景是用户 A 运行程序,用户 A 锁定系统,用户 B 登录,尝试运行程序。在这种情况下,我们希望用户 B 能够运行,因此我们需要终止用户 A 会话中的程序。杀死程序并不理想,但是我们使用的通信协议一次只能使用一个
-
该句柄在创建它的会话中可用,您的 PostMessage() 消息无处可去。
标签: c# .net wpf user32 inter-process-communicat