Sto creando un kill switch nella mia applicazione in modo che solo un'istanza possa essere eseguita contemporaneamente su un singolo computer. Sto realizzare questo inviando messaggi tra il processo di un'applicazione in esecuzione e il processo della nuova istanza dell'applicazione:PInvoke PostMessage non funziona su tutti gli account utente
[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);
non posso usare Process.Kill perché se un altro utente è in esecuzione l'applicazione e l'utente corrente non ha privilegi sufficienti ottengo problemi.
Quando si eseguono 2 istanze sotto lo stesso account utente non ho problemi. I messaggi vengono inviati correttamente e ricevuti correttamente. Tuttavia, quando si esegue un'istanza da un account utente, quindi si cambia utente e si esegue una seconda istanza, la prima istanza non riceve i messaggi.
Ecco la mia logica per la sottoscrizione ai messaggi di finestra:
var wih = new WindowInteropHelper(this);
var hwndSource = HwndSource.FromHwnd(wih.Handle);
var hwndSourceHook = new HwndSourceHook(HookHandler);
if (hwndSource != null)
hwndSource.AddHook(hwndSourceHook);
Ed ecco il mio gestore gancio:
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;
}
Ecco la logica per inviare il messaggio:
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);
}
No Win32 gli errori vengono impostati dalla funzione PostMessage. Non riesco a trovare alcuna documentazione riguardante la pubblicazione di messaggi tra processi attraverso account utente. È qualcosa che non può essere effettivamente fatto?
L'altro utente esegue il programma nella propria sessione con il proprio heap del desktop. Le probabilità che tu stia usando l'handle della finestra corretto sono piuttosto basse, dato che non puoi trovarlo dalla tua sessione. Andare avanti con il modo comune di farlo, utilizzando un mutex denominato.Prefix il suo nome con 'Global \' in modo che sia visibile attraverso le sessioni. E tieni presente che l'utente sarà completamente ignaro del motivo per cui non può avviare il programma e non avrà idea di come risolverlo. Visto quanto è ostile, è certamente meglio non farlo affatto. –
Recupero l'handle con Process.MainWindowHandle, quindi non sono sicuro del motivo per cui non otterremmo l'handle corretto a meno che il sistema non imposti un handle arbitrario a questo punto. Utilizzo già il mutex per determinare se è in esecuzione un'altra istanza, tuttavia lo scenario su cui stiamo lavorando è il programma di esecuzione A dell'utente, il sistema di blocchi utente A, l'utente B si firma, tenta di eseguire il programma. In questo scenario, vogliamo che l'utente B sia in grado di eseguire, quindi è necessario chiudere il programma nella sessione dell'utente A. Uccidere il programma non è l'ideale, tuttavia utilizziamo protocolli di comunicazione che possono essere utilizzati solo uno alla volta. – flamebaud
Tale handle è utilizzabile nella sessione che lo ha creato, il messaggio PostMessage() non va da nessuna parte. –