使用CreateFileMapping时出错 - C.

时间:2010-04-15 16:16:01

标签: c winapi

我正在使用this MSDN link上的教程来实现一种将数据从一个进程传输到另一个进程的方法。虽然我在earlier question中被建议使用Pipe方法,但由于某些限制,我别无选择,只能使用CreateFileMapping方法。

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

此外,我已经设法将MSDN示例中给出的代码实现到第一个(Producer)和第二个(Consumer)程序中,而没有任何编译错误。

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

我已经添加了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

编辑2:输出

Output Image

6 个答案:

答案 0 :(得分:3)

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

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

答案 1 :(得分:3)

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

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

  1. 从SysInternals
  2. 下载Process Explorer
  3. 运行Process Explorer
  4. 在CreateFileMapping()失败之前将应用程序运行到断点
  5. 使用查找(Ctrl-F)搜索 MyFileMappingObject
  6. 如果出现任何其他问题,例如另一个FileMap,Mutex等,请考虑一个更独特的名称,并确保您的应用程序不是创建它的人。
  7. 注意:考虑在Visual Studio中使用GUID(文件 - &gt;工具&gt;创建GUID)命名您的FileMapping

答案 2 :(得分:1)

答案 3 :(得分:1)

也许我们从过去的相同材料/例子中学到了东西。从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

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

  

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

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

在Windows 7下 我找到了:

OpenFileMapping(FILE_MAP_ALL_ACCESS, ...);

导致问题:

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

尝试:

OpenFileMappingA(SECTION_MAP_WRITE | SECTION_MAP_READ,...);