WINAPI Cpp - OpenFileMapping 失败并出现错误 (2) ERROR_FILE_NOT_FOUND
WINAPI Cpp - OpenFileMapping fails with error (2) ERROR_FILE_NOT_FOUND
我正在尝试使用 WinApi 来创建文件映射、MapViewOfFile 和 CopyMemory。它没有向我显示错误,并且正在使用我的 PID
归档缓冲区
int write_pid_to_memory(const char *t_pid)
{
_tprintf(TEXT("[write_pid_to_memory] t_pid: (%s).\n"), t_pid);
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = CreateFileMapping(
INVALID_HANDLE_VALUE, // 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)
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
std::cout << "[write_pid_to_memory] strlen(t_pid) * sizeof(char) " << strlen(t_pid) * sizeof(char) << std::endl;
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
_getch();
std::cout << "p_buf " << p_buf << std::endl;
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
...但是从内存中读取
int access_pid_from_memory()
{
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
MessageBox(NULL, p_buf, TEXT("[access_pid_from_memory] Process2"), MB_OK);
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
我在尝试打开映射时遇到系统错误 (2)。
My PID: 19516
[access_pid_from_memory] Could not open file mapping object (2).
[write_pid_to_memory] t_pid: (19516).
[write_pid_to_memory] strlen(t_pid) * sizeof(char) 5
p_buf 19516
Envariamental variable = NEW
Env var value length = 3
Env var value compare resault = 0
Mutex created sucesfully
这些函数的代码来自
https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory
我唯一改变的是
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
而不是
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
其中 t_pid 只是一个 const char *,因为我厌倦了 Windows TCHAR 类型,而且我不知道如何将 DWORD ProcessID 转换为 TCHAR 以将其传递给 memcopy。
嗯,我不知道为什么我无法打开地图。 Windows 可能超出我的范围,我不知道
怎么样
TCHAR t_name[] = TEXT("Global\MyFileMappingObject");
应该被系统识别以找到我想从中读取消息的内存。
整个程序应该只锁定一个进程的执行,如果有一个名为“SO2”的值为“NEW”的系统变量,新进程应该停止执行前一个进程并继续为自己锁定程序。
锁定机制与互斥体一起查找以前的进程 ID,我希望将当前进程 ID 保存在内存中,以便下一个进程读取它的形式,当 sys var 为“新”时关闭它。
没什么疯狂的。 Linux 中的所有这些我都在一天内完成了,但是 Windows 简直要了我的命。
请帮忙
主要是如果有人感兴趣:
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <windows.h>
#include <string>
#include <conio.h>
#include <tchar.h>
#define BUFFER_SIZE 2048
#define ENV_KEY "SO2"
#define ENV_VAL "NEW"
#define BUF_SIZE 256
TCHAR t_name[] = TEXT("Global\MyFileMappingObject");
HANDLE h_mutex;
int write_pid_to_memory(const char *dw_pid);
int access_pid_from_memory();
int main(int argc, char **argv)
{
DWORD dw_pid = GetCurrentProcessId();
std::stringstream stream;
stream << dw_pid;
const char *t_pid = stream.str().c_str();
// int legnth = s_pid.length()
// const char *t_pid = (char*)malloc( * sizeof(char));
// const char t_pid = (char)malloc(strlen(dw_pid) * sizeof(char));
std::cout << "My PID: " << dw_pid << std::endl;
access_pid_from_memory();
write_pid_to_memory(t_pid);
std::string env_val(ENV_VAL);
char c_buffer[BUFFER_SIZE];
LPCSTR lp_name = ENV_KEY;
LPSTR lp_buffer = c_buffer;
DWORD dw_size = BUFFER_SIZE;
DWORD get_env_var;
//Write to memory your pid for other process to access it and close you
get_env_var = GetEnvironmentVariable(
lp_name,
lp_buffer,
dw_size);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
std::cout << "Couldn't find envariamental variable \"SO2\"." << std::endl;
}
if (BUFFER_SIZE == get_env_var)
{
std::cout << "Buffer for function [GetEnvironmentVariable] is too small. Function failed." << std::endl;
}
std::cout << "Envariamental variable = " << lp_buffer << std::endl;
std::string str_buffer(lp_buffer);
std::cout << "Env var value length = " << str_buffer.length() << std::endl;
std::cout << "Env var value compare resault = " << str_buffer.compare(env_val) << std::endl;
HANDLE h_mutex = NULL;
LPCSTR str = ENV_KEY;
h_mutex = OpenMutex(
MUTEX_ALL_ACCESS,
TRUE,
str);
if (NULL != h_mutex)
{
if (str_buffer.compare(env_val) == 0)
{
//Realease mutex3
ReleaseMutex(h_mutex);
//Close previous process
}
else
{
throw std::runtime_error("Instance of a program is already running");
}
}
h_mutex = CreateMutex(
NULL,
FALSE,
str);
if (h_mutex == NULL)
{
std::cout << "Failed to create mutex: error - " << GetLastError() << std::endl;
return 1;
}
std::cout << "Mutex created sucesfully" << std::endl;
DWORD dw_wait_res;
dw_wait_res = WaitForSingleObject(
h_mutex, // handle to mutex
INFINITE); // no time-out interval
for (;;)
{
Sleep(100);
}
CloseHandle(h_mutex);
system("PAUSE");
return 0;
}
您的日志记录清楚地显示 [access_pid_from_memory]
发生在 之前 [write_pid_to_memory]
.
我们可以在你的 main()
函数中清楚地看到它首先调用 access_pid_from_memory()
(它试图打开内存映射然后关闭它),然后调用 write_pid_to_memory()
(创建内存映射然后关闭它)。由于没有引用映射的活动句柄,它会在 write_pid_to_memory()
退出后立即被销毁。
所以,您的操作乱序,这就是 OpenFileMapping()
失败的原因。当 access_pid_from_memory()
试图打开它时,映射根本不存在。
您需要改为执行以下操作:
在一个进程中,首先创建映射,并保持打开状态。
THEN,在另一个进程中,打开映射,同时它在上一个进程.
中仍然打开
然后,根据需要使用映射内存。
然后,关闭两个进程中的映射。
您的代码还有其他问题:
将进程 ID 转换为字符串只是为了共享它。您可以将 ID 共享为二进制文件 DWORD
。
access_pid_from_memory()
实际上并没有从映射中读取任何内容(如果它能够打开的话)。
main()
正在分配 t_pid
以指向 悬空内存 。对 stream.str()
的调用会产生一个 临时 std::string
,一旦 c_str()
退出,它就会被销毁。
我什至不知道你想用你的环境变量和互斥量做什么,以及这与共享内存有什么关系。为此 post,您应该删除该代码,直到您的共享内存正常工作。
我正在尝试使用 WinApi 来创建文件映射、MapViewOfFile 和 CopyMemory。它没有向我显示错误,并且正在使用我的 PID
归档缓冲区int write_pid_to_memory(const char *t_pid)
{
_tprintf(TEXT("[write_pid_to_memory] t_pid: (%s).\n"), t_pid);
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = CreateFileMapping(
INVALID_HANDLE_VALUE, // 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)
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not create file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[write_pid_to_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
std::cout << "[write_pid_to_memory] strlen(t_pid) * sizeof(char) " << strlen(t_pid) * sizeof(char) << std::endl;
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
_getch();
std::cout << "p_buf " << p_buf << std::endl;
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
...但是从内存中读取
int access_pid_from_memory()
{
HANDLE h_map_file;
LPCTSTR p_buf;
h_map_file = OpenFileMapping(
FILE_MAP_ALL_ACCESS, // read/write access
FALSE, // do not inherit the name
t_name); // name of mapping object
if (h_map_file == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not open file mapping object (%d).\n"),
GetLastError());
return 1;
}
p_buf = (LPTSTR)MapViewOfFile(
h_map_file, // handle to map object
FILE_MAP_ALL_ACCESS, // read/write permission
0,
0,
BUF_SIZE);
if (p_buf == NULL)
{
_tprintf(TEXT("[access_pid_from_memory] Could not map view of file (%d).\n"),
GetLastError());
CloseHandle(h_map_file);
return 1;
}
MessageBox(NULL, p_buf, TEXT("[access_pid_from_memory] Process2"), MB_OK);
UnmapViewOfFile(p_buf);
CloseHandle(h_map_file);
return 0;
}
我在尝试打开映射时遇到系统错误 (2)。
My PID: 19516
[access_pid_from_memory] Could not open file mapping object (2).
[write_pid_to_memory] t_pid: (19516).
[write_pid_to_memory] strlen(t_pid) * sizeof(char) 5
p_buf 19516
Envariamental variable = NEW
Env var value length = 3
Env var value compare resault = 0
Mutex created sucesfully
这些函数的代码来自 https://docs.microsoft.com/en-us/windows/win32/memory/creating-named-shared-memory 我唯一改变的是
CopyMemory((PVOID)p_buf, t_pid, (strlen(t_pid) * sizeof(char)));
而不是
CopyMemory((PVOID)pBuf, szMsg, (_tcslen(szMsg) * sizeof(TCHAR)));
其中 t_pid 只是一个 const char *,因为我厌倦了 Windows TCHAR 类型,而且我不知道如何将 DWORD ProcessID 转换为 TCHAR 以将其传递给 memcopy。
嗯,我不知道为什么我无法打开地图。 Windows 可能超出我的范围,我不知道 怎么样
TCHAR t_name[] = TEXT("Global\MyFileMappingObject");
应该被系统识别以找到我想从中读取消息的内存。
整个程序应该只锁定一个进程的执行,如果有一个名为“SO2”的值为“NEW”的系统变量,新进程应该停止执行前一个进程并继续为自己锁定程序。
锁定机制与互斥体一起查找以前的进程 ID,我希望将当前进程 ID 保存在内存中,以便下一个进程读取它的形式,当 sys var 为“新”时关闭它。
没什么疯狂的。 Linux 中的所有这些我都在一天内完成了,但是 Windows 简直要了我的命。
请帮忙
主要是如果有人感兴趣:
#include <iostream>
#include <sstream>
#include <stdlib.h>
#include <windows.h>
#include <string>
#include <conio.h>
#include <tchar.h>
#define BUFFER_SIZE 2048
#define ENV_KEY "SO2"
#define ENV_VAL "NEW"
#define BUF_SIZE 256
TCHAR t_name[] = TEXT("Global\MyFileMappingObject");
HANDLE h_mutex;
int write_pid_to_memory(const char *dw_pid);
int access_pid_from_memory();
int main(int argc, char **argv)
{
DWORD dw_pid = GetCurrentProcessId();
std::stringstream stream;
stream << dw_pid;
const char *t_pid = stream.str().c_str();
// int legnth = s_pid.length()
// const char *t_pid = (char*)malloc( * sizeof(char));
// const char t_pid = (char)malloc(strlen(dw_pid) * sizeof(char));
std::cout << "My PID: " << dw_pid << std::endl;
access_pid_from_memory();
write_pid_to_memory(t_pid);
std::string env_val(ENV_VAL);
char c_buffer[BUFFER_SIZE];
LPCSTR lp_name = ENV_KEY;
LPSTR lp_buffer = c_buffer;
DWORD dw_size = BUFFER_SIZE;
DWORD get_env_var;
//Write to memory your pid for other process to access it and close you
get_env_var = GetEnvironmentVariable(
lp_name,
lp_buffer,
dw_size);
if (GetLastError() == ERROR_ENVVAR_NOT_FOUND)
{
std::cout << "Couldn't find envariamental variable \"SO2\"." << std::endl;
}
if (BUFFER_SIZE == get_env_var)
{
std::cout << "Buffer for function [GetEnvironmentVariable] is too small. Function failed." << std::endl;
}
std::cout << "Envariamental variable = " << lp_buffer << std::endl;
std::string str_buffer(lp_buffer);
std::cout << "Env var value length = " << str_buffer.length() << std::endl;
std::cout << "Env var value compare resault = " << str_buffer.compare(env_val) << std::endl;
HANDLE h_mutex = NULL;
LPCSTR str = ENV_KEY;
h_mutex = OpenMutex(
MUTEX_ALL_ACCESS,
TRUE,
str);
if (NULL != h_mutex)
{
if (str_buffer.compare(env_val) == 0)
{
//Realease mutex3
ReleaseMutex(h_mutex);
//Close previous process
}
else
{
throw std::runtime_error("Instance of a program is already running");
}
}
h_mutex = CreateMutex(
NULL,
FALSE,
str);
if (h_mutex == NULL)
{
std::cout << "Failed to create mutex: error - " << GetLastError() << std::endl;
return 1;
}
std::cout << "Mutex created sucesfully" << std::endl;
DWORD dw_wait_res;
dw_wait_res = WaitForSingleObject(
h_mutex, // handle to mutex
INFINITE); // no time-out interval
for (;;)
{
Sleep(100);
}
CloseHandle(h_mutex);
system("PAUSE");
return 0;
}
您的日志记录清楚地显示 [access_pid_from_memory]
发生在 之前 [write_pid_to_memory]
.
我们可以在你的 main()
函数中清楚地看到它首先调用 access_pid_from_memory()
(它试图打开内存映射然后关闭它),然后调用 write_pid_to_memory()
(创建内存映射然后关闭它)。由于没有引用映射的活动句柄,它会在 write_pid_to_memory()
退出后立即被销毁。
所以,您的操作乱序,这就是 OpenFileMapping()
失败的原因。当 access_pid_from_memory()
试图打开它时,映射根本不存在。
您需要改为执行以下操作:
在一个进程中,首先创建映射,并保持打开状态。
THEN,在另一个进程中,打开映射,同时它在上一个进程.
中仍然打开然后,根据需要使用映射内存。
然后,关闭两个进程中的映射。
您的代码还有其他问题:
将进程 ID 转换为字符串只是为了共享它。您可以将 ID 共享为二进制文件
DWORD
。access_pid_from_memory()
实际上并没有从映射中读取任何内容(如果它能够打开的话)。main()
正在分配t_pid
以指向 悬空内存 。对stream.str()
的调用会产生一个 临时std::string
,一旦c_str()
退出,它就会被销毁。我什至不知道你想用你的环境变量和互斥量做什么,以及这与共享内存有什么关系。为此 post,您应该删除该代码,直到您的共享内存正常工作。