Esta pregunta nos la hemos hecho algunos cuando se trataba de hacer un programa que sólo pudiera tener una ventana abierta a la vez, esto a veces puede ser útil por ejemplo para hacer un aplicación MDI, o porque al ser un programa único sin posibles añadidos ni cambio de pantallas, quisiéramos que no ocurriera nada.
Pues bien, éste es mi truco personal:
Process oCurrentProcess = Process.GetCurrentProcess();
//get all other process by the same name, atleast one will
be returned - the current one.
Process[]
arrProcesses = Process.GetProcessesByName(oCurrentProcess.ProcessName);
bool bProcess = false;
//go thru all of them
foreach(Process oProcess in
arrProcesses)
{
//if the id is different, that means another process by the
same name exists
if(oProcess.Id != oCurrentProcess.Id) //
{
MessageBox.Show("Another
instance of the application is already running");
bProcess
= true;
break;
}
}
if(!bProcess)
{
//if process not found, start one
Application.Run(new actualizaDB());
}
else
{
//else exit
Application.Exit();
}
Hasta aquí yo creo que todo se entiende, y siento no tener mucho tiempo para explicarlo con detenimiento.
Pero el caso es que pensaréis, aquí falta algo, ese algo es que la ventana del programa no se abre en estos casos, se queda minimizada.
Bueno, este truco es más difícil y requiere algo más de programación pero seguro que me agradecéis que os pase este código tan socorrido.
Ah, por cierto, en .NET 2 ha llegado a mis oídos que ya hay métodos para facilitar la tarea.
Primero crear la siguiente clase:
using System;
using System.Collections.Specialized;
using System.Diagnostics;
using System.Runtime.InteropServices;
namespace Win32APIs
{
public sealed class WindowsHelper
{ #region structures needed to call into unmanaged Win32 APIs.
[StructLayout(LayoutKind.Sequential)]
private class ManagedPt
{ public int x = 0;
public int y = 0;
public ManagedPt()
{ }
public ManagedPt(int x, int y)
{ this.x = x;
this.y = y;
}
}
[StructLayout(LayoutKind.Sequential)]
private class ManagedRect
{ public int x = 0;
public int y = 0;
public int right = 0;
public int bottom = 0;
public ManagedRect()
{ }
public ManagedRect(int x, int y, int right, int bottom)
{ this.x = x;
this.y = y;
this.right = right;
this.bottom = bottom;
}
}
[StructLayout(LayoutKind.Sequential)]
private class ManagedWindowPlacement
{ public uint length = 0;
public uint flags = 0;
public uint showCmd = 0;
public ManagedPt minPosition = null;
public ManagedPt maxPosition = null;
public ManagedRect normalPosition = null;
public ManagedWindowPlacement()
{ this.length = (uint)Marshal.SizeOf(this);
}
}
#endregion
[DllImport("USER32.DLL", SetLastError=true)] private static extern uint ShowWindow (uint hwnd, int showCommand);
[DllImport("USER32.DLL", SetLastError=true)] private static extern uint SetForegroundWindow (uint hwnd);
[DllImport("USER32.DLL", SetLastError=true)] private static extern uint GetWindowPlacement (uint hwnd,
[In, Out]ManagedWindowPlacement lpwndpl);
[DllImport("USER32.DLL", SetLastError=true)] private static extern uint FindWindow (string lpClassName, string lpWindowName);
private const int WM_ACTIVATE = 0x0006;
private const int WA_CLICKACTIVE = 2;
private const int SW_SHOWNORMAL = 1;
private const int SW_SHOWMINIMIZED = 2;
private const int SW_SHOWMAXIMIZED = 3;
private const int WPF_RESTORETOMAXIMIZED = 2;
static private uint FindWindow(string windowName)
{
uint hwndInstance = FindWindow(null, windowName);
if (hwndInstance <= 0)
{ Debug.Assert(false,
"Couldn't find window handle for the specified window name.");
}
return hwndInstance;
}
static public void ActivateWindow(string windowName)
{
uint hwndInstance = FindWindow(windowName);
ManagedWindowPlacement placement = new ManagedWindowPlacement();
GetWindowPlacement(hwndInstance, placement);
if (placement.showCmd == SW_SHOWMINIMIZED)
{
int showCmd = (placement.flags == WPF_RESTORETOMAXIMIZED) ?
SW_SHOWMAXIMIZED : SW_SHOWNORMAL;
ShowWindow(hwndInstance, showCmd);
}
else
{
SetForegroundWindow(hwndInstance);
}
}
}
}
Después cread esta otra clase:
using System;
using System.Collections.Specialized;
using System.Reflection;
using System.Threading;
using System.Windows.Forms;
using Win32APIs;
namespace SingleInstanceApp
{
public sealed class SingleInstanceHelper
{
static private Mutex singleInstance = null; for
private const string formatMutexName = "SingleInstanceMutex-{0}-{1}";
static private string UniqueIdentifier
{ get
{ string appName = "";
string appVersion = "0.0.0.0";
Assembly entry = Assembly.GetEntryAssembly();
if (entry != null)
{ AssemblyName assemblyName = entry.GetName();
if (assemblyName != null)
{ appName = assemblyName.Name;
appVersion = assemblyName.Version.ToString();
}
}
return string.Format(formatMutexName, appName, appVersion);
}<