Prevent a Process from Being Created Again in VC or C#

7 篇文章 0 订阅
    In some circumstances we expect that a process can do the following checks when it is created:
    1. If none of the processes with the same name has been created yet, the process continues to perform its tasks;
    2. If there exists a process with the same name, the process activates it, bring it to the top level of screen and exits, especially when the type of the process is winform.
    To meet the first requirement, the mutex or the semaphore can be used in VC, and Process.GetProcessesByName( ) method can be used in C#. It isn't the focus of this article. How to meet the second requirement is discussed here.
    The following way is recommended on many websites:
/* VC example */
if(hWnd)  /* assuming that hwnd is the handle of the program window */
{
  HWND hForeWnd = ::GetForegroundWindow();
  DWORD dwForeID = ::GetWindowThreadProcessId(hForeWnd,NULL);
  DWORD dwCurID = ::GetCurrentThreadId();
  ::AttachThreadInput(dwCurID,dwForeID,TRUE);
  ::ShowWindow(hWnd,SW_SHOWNORMAL);
  ::SetWindowPos(hWnd,HWND_TOPMOST,0,0,0,0,SWP_NOSIZE|SWP_NOMOVE);
  ::SetWindowPos(hWnd,HWND_NOTOPMOST,0,0,0,0, SWP_NOSIZE|SWP_NOMOVE);
  ::SetForegroundWindow(hWnd);
  ::AttachThreadInput(dwCurID,dwForeID,FALSE);
}

    The operating system in my computer is Win7-64bits. I tried to use such codes in my program. It was surprising that it worked only when the EXE file was run in the debug or release folder of Visual Studio 2010, in the search box of the Start menu, and in the Run command dialog (invoked by pressing Win+R). After I copied the EXE file to another folder of the same disk or to a USB disk, I found this method didn't work. Even if I double clicked the icon of the program, the new process exited directly. It couldn't bring the process already running in the background to the foreground and activate the program window. I had been puzzled for weeks before one of my friends suggested that a program window be restored by receiving restore message. He told me the following solution in VC:
    1. find the program window handle by its title;
    2. send restore message to that program window;
    3. bring that program window to the foreground of the screen.
    I tried the solution and found it did work. The code snippet is as follows:

/* VC example: check if this program has been started */
BOOL CMyApp::InitInstance()
{
  TCHAR MutexObjectName[MAX_PATH] = {_T("MutexObjectNameInMyExampleProgram")};
  ghMutex = CreateMutex(NULL, FALSE, MutexObjectName);
  if (!ghMutex)
  {
    MessageBox(NULL, _T("Creating mutex object failed!"), _T("Example program"), MB_ICONERROR);
    return FALSE;
  }
  if ( GetLastError() == ERROR_ALREADY_EXISTS )
  {
    HWND hPrgWnd = FindWindow(NULL, ProgramWindowTitle); /* ProgramWindowTitle is the window title of the winform program */
    if (!hPrgWnd)
    {
      MessageBox(NULL, _T("Finding window failed!"), ProgramTitle, MB_ICONERROR);
      return FALSE;
    }
    SendMessage(hPrgWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
    SetForegroundWindow(hPrgWnd);
  }
  return FALSE;  
}

    I transplanted the codes to C#. The code snippet is as follows:

/**************************************************
* Author: HAN Wei
* Author's blog: http://blog.csdn.net/henter/
* Date: May 26th, 2016
* Description: demonstrate how to check if the process 
               of the winform program has been started in C#
* File name: Program.cs
**************************************************/
using System;
using System.Collections.Generic;
using System.Windows.Forms;
using System.Diagnostics;
using System.Runtime.InteropServices;

namespace MyExampleProgram
{
    static class Program
    {
        [DllImport("user32.dll")]
        private static extern IntPtr FindWindow(string ClassName, string WindowName);
        [DllImport("user32.dll")]
        private static extern IntPtr SendMessage(IntPtr hWnd, uint Msg, uint wParam, uint lParam);
        [DllImport("user32.dll")]
        private static extern int SetForegroundWindow(IntPtr hWnd);

        const uint WM_SYSCOMMAND = 0x112;
        const uint SC_RESTORE = 0xf120;

        [STAThread]
        static void Main()
        {
            const string strPrgName = "MyExampleProgramName"; /* This variable denotes the 
                                    executable file name. Note the EXE sufix is not needed */
            const string strProgramWindowTitle = "MyExampleProgramWindowTitle"; /* This 
                                 variable denotes the window title of the winform program. */
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);

            Process[] processes = Process.GetProcessesByName(strPrgName);
            if (processes.Length > 1) /* There exists a process with the same program name. */
            {
                IntPtr hPrgWnd = FindWindow(null, strProgramWindowTitle);
                if (hPrgWnd == null)
                {
                    return;
                }
                SendMessage(hPrgWnd, WM_SYSCOMMAND, SC_RESTORE, 0);
                if (SetForegroundWindow(hPrgWnd) == 0)
                {
                    return;
                }
                return;
            }
            else
            {
                Application.Run(new Form1()); /* Form1 is the main form of the program. 
                                                 Operation is performed by user in Form1. */
            }
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值