2012-02-10 33 views
5

Tôi muốn tạo mutex bằng Dịch vụ Windows và một tên miền có cùng tên bằng chức năng CreateMutex. Nếu một mutex được tạo bởi Dịch vụ Windows và khi exe cố tạo một mutex khác có cùng tên thì nó sẽ thành công mà không có bất kỳ lỗi nào như ERROR_ALREADY_EXIST.Tên mutex giống nhau cho dịch vụ Windows và exe trong Windows 7

Điều này chỉ xảy ra trong Windows 7. Nhưng đối với Windows XP ERROR_ALREADY_EXIST được hiển thị. Tôi không thể đưa ra lý do cho sự khác biệt này trong hệ điều hành và cách khắc phục vấn đề này.

Mẫu Mã

Đối với Mã dịch vụ

#include<iostream> 
#include<windows.h> 
#include<winbase.h> 
using namespace std; 
#define SLEEP_TIME 50000 

typedef void* handle; 
typedef WINADVAPI BOOL (WINAPI *PInitializeSecurityDescriptor)(PSECURITY_DESCRIPTOR, DWORD); 
typedef WINADVAPI BOOL (WINAPI *PSetSecurityDescriptorDacl)(PSECURITY_DESCRIPTOR, BOOL, PACL, BOOL); 
#define LOGFILE "D:\\result.txt" 
handle temp=NULL; 
static int a=65; 
char muname[]={"NewMutex2"}; 
int errNm; 
char *str; 
FILE* log; 

SECURITY_ATTRIBUTES *g_pSaCms; 
SERVICE_STATUS ServiceStatus; 
SERVICE_STATUS_HANDLE hStatus; 

void ServiceMain(int argc, char** argv); 
void ControlHandler(DWORD request); 
int InitService(); 


bool Win32Mutex(char muname[8]) 
{ 

    HINSTANCE hAdvApi = LoadLibrary("Advapi32.DLL"); 
    PInitializeSecurityDescriptor pInitializeSecurityDescriptor = 0; 
    PSetSecurityDescriptorDacl pSetSecurityDescriptorDacl = 0; 
    PSECURITY_DESCRIPTOR pSD = 0; 
    g_pSaCms = new SECURITY_ATTRIBUTES; 
    if (g_pSaCms == 0) 
    { 
     prinerr(); 
     return 1; 
    } 
    memset(g_pSaCms,0X0, sizeof(*g_pSaCms)); 
    g_pSaCms->nLength = sizeof(*g_pSaCms); 
    g_pSaCms->bInheritHandle = 1; 

    pSD = new SECURITY_DESCRIPTOR; 

    if (pSD == 0) 
    { 
     printerr(); 
      goto LABEL_CSA_ERROR; 
    } 

    pInitializeSecurityDescriptor = (PInitializeSecurityDescriptor)GetProcAddress(hAdvApi,"InitializeSecurityDescriptor"); 

    if (pInitializeSecurityDescriptor == 0) 
    { 
     printerr(); 
      goto LABEL_CSA_ERROR; 
    } 

    pSetSecurityDescriptorDacl = (PSetSecurityDescriptorDacl)GetProcAddress(hAdvApi, "SetSecurityDescriptorDacl"); 

    if (pSetSecurityDescriptorDacl == 0) 
    { 
      goto LABEL_CSA_ERROR; 
    } 

    if (!(*pInitializeSecurityDescriptor)(pSD, SECURITY_DESCRIPTOR_REVISION) 
      || (!(*pSetSecurityDescriptorDacl)(pSD, TRUE, (PACL)0, FALSE))) 
    { 
      goto LABEL_CSA_ERROR; 
    } 

    (void)FreeLibrary(hAdvApi); 
    g_pSaCms->lpSecurityDescriptor=pSD; 
    goto LABEL_CSA_PASS; 

LABEL_CSA_ERROR: 
    (void)FreeLibrary(hAdvApi); 

    if (pSD != 0) 
    { 
     delete pSD; 
     pSD = 0; 
    } 

    if (g_pSaCms != 0) 
    { 
     delete g_pSaCms; 
     g_pSaCms = 0; 
    } 


LABEL_CSA_PASS: 
    temp=::CreateMutex(g_pSaCms,0,muname); //for icdcomm 
    errNm=GetLastError(); 
    if (!temp) 
    { 
     print_err(); 
    } 
    else 
    { 
     print_err(); 
    } 
    if ((!temp) || errNm == ERROR_ALREADY_EXISTS) 
    { 
      if(temp) 
      { 
      (void)CloseHandle(temp); 
      a++; 
      muname[8]=a; 
      Win32Mutex(muname); 
      } 
      else 
      { 
      printInf() 
      } 
      return 0; 
    } 
    return 1; 
} 



int main() 
{ 
    SERVICE_TABLE_ENTRY ServiceTable[2]; 
    ServiceTable[0].lpServiceName = "MemoryStatus"; 
    ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain; 

    ServiceTable[1].lpServiceName = NULL; 
    ServiceTable[1].lpServiceProc = NULL; 
    StartServiceCtrlDispatcher(ServiceTable); 
    return 0; 
} 

void ServiceMain(int argc, char** argv) 
{ 
    int error; 
    ServiceStatus.dwServiceType  = SERVICE_WIN32; 
    ServiceStatus.dwCurrentState  = SERVICE_START_PENDING; 
    ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; 
    ServiceStatus.dwWin32ExitCode  = 0; 
    ServiceStatus.dwServiceSpecificExitCode = 0; 
    ServiceStatus.dwCheckPoint   = 0; 
    ServiceStatus.dwWaitHint   = 0; 

    hStatus = RegisterServiceCtrlHandler(
     "MemoryStatus", 
     (LPHANDLER_FUNCTION)ControlHandler); 
    if (hStatus == (SERVICE_STATUS_HANDLE)0) 
    { 
     // Registering Control Handler failed 
     return; 
    } 
    // Initialize Service 
    error = InitService(); 
    if (error) 
    { 
     // Initialization failed 
     ServiceStatus.dwCurrentState  = SERVICE_STOPPED; 
     ServiceStatus.dwWin32ExitCode  = -1; 
     SetServiceStatus(hStatus, &ServiceStatus); 
     return; 
    } 

    // My service 
    muname[8]=a; 
    Win32Mutex(muname); 

    // We report the running status to SCM. 
    ServiceStatus.dwCurrentState = SERVICE_RUNNING; 
    SetServiceStatus (hStatus, &ServiceStatus); 


    // The worker loop of a service 
    while (ServiceStatus.dwCurrentState == SERVICE_RUNNING) 
    { 
     Sleep(SLEEP_TIME); 
    } 
    return; 
} 

// Control handler function 
void ControlHandler(DWORD request) 
{ 
    switch(request) 
    { 
     case SERVICE_CONTROL_STOP: 
      ServiceStatus.dwWin32ExitCode = 0; 
      ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
      SetServiceStatus (hStatus, &ServiceStatus); 
      return; 

     case SERVICE_CONTROL_SHUTDOWN: 

      ServiceStatus.dwWin32ExitCode = 0; 
      ServiceStatus.dwCurrentState = SERVICE_STOPPED; 
      SetServiceStatus (hStatus, &ServiceStatus); 
      return; 

     default: 
      break; 
    } 

    // Report current status 
    SetServiceStatus (hStatus, &ServiceStatus); 

    return; 
} 

Đối với mã thực thi (Mã số vẫn giống nhau, buc chỉ thay đổi trong chức năng chính)

int main() 
{ 
    muname[8]=a; 
    Win32Mutex(muname); 
    Sleep(SLEEP_TIME); 
    return 0; 
} 
+0

Bạn có ý nghĩa gì? Bạn đã nói rằng 'ERROR_ALREADY_EXIST' xuất hiện trong cả hai trường hợp (trên cả hai phiên bản Windows). Quy trình có thể chia sẻ (tên) mutex. Người ta sẽ tạo ra nó (dịch vụ trong trường hợp của bạn, vì nó chạy trước ứng dụng độc lập của bạn) và một ứng dụng khác (ứng dụng của bạn) sẽ mở nó (với 'CreateMutex' sẽ trả về' ERROR_ALREADY_EXIST'). –

+0

@Bojan: Không, anh ấy nói mã chạy trên Win7 *** mà không có *** 'ERROR_ALREADY_EXIST'. –

+0

Oooups, sai lầm của tôi, có quá nhiều cửa sổ đang mở, đang thực hiện đa nhiệm để bỏ qua từ :) –

Trả lời

16

Trên XP:

Dịch vụ, chạy trong sess ion bằng không, tạo ra mutex. Ứng dụng, cũng đang chạy trong phiên không, mở thành công một chốt xử lý cho mutex hiện tại và lỗi cuối cùng được đặt thành ERROR_ALREADY_EXISTS để cho bạn biết điều gì đã xảy ra.

Trên Windows 7:

Dịch vụ, chạy trong phiên không, tạo ra mutex. Ứng dụng, có thể đang chạy trong phiên một, tạo ra một mutex mới có cùng tên. Hai mutex là độc lập. Điều này là có thể bởi vì tên mutex được scoped đến phiên hiện tại.

Nếu bạn muốn mutexes để được chia sẻ bạn cần phải tạo ra chúng trong không gian tên toàn cầu bằng cách đặt trước tên với "Global \" tiền tố, ví dụ:

char muname[]={"Global\\NewMutex2"}; 

Bạn có thể tìm thêm chi tiết về session zero isolation đây .

+0

Cảm ơn bạn đã trả lời. Một câu hỏi tiếp theo, làm cách nào để tạo một đoạn mã duy nhất, hoạt động trên cả hai hệ điều hành trước Vista và pos-Vista. Chúng ta có thể sử dụng GLOBAL \ cho cả hai hệ điều hành WIN hoặc Do chúng ta cần phải bảo vệ loại mutex khác nhau với header guard.What là lời khuyên của bạn? –

+0

Bài viết này ngụ ý rằng "Toàn cầu" được hỗ trợ từ Windows 2000 trở đi: http://msdn.microsoft.com/en-us/library/windows/desktop/ms684292%28v=vs.85%29.aspx – arx

+0

Cảm ơn arx cho câu trả lời. Các giải pháp làm việc cho tôi – Baplix

Các vấn đề liên quan