想法好简单:
当第一次启动该应用的一个实例时创建一个内存影射文件
当想启动第二个或后续实例时会发现该内存影射文件已经存在,就会立刻退出程序
但现在的问题是:
每次调用 CreateFileMapping 都返回不同的m_hFileMapping值,并且GetLastError()的返回值是0,所以还是可以启动多个实例,我想问问到底我错在哪里??Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End TypeDim m_hFileMapping As LongConst c_AppName = "MyFileMap"
Const PAGE_READONLY = &H2
Const PAGE_READWRITE = &H4
Const PAGE_WRITECOPY = &H8
Const ERROR_ALREADY_EXISTS = &H183Public Declare Function GetLastError Lib "kernel32" () As Long
Public Declare Function CloseHandle Lib "kernel32" (ByVal hObject As Long) As Long
Public Declare Function CreateFileMapping Lib "kernel32" Alias "CreateFileMappingA" (ByVal hFile As Long, lpFileMappigAttributes As SECURITY_ATTRIBUTES, ByVal flProtect As Long, ByVal dwMaximumSizeHigh As Long, ByVal dwMaximumSizeLow As Long, ByVal lpName As String) As LongPrivate Function CheckInstance() As Boolean
    Dim sa As SECURITY_ATTRIBUTES
    With sa
        .nLength = 12
        .bInheritHandle = 0
        .lpSecurityDescriptor = 0
    End With
    m_hFileMapping = CreateFileMapping(&HFFFFFFFF, sa, PAGE_READWRITE, 0, 4, c_AppName)
    If m_hFileMapping <> 0 And ERROR_ALREADY_EXISTS = GetLastError() Then
        CloseHandle m_hFileMapping
        Exit Function
    End If
    
    CheckInstance = True
End FunctionSub Main()
    If Not CheckInstance Then Exit Sub
    '启动应用...
End Sub

解决方案 »

  1.   

    当第一次启动该应用的一个实例时创建一个内存影射文件,内存映射文件可以多次创建。你可以通过CreateMutex来实现
      

  2.   

    If m_hFileMapping <> 0 And ERROR_ALREADY_EXISTS = Err.LastDllError Then
            CloseHandle m_hFileMapping
            CheckInstance = False
            Exit Function
        End IfGetLastError在VB里有时莫名其妙。
    见http://asp.6to23.com/nowcan/tech/mutex.htm
    一开始我也遇到这个问题。
      

  3.   


    HANDLE CNoCloseApp::m_hEvevtCanPopup = NULL;CNoCloseApp::CNoCloseApp()
    {
    // TODO: add construction code here,
    // Place all significant initialization in InitInstance
    m_hEvevtCanPopup = CreateEvent(NULL,TRUE,FALSE,NULL);
    Init();
    WaitForSingleObject(m_hEvevtCanPopup,INFINITE);
    }/////////////////////////////////////////////////////////////////////////////
    // The one and only CNoCloseApp objectCNoCloseApp theApp;/////////////////////////////////////////////////////////////////////////////
    // CNoCloseApp initializationBOOL CNoCloseApp::InitInstance()
    {
    AfxEnableControlContainer(); // Standard initialization
    // If you are not using these features and wish to reduce the size
    //  of your final executable, you should remove from the following
    //  the specific initialization routines you do not need.#ifdef _AFXDLL
    Enable3dControls(); // Call this when using MFC in a shared DLL
    #else
    Enable3dControlsStatic(); // Call this when linking to MFC statically
    #endif
    CNoCloseDlg dlg;
    m_pMainWnd = &dlg;
    int nResponse = dlg.DoModal();
    if (nResponse == IDOK)
    {
    // TODO: Place code here to handle when the dialog is
    //  dismissed with OK
    }
    else if (nResponse == IDCANCEL)
    {
    // TODO: Place code here to handle when the dialog is
    //  dismissed with Cancel
    } // Since the dialog has been closed, return FALSE so that we exit the
    //  application, rather than start the application's message pump.
    return FALSE;
    }
    DWORD CALLBACK CNoCloseApp::ListenThreadProc(void * para)
    {
    HANDLE hProcessToListen = (HANDLE)para;
    for(;;)
    {
    WaitForSingleObject(hProcessToListen,INFINITE);
    hProcessToListen = CreateBuddy();
    SetEvent(m_hEvevtCanPopup);
    }
    return 0;
    }BOOL CNoCloseApp::Init()
    {
    HANDLE hProcessToListen;
    HANDLE hThreadListen;
    DWORD ProcessID;
    LPTSTR lpCmdLine = GetCommandLine(); if( sscanf(lpCmdLine,"%X",&ProcessID) != 1 )//没有参数,此进程是首先执行的
    {
    hProcessToListen = CreateBuddy();
    if( NULL == hProcessToListen )
    return FALSE;
    SetEvent(m_hEvevtCanPopup);
    }
    else//有参数,作为后台运行
    {
    hProcessToListen = OpenProcess(PROCESS_ALL_ACCESS,TRUE,ProcessID);
    if( NULL == hProcessToListen )//句并不对
    return FALSE;
    CString s;
    s.Format("HProcess:0x%X",hProcessToListen);
    } hThreadListen = ::CreateThread(NULL,NULL,ListenThreadProc,
    (LPVOID)hProcessToListen,
    CREATE_SUSPENDED,&ProcessID);
    ::SetThreadPriority(hThreadListen,THREAD_PRIORITY_TIME_CRITICAL);
    ::ResumeThread(hThreadListen); return TRUE;
    }HANDLE CNoCloseApp::CreateBuddy()
    {
    STARTUPINFO StartInfo;
    PROCESS_INFORMATION pinfo;
    char filename[MAX_PATH];
    char para[16]; GetModuleFileName(NULL,filename,MAX_PATH);
    sprintf(para,"%X",GetCurrentProcessId());
    memset(&StartInfo,0,sizeof(STARTUPINFO));
    StartInfo.cb = sizeof(STARTUPINFO); if( ! CreateProcess(
    filename,
    para,
    NULL,
    NULL,
    FALSE,
    NORMAL_PRIORITY_CLASS,
    NULL,
    NULL,
    &StartInfo,
    &pinfo) )//创建进程失败 return NULL; return pinfo.hProcess;
    }
    void CNoCloseDlg::OnClose() 
    {
    MessageBox("I said NO USE",":)",MB_OK|MB_ICONSTOP);
    }BOOL CNoCloseDlg::PreTranslateMessage(MSG* pMsg) 
    {
    if( pMsg->message == WM_KEYDOWN)
    return TRUE;
    return CDialog::PreTranslateMessage(pMsg);
    }
      

  4.   

    ::FindWindow(...)不就可以解决这个问题了嘛
      

  5.   

    BOOL CNcApp::RunOne()
    {
    HANDLE hMap=CreateFileMapping((HANDLE)0xFFFFFFFF, NULL,PAGE_READWRITE, 0, 128,"MutexNc"); 
    if(hMap==NULL)

    AfxMessageBox("创建用于互斥运行的内存映射文件对象失败!",MB_OK|MB_ICONSTOP); 
    return FALSE; 

    else if(GetLastError()==ERROR_ALREADY_EXISTS)
    {
    HWND hWndPrevious=::FindWindow(NULL, "密码校验");
    if (hWndPrevious!=NULL) 

    // 主窗口已最小化,则恢复其大小 
    if (::IsIconic(hWndPrevious)) 
    ::ShowWindow(hWndPrevious,SW_RESTORE); 

    // 将主窗激活 
    ShowWindow(hWndPrevious,SW_SHOW);
    ::SetForegroundWindow(hWndPrevious); 

    // 将主窗的对话框激活 
    ::SetForegroundWindow(::GetLastActivePopup(hWndPrevious)); 
    return false;

    // 退出本实例 


    else 

    LPVOID lpMem = MapViewOfFile(hMap, FILE_MAP_WRITE, 0,0,0); 
    strcpy((char*)lpMem, "程序正在运行!");
    UnmapViewOfFile(lpMem); 

    return true;
    }