我正在使用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
//
这绝不是整洁和最终的,但它只是一个开始,感谢任何帮助。
编辑:错误
编辑2:输出
答案 0 :(得分:3)
您的制作人代码适合我。您使用的是哪个版本的Windows?在较新的版本(如Vista和7)中,访问共享内存存在额外的安全限制。在上面引用的MSDN文章中有一个关于此的说明,表示您必须是管理员才能在Windows Vista / 7中创建全局共享内存对象。
您还应调用GetLastError()以查看实际从CreateFileMapping()返回的错误代码,这可能有助于确定问题的根本原因。
答案 1 :(得分:3)
确保全局名称是唯一的;这可以使用名为Process Explorer的工具完成。
如果不是唯一的,那么在调用CreateFileMappinng时,这通常会失败,错误代码为6(句柄无效)
注意:考虑在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,...);