gpt4 book ai didi

c# - PInvoke PostMessage 不能跨用户帐户工作

转载 作者:太空狗 更新时间:2023-10-29 23:44:49 25 4
gpt4 key购买 nike

我正在我的应用程序中构建一个终止开关,以便在一台计算机上一次只能运行一个实例。我通过在正在运行的应用程序的进程和应用程序的新实例的进程之间发布消息来完成此操作:

[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);

这是我的钩子(Hook)处理程序:

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 错误。我似乎找不到任何关于跨用户帐户在进程之间发布消息的文档。这真的是做不到的事情吗?

最佳答案

您不能将窗口消息发送到不同 session 中的进程。您必须使用基于内核而非用户对象的 IPC 机制。

在您的场景中,一个命名的互斥量和一个命名的信号量可能就是您所需要的。请注意,名称必须具有 Global\ 前缀,以允许多个 session 共享一个对象。

在进程启动时,首先创建或打开信号量。将初始计数设置为零。

然后创建命名互斥锁,将 bInitialOwner 设置为 TRUE 并检查最后一个错误代码以查看互斥锁是否已经存在。

如果互斥锁不存在,那么你是第一个实例,所以创建一个线程来等待信号量。如果信号量发出信号,则退出进程。确保在其他进程可以安全运行之前不要释放互斥量;如果有疑问,根本不要释放它。一旦进程退出,Windows 将发出放弃信号。

如果互斥锁已经存在,则另一个实例正在运行。向信号量发出信号,然后等待互斥量。一旦您获得互斥量的所有权,就可以安全地继续。然后,您需要创建一个线程来等待信号量,以防另一个实例出现并想要干扰您。

如果你需要一个更复杂的进程之间的通信 channel ,例如,如果你需要交出通信 channel 的当前状态,那么你最好的选择可能是named pipes。 .

关于c# - PInvoke PostMessage 不能跨用户帐户工作,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31028991/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com