2010-04-15 267 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,...);