2010-04-15 110 views
1

我正在使用this MSDN link上的教程來實現將數據從一個進程傳輸到另一個進程的方式。儘管我在earlier question中建議使用Pipe方法,但由於某些限制,我別無選擇,只能使用CreateFileMapping方法。使用CreateFileMapping時出錯 - C

現在,我已成功設法在同一解決方案中創建兩個獨立的窗體項目,並通過編輯同時加載兩個窗體的一些屬性。

此外,我設法將MSDN示例中給出的代碼實現到第一個(Producer)和第二個(Consumer)程序中,沒有任何編譯錯誤。

現在我遇到的問題是,當我運行第一個程序並嘗試創建映射文件的句柄時,我收到一個錯誤,說它不成功,我不明白爲什麼會發生這種情況。

我已經添加了生產者和消費者代碼文件來演示我正在嘗試做什麼。

監製

#include <windows.h> 
#include <stdio.h> 
#include <conio.h> 


//File header definitions 
#define IDM_FILE_ROLLDICE 1 
#define IDM_FILE_QUIT 2 
#define BUF_SIZE 256 

TCHAR szName[]=TEXT("Global\\MyFileMappingObject"); 
    TCHAR szMsg[]=TEXT("Message from first process!"); 

void AddMenus(HWND); 
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); 

////Standard windows stuff - omitted to save space. 

////////////////////// 
// WINDOWS FUNCTION // 
////////////////////// 
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
          WPARAM wParam, LPARAM lParam) 
{ 
    WCHAR buffer[256]; 
    LPCTSTR pBuf; 

    struct DiceData storage; 
    HANDLE hMapFile; 

    switch(message)  
    { 
    case WM_CREATE: 
     { 

      // Create Menus 
      AddMenus(hMainWindow); 
     } 

     break; 
    case WM_COMMAND: 
     // Intercept menu choices 
     switch(LOWORD(wParam)) 
     { 
     case IDM_FILE_ROLLDICE: 
      { 
       //Roll dice and store results in variable 
       //storage = RollDice(); 

       ////Copy results to buffer 
       //swprintf(buffer,255,L"Dice 1: %d, Dice 2: %d",storage.dice1,storage.dice2); 

       ////Show via message box 
       //MessageBox(hMainWindow,buffer,L"Dice Result",MB_OK); 

       hMapFile = CreateFileMapping(
       (HANDLE)0xFFFFFFFF, // use paging file 
       NULL,     // default security 
       PAGE_READWRITE,   // read/write access 
       0,      // maximum object size (high-order DWORD) 
       BUF_SIZE,    // maximum object size (low-order DWORD) 
       szName);     // name of mapping object 

    if (hMapFile == NULL) 
    { 
     MessageBox(hMainWindow,L"Could not create file mapping object",L"Error",NULL); 
     return 1; 
    } 
    pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object 
         FILE_MAP_ALL_ACCESS, // read/write permission 
         0,     
         0,     
         BUF_SIZE);   

    if (pBuf == NULL) 
    { 
     MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL); 

     CloseHandle(hMapFile); 

     return 1; 
    } 


    CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR))); 
    _getch(); 

    UnmapViewOfFile(pBuf); 

    CloseHandle(hMapFile); 

      } 
      break; 

     case IDM_FILE_QUIT: 
      SendMessage(hMainWindow, WM_CLOSE, 0, 0); 
      break; 
     } 
     break; 

    case WM_DESTROY: 
     PostQuitMessage(0); 
     break; 
    } 
    return DefWindowProc(hMainWindow, message, wParam, lParam); 
} 

// 
//Setup menus 
// 

消費者

#include <windows.h> 
#include <stdio.h> 
#include <conio.h> 

//File header definitions 
#define IDM_FILE_QUIT 1 
#define IDM_FILE_POLL 2 

#define BUF_SIZE 256 
TCHAR szName[]=TEXT("Global\\MyFileMappingObject"); 


//Prototypes 
void AddMenus(HWND); 
LRESULT CALLBACK WindowFunc(HWND, UINT, WPARAM, LPARAM); 

//More standard windows creation, again omitted. 

////////////////////// 
// WINDOWS FUNCTION // 
////////////////////// 
LRESULT CALLBACK WindowFunc(HWND hMainWindow, UINT message, 
          WPARAM wParam, LPARAM lParam) 
{ 


    HANDLE hMapFile; 
    LPCTSTR pBuf; 

    switch(message)  
    { 
    case WM_CREATE: 
     { 

      // Create Menus 
      AddMenus(hMainWindow); 
      break; 
     } 

    case WM_COMMAND: 
     { 
      // Intercept menu choices 
      switch(LOWORD(wParam)) 
      { 
      case IDM_FILE_POLL: 
       { 
        hMapFile = OpenFileMapping(
         FILE_MAP_ALL_ACCESS, // read/write access 
         FALSE,     // do not inherit the name 
         szName);    // name of mapping object 

        if (hMapFile == NULL) 
        { 
         MessageBox(hMainWindow,L"Could not open file mapping object",L"Error",NULL); 
         return 1; 
        } 

        pBuf = (LPTSTR) MapViewOfFile(hMapFile, // handle to map object 
         FILE_MAP_ALL_ACCESS, // read/write permission 
         0,      
         0,      
         BUF_SIZE);     

        if (pBuf == NULL) 
        { 
         MessageBox(hMainWindow,L"Could not map view of file",L"Error",NULL); 

         CloseHandle(hMapFile); 

         return 1; 
        } 

        MessageBox(NULL, pBuf, TEXT("Process2"), MB_OK); 

        UnmapViewOfFile(pBuf); 

        CloseHandle(hMapFile); 

        break; 
       } 




      case IDM_FILE_QUIT: 
       SendMessage(hMainWindow, WM_CLOSE, 0, 0); 
       break; 
      } 
      break; 
     } 

    case WM_DESTROY: 
     { 
      PostQuitMessage(0); 
      break; 
     } 
    } 
    return DefWindowProc(hMainWindow, message, wParam, lParam); 
} 

// 
//Setup menus 
// 

這絕非整齊,最後,但它僅僅是一個開始,感謝您的幫助。

編輯:錯誤

Error Image

EDIT2:輸出

Output Image

+0

另外有一點可以看:它看起來像你的製作人創建映射,映射,寫入,然後unmaps +關閉。文件映射對象只存在,而一些進程持有打開的句柄到它,所以一旦生產者關閉其手柄,*噗!* - 映射跑了,不會有任何的消費者在稍後打開。要以這種方式使用共享內存,至少有一個進程需要長期保存內存。例如,讓生產者在流程開始時打開並映射內存,並在流程結束時取消映射/關閉:只要客戶端查找它,它就會存在。 – BrendanMcK 2012-05-02 09:27:24

回答

3

您的製片人對我的作品的代碼。你使用的是哪個版本的Windows?在較新的版本(如Vista和7)中,訪問共享內存時存在額外的安全限制。在上面引用的MSDN文章中有關於此的說明,指出您必須是管理員才能在Windows Vista/7中創建全局共享內存對象。

您還應該調用GetLastError()以查看哪些錯誤代碼實際上是從CreateFileMapping()返回的,這可能有助於確定問題的根本原因。

+0

目前我正在使用Windows 7,就查看GetLastError而言,我可以簡單地創建一個緩衝區,調用GetLastError並將其顯示到MessageBox中? – 2010-04-15 18:18:56

+0

GetLastError()只是返回一個DWORD狀態代碼(您可以在MSDN的系統錯誤代碼列表中查找該消息)。你可以用MessageBox來顯示它,或者如果你有一個調試器,你可以通過程序來查看這個值。 – WildCrustacean 2010-04-15 18:25:42

+0

我試過使用「FILE_MAP_ALL_ACCESS」,但它沒有任何區別。 – 2010-04-15 18:54:46

1

在生產者代碼中,_getch()是否也適用於非控制檯應用程序?

+0

看起來很棒,不知道那裏是怎麼回事。我認爲我從MSDN文章中找到的示例是用於控制檯應用程序,我必須忘記刪除它。 – 2010-07-26 09:56:25

0

嘗試改變 「全球\ MyFileMappingObject」 到 「MyFileMappingObject」

3

確保全球名稱是唯一的;這可以使用名爲Process Explorer的工具完成。

如果不是唯一的,這通常在調用時CreateFileMappinng

  1. 下載Process Explorer Sysinternals公司的失敗,錯誤代碼爲6(句柄是無效)
  2. 運行的Process Explorer
  3. 運行你的應用遷移到()失敗
  4. 搜索MyFileMappingObject使用查找(Ctrl-F)
  5. 如果發生了任何事情,如另一個FileMap,互斥等。考慮一個更獨特的名稱,並確保您的應用程序不是一個創建它。

注:考慮命名使用GUID您的文件映射(文件 - >工具>創建GUID)的Visual Studio

1

也許我們從過去的相同材料/例子學到內。

NULL句柄返回值和GetLastError函數() = 5

ERROR_ACCESS_DENIED 
    5 (0x5) 
    Access is denied. 

系統錯誤代碼(0-499):http://msdn.microsoft.com/en-us/library/ms681382.aspx

我從遷移XP升級到Windows 7後有同樣的問題

我用像微軟例子反斜線lpName從http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx您在上面發佈。 從「全球\ MyFileMappingObject」到「GlobalMyFileMappingObject」改變文件映射對象(lpName)的名稱後,CreateFileMapping函數再次工作在Windows 7下,沒有其他變化。

「的名稱可以有一個‘全球\’或‘Local \’前綴在全球或會話命名空間顯式創建的對象。該名稱的其餘部分可以包含除反斜槓字符任何字符('\ 「)。創建從比會話零的會話全局命名空間文件映射對象需要SeCreateGlobalPrivilege特權。欲瞭解更多信息,請參閱Kernel Object Namespaces」。

這不只是一個名字改變!如果你需要訪問全局命名空間,那麼你必須去SeCreateGlobalPrivilege的方式。

0

在Windows 7 我發現:

OpenFileMapping(FILE_MAP_ALL_ACCESS, ...); 

原因與問題:

CreateFileMapping(
       (HANDLE)0xFFFFFFFF, // use paging file 

嘗試:

OpenFileMappingA(SECTION_MAP_WRITE | SECTION_MAP_READ,...);