Blokowanie nowej instancji programu

0

Witam

Od jakiegoś czasu poszukuję sposobu, jak zablokować odpalenie kolejny raz tego samego programu, w sensie odpalamy pierwszą instancję, która działa normalnie, a kolejne odpalenie powoduje pokazanie ukrytej pierwszej instancji i zamknięcie kolejnej (właśnie odpalonej).

Pozdrawiam
Dragas

0

Muteks, gniazdo, plik otwarty w trybie exclusive, potok nazwany, DDE, pamięć współdzielona... Temat był poruszany tyle razy, że go usuwam.

0

Oprócz tego co @ŁF podał, można wylistować sobie uruchomione procesy i jeśli widać tam drugą instancję no to nie jesteśmy pierwsi.

1

Tutaj przy okazji w sumie czegoś innego jest dobry przykład: http://www.pzielinski.com/?p=183

0

@madmike: http://4programmers.net/Delphi/faq/Jak_zablokowa%C4%87_wielokrotne_uruchomie_programu
Delphi7. Jaki jest najlepszy sposób, by nie dopuścić do uruchomienia po raz drugi programu?
Wielokrotne otwieranie
Rozumiem, że to Delphi a nie C#, jednak mechanizmy pozostają identyczne. Dalej nie chce mi się szukać, ale wiem że jest tego dużo więcej, bo sam na kilkanaście takich postów odpisywałem.

0

@somekind: dzięki :)
No właśnie kod ma być w C#, tylko nie wiem jak zrobić, aby instancja, która została uruchomiona jako pierwsza, pokazała się przy próbie kolejnego odpalenia programu.

1

OK, więc po raz ostatni (oby) odpowiadam w temacie jednej instancji aplikacji. Poniższy kod jest sklejony z kilku dostępnych na stackoverflow (głównie http://stackoverflow.com/questions/184084/how-to-force-c-sharp-net-app-to-run-only-one-instance-in-windows/11463450#11463450 i http://stackoverflow.com/questions/11065026/get-window-state-of-another-process).
Kod:

  • przywróci pierwsze okno aplikacji o nazwie procesu identycznej z procesem sprawdzającym te dane;
  • jeśli takiego okna nie znajdzie, a nie jest to jedyna instancja muteksu o podanej nazwie, wyświetli informację o nieznalezieniu procesu i nie pozwoli na uruchomienie aplikacji;
  • poradzi sobie zarówno z oknem zminimalizowanym, jak i zmaksymalizowanym oraz o normalnym rozmiarze.
using System;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Threading;
using System.Windows.Forms;


namespace SomeApplication
{
	static class Program
	{
		[DllImport("USER32.DLL")]
		public static extern bool SetForegroundWindow(IntPtr hWnd);

		[DllImport("user32.dll")]
		private static extern bool ShowWindow(IntPtr hWnd, int nCmdShow);

		[DllImport("user32.dll", SetLastError = true)]
		[return: MarshalAs(UnmanagedType.Bool)]
		private static extern bool GetWindowPlacement(IntPtr hWnd, ref WindowPlacement lpwndpl);


		private enum ShowWindowCommands : int
		{
			ShowNormal = 1,
			ShowMinimized = 2,
			ShowMaximized = 3,
			Show = 5,
			Restore = 9
		}

		[Serializable]
		[StructLayout(LayoutKind.Sequential)]
		private struct WindowPlacement
		{
			public int length;
			public int flags;
			public ShowWindowCommands showCmd;
			public System.Drawing.Point ptMinPosition;
			public System.Drawing.Point ptMaxPosition;
			public System.Drawing.Rectangle rcNormalPosition;
		}


		private static WindowPlacement GetPlacement(IntPtr hwnd)
		{
			WindowPlacement placement = new WindowPlacement();
			placement.length = Marshal.SizeOf(placement);
			GetWindowPlacement(hwnd, ref placement);
			return placement;
		}



		/// <summary>
		/// The main entry point for the application.
		/// </summary>
		[STAThread]
		static void Main()
		{
			bool createdNew = true;
			using (Mutex mutex = new Mutex(true, "SomeApplication", out createdNew))
			{
				if (createdNew)
				{
					Application.EnableVisualStyles();
					Application.SetCompatibleTextRenderingDefault(false);
					Application.Run(new Form1());
				}
				else
				{
					var processFound = false;
					Process current = Process.GetCurrentProcess();
					foreach (Process process in Process.GetProcessesByName(current.ProcessName))
					{
						if (process.Id != current.Id)
						{
							var handle = process.MainWindowHandle;
							var placement = GetPlacement(handle);
							if (placement.showCmd == ShowWindowCommands.ShowMinimized) ShowWindow(handle, (int)ShowWindowCommands.Restore);
							SetForegroundWindow(handle);
							processFound = true;
						}
					}

					if (!processFound) MessageBox.Show("Process not found, use genuine executable name."); // gtfo
				}
			}
		}


	}
}

Może ktoś pokusi się o napisanie wersji, która będzie działać niezależnie od zmiany nazwy procesu? Chodzi o postawienie czegoś w rodzaju "serwera" i odebrania sygnału z innej aplikacji.

1 użytkowników online, w tym zalogowanych: 0, gości: 1