📜 ⬆️ ⬇️

Windows mobile: one instance of the application

Problem


While working on windows mobile project (Visual Studio 2008, .net cf 3.5, C #), I ran into the problem of controlling the launch of a single instance of an application. Unfortunately, the creators of the .net compact framework 3.5 (and earlier versions) did not include the ability to search for a process by its name — the System.Diagnostics.Process method .GetProcessesByName () . No additional methods were found that could solve the problem with the help of managed code.

Decision


The problem can be solved in several ways using unmanaged code. Global process synchronization objects act as helpers: mutexes, semaphores and events. Let us dwell on the latter.
First you need to create a permanent identifier for our event (Visual Studio has a built-in GUID generator: Tools-> Create GUID):
private static readonly Guid SingleInstanceGuid = new Guid ( "1DADFDD1-DDD1-4390-95B9-5852CFB39807" );


Then use unmanaged code:
private const int ERROR_ALREADY_EXISTS = 183; // error code returned in case of an already existing event

[DllImport ( "coredll.dll" , SetLastError = true )]
private static extern IntPtr CreateEvent ( IntPtr lpEventAttributes, bool bManualReset, bool bInitialState, string lpName);
')
[DllImport ( "coredll.dll" , SetLastError = true )]
private static extern bool CloseHandle ( IntPtr hObject);

[DllImport ( "coredll.dll" , SetLastError = true )]
private static extern IntPtr FindWindow ( string className, string wndName);


Create an event, get an error code, return the answer:
public static bool IsSingleInstance () {
var path = Assembly .GetExecutingAssembly (). GetName (). CodeBase;
handle = CreateEvent ( IntPtr .Zero, false , false , SingleInstanceGuid.ToString ());
var error = Marshal.GetLastWin32Error ();

// If the event already exists, find the running application and send it the command 0x8001, which should re-activate the application
if (error == ERROR_ALREADY_EXISTS) {
var hWnd = FindWindow ( "#NETCF_AGL_PARK_" + path, string .Empty);

if (hWnd! = IntPtr .Zero) {
var msg = Message.Create (hWnd, 0x8001, ( IntPtr ) 0, ( IntPtr ) 0);
MessageWindow.SendMessage ( ref msg);
}

return false ;
}

return true ;
}


Before closing the application, close the event:
public static void CloseHandle () {
CloseHandle (handle);
}


For convenience, all this code is placed in a class, for example, SingleInstance.cs. In practice, it is applied as follows in the program.cs file:

if (! SingleInstance.IsSingleInstance ()) {
return ;
}
try {
Application.Run ( new Form1 ());
} catch (Exception ex) {
} finally {
SingleInstance.CloseHandle ();
} * This source code was highlighted with Source Code Highlighter .


A similar idea has option using mutexes.
I hope this decision will be useful to someone.

Source: https://habr.com/ru/post/30241/


All Articles