使用CreateFileMapping时出错 – C

我正在使用此MSDN链接上的教程来实现一种将数据从一个进程传输到另一个进程的方法。 虽然我在之前的一个问题中被告知使用Pipe方法,但由于某些约束,我别无选择,只能使用CreateFileMapping方法。

现在,我已经成功地在同一个解决方案中创建了两个单独的窗口窗体项目,并通过编辑一些属性同时加载两个窗体。

此外,我设法将MSDN示例中给出的代码实现到第一个(生产者)和第二个(消费者)程序中,没有任何编译错误。

我现在遇到的问题是当我运行第一个程序并尝试创建映射文件的句柄时,我收到一个错误,说它不成功,我不明白为什么会发生这种情况。

我已经添加了Producer和Consumer代码文件来演示我想要做的事情。

制片人

#include  #include  #include  //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  #include  #include  //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 // 

它绝不是整洁和最终的,但它只是一个开始,感谢任何帮助。

编辑:错误

错误图片

Edit2:输出

输出图像

您的生产者代码适合我。 您使用的是哪个版本的Windows? 在较新的版本(如Vista和7)中,访问共享内存存在额外的安全限制。 在上面引用的MSDN文章中有一个关于此的说明,表示您必须是管理员才能在Windows Vista / 7中创建全局共享内存对象。

您还应该调用GetLastError()以查看从CreateFileMapping()实际返回的错误代码,这可能有助于确定问题的根本原因。

确保全局名称是唯一的; 这可以使用名为Process Explorer的工具完成。

如果不是唯一的,那么在调用CreateFileMappinng时,这通常会失败,错误代码为6(句柄无效)

  1. 从SysInternals下载Process Explorer
  2. 运行Process Explorer
  3. 在CreateFileMapping()失败之前运行应用程序直到断点
  4. 使用Find(Ctrl-F)搜索MyFileMappingObject
  5. 如果出现任何其他问题,例如另一个FileMap,Mutex等,请考虑一个更独特的名称,并确保您的应用程序不是创建它的人。

注意:考虑使用Visual Studio中的GUID(文件 – >工具>创建GUID)命名FileMapping

在生产者的代码中,_getch()是否也适用于非控制台应用程序?

也许我们从过去的相同材料/例子中学到了东西。 从XP迁移到Windows 7后我遇到了同样的问题:

NULL处理返回值和GetLastError() = 5。

 ERROR_ACCESS_DENIED 5 (0x5) Access is denied. 

系统错误代码(0-499): http : //msdn.microsoft.com/en-us/library/ms681382.aspx

我在上面发布的http://msdn.microsoft.com/en-us/library/windows/desktop/aa366537.aspx上的Microsoft示例中使用了带反斜杠的lpName。 将文件映射对象(lpName)的名称从“Global \ MyFileMappingObject”更改为“GlobalMyFileMappingObject”后,CreateFileMapping函数在Windows 7下再次运行,没有其他更改。

“该名称可以具有”Global \“或”Local \“前缀,以在全局或会话命名空间中显式创建对象。名称的其余部分可以包含除反斜杠字符(’\’)之外的任何字符。 创建文件从会话零以外的会话中映射全局命名空间中的对象需要SeCreateGlobalPrivilege特权 。有关更多信息,请参阅“ 内核对象命名空间 ”。

这不仅仅是改变名称! 如果您需要访问全局命名空间,那么您必须采用SeCreateGlobalPrivilege方式。

尝试将“Global \ MyFileMappingObject”更改为“MyFileMappingObject”

在Windows 7下我发现:

 OpenFileMapping(FILE_MAP_ALL_ACCESS, ...); 

导致问题:

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

尝试:

 OpenFileMappingA(SECTION_MAP_WRITE | SECTION_MAP_READ,...);