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,您应该删除该代码,直到您的共享内存正常工作。