Я создаю переключатель kill в своем приложении, так что только один экземпляр может запускаться одновременно на одном компьютере. Я выполнение этого пути размещения сообщений между процессом запущенного приложения и процессом нового экземпляра приложения:PInvoke PostMessage не работает через учетные записи пользователей
[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);
}
Нет Win32 ошибки устанавливаются функцией PostMessage. Я не могу найти какую-либо документацию, связанную с отправкой сообщений между процессами через учетные записи пользователей. Это то, что на самом деле нельзя сделать?
Другой пользователь запускает программу на своем собственном сеансе с собственной кучей рабочего стола. Шансы, что вы используете правильный дескриптор окна, довольно низки, учитывая, что вы не можете найти его на своем сеансе. Продвигайтесь общим путем, используя именованный мьютекс.Префикс его имени 'Global \ ', чтобы он отображался в разных сеансах. И имейте в виду, что пользователь будет совершенно непонятен, почему он не может запустить программу и не знает, как это исправить. Учитывая, насколько это враждебно, безусловно, лучше вообще не делать этого. –
Я извлекаю дескриптор с Process.MainWindowHandle, поэтому я не уверен, почему мы не получим правильный дескриптор, если система просто не установит произвольный дескриптор в этой точке. Я уже использую мьютекс, чтобы определить, работает ли другой экземпляр, однако сценарий, с которым мы работаем, - это программа запуска User A, система блокировки пользователя A, пользовательский знак B, пытается запустить программу. В этом сценарии мы хотим, чтобы User B мог работать, поэтому нам нужно завершить программу в сеансе User A. Убийство программы не является идеальным, однако мы используем протоколы связи, которые могут использоваться только по одному. – flamebaud
Этот дескриптор можно использовать в сеансе, который его создал, ваше сообщение PostMessage() никуда не отправляется. –