博客园  :: 首页  :: 新随笔  :: 联系 :: 管理

实现单进程(Single Instance)的.NET WinForm应用程序

Posted on 2009-11-13 23:37  codingsilence  阅读(370)  评论(0编辑  收藏  举报

 

 

    最近发现我参与开发的基于.NET WinForm + WebService的呼叫中心应用程序如果客户端打开一个以上窗口的时候会出现非预期的异常.这促使我将我们的应用程序改进成同一时间内只允许有一个进程运行.

    基本的原理上Google一搜一大把,无非是利用System.Diagnostics.Process.GetProcess()方法获取当先系统所有运行着的进程信息来进行判断.但是我们有一个特殊的要求,那就是如果发现已经有进程在运行着就把这个运行中进程的主窗体显示出来.

    既然要获取当前进程的主窗体,那么就从Process类的属性着手, Process类有一个名为MainWindowHandle的属性,其类型为System.IntPtr, 表示一个指向该进程主窗体的指针, OK,知道这些就好办了.既然是指针那么肯定不能使用托管代码的方法来操纵窗体了. 这也OK, 用API呗.

    MSDN了一下Windows API,发现了这么几个方法对我有用.

BOOL ShowWindowAsync(HWND hWnd,int nCmdShow);
The ShowWindowAsync function sets the show state of a window created by a different thread.

VOID SwitchToThisWindow(HWND hWnd, BOOL fAltTab);
The SwitchToThisWindow function is called to switch focus to a specified window and bring it to the foreground.

 

具体的代码实现如下:

[DllImport("User32.dll")]
public static extern int ShowWindowAsync(IntPtr hWnd , int swCommand);
[DllImport("User32.dll")]
public static extern void SwitchToThisWindow(IntPtr hWnd,bool fAltTab);
[STAThread()]
public static void Main()
{
  Process[] RunningProcesses = Process.GetProcessesByName("WindowsApplication1");
  if(RunningProcesses.Length == 1)
  {
    Application.Run(new GetProcessInfos());
  }
  foreach(Process proc in RunningProcesses)
  {
    if(proc.MainWindowHandle.ToInt32() >0)
   {
      //ShowWindowAsync(RunningProcesses[0].MainWindowHandle, (int)ShowWindowConstants.SW_SHOWMINIMIZED);
     ShowWindowAsync(proc.MainWindowHandle, (int)ShowWindowConstants.SW_RESTORE);
     SwitchToThisWindow(proc.MainWindowHandle,false);
   }
  }
}
public enum ShowWindowConstants
{
 SW_HIDE = 0,
 SW_SHOWNORMAL = 1,
 SW_NORMAL = 1,
 SW_SHOWMINIMIZED = 2,
 SW_SHOWMAXIMIZED = 3,
 SW_MAXIMIZE = 3,
 SW_SHOWNOACTIVATE = 4,
 SW_SHOW = 5,
 SW_MINIMIZE = 6,
 SW_SHOWMINNOACTIVE = 7,
 SW_SHOWNA = 8,
 SW_RESTORE = 9,
 SW_SHOWDEFAULT = 10,
 SW_FORCEMINIMIZE = 11,
 SW_MAX = 11
}

 

其中ShowWindowConstants枚举类型的定义请参考WinUser.h  安装有VisualStudio的都可以在安装路径下找到.