【问题标题】:WINAPI Cpp - OpenFileMapping fails with error (2) ERROR_FILE_NOT_FOUND [duplicate]WINAPI Cpp - OpenFileMapping 失败并出现错误 (2) ERROR_FILE_NOT_FOUND [重复]
【发布时间】:2022-02-17 08:10:24
【问题描述】:

我正在尝试使用 WinApi 来 CreateFileMapping、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。

好吧,我不知道为什么我无法打开 Mapping。 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;
}

【问题讨论】:

  • openfilemapping 应该在一个程序中,而 createfilemapping 应该在另一个程序中。首先调用create,然后其他进程调用open。即使所有一个进程都必须先调用 create
  • @pm100 好吧,我正在运行一个程序的两个实例,所以有两个程序。首先我需要读取 PID,然后我决定是否要继续执行
  • 错误代码告诉你不存在同名的部分,当你尝试打开它时
  • @pm100 我知道我必须先创建,但我希望在不同的进程中运行相同的代码,所以首先,我需要检查是否已经有带有 PID 的内存,如果没有,我需要创建一个。我正在更改调用这两个函数的顺序,但效果相同
  • @RbMm 是的,我知道,但是代码没有理由找不到这个共享命名内存。至少我看不到原因

标签: c++ windows winapi shared-memory file-mapping


【解决方案1】:

您的日志清楚地显示[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() 试图打开它时,映射实际上并不存在。

您需要改为:

  • 在一个过程中,首先创建映射,并保持打开状态

  • 然后,在另一个进程中,在前一个进程中仍处于打开状态时打开映射

  • 那么,根据需要使用映射内存。

  • 然后,关闭两个进程中的映射。

您的代码也存在其他问题:

  • 将进程 ID 转换为字符串只是为了共享它。您可以将 ID 共享为二进制 DWORD

  • access_pid_from_memory() 实际上并没有从映射中读取任何内容(如果它能够打开它的话)。

  • main() 正在分配 t_pid 指向悬空内存。对stream.str() 的调用会产生一个临时 std::string,它会在c_str() 退出时立即销毁。

  • 我什至不知道您试图对环境变量和互斥体做什么,以及与共享内存有什么关系。就本文而言,您应该删除该代码,直到您的共享内存正常工作。

【讨论】:

  • 谢谢你的内心。在我的帖子中显示 main() 之前,我正在解释程序主要功能的原因。我开始编写带有锁定机制的程序,并尝试使 Microsoft 示例适应我的情况。整个事情还没有完成,这就是为什么函数读取内存没有写入缓冲区的原因。这是我现在正在做的事情。我需要的是整理我对映射使用的处理;当没有句柄时,我不知道对象销毁 - 感谢您的帮助。
  • @BartłomiejBłaszczyk “谢谢你的内情” - 我想你的意思是见解。你不想要我的 inside ;-)
  • - 将进程 ID 转换为字符串只是为了共享它。您可以改为将 ID 共享为二进制 DWORD。
    你会怎么做呢?
  • @BartłomiejBłaszczyk 只需将共享内存分配给sizeof(DWORD) 字节数,获取指向内存的DWORD* 指针,然后将原始进程ID DWORD 分配给该内存。
猜你喜欢
  • 1970-01-01
  • 2018-02-11
  • 2013-01-19
  • 2014-11-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-06
  • 2016-03-12
相关资源
最近更新 更多