使用ReadFile函数从进程中读取数据



我正在尝试使用Win32 API函数ReadFile()从进程读取数据。我没有使用标准库函数,因为我使用的是来自公共repo的源代码。在这里,我提供了我遇到问题的特定片段。。

//Those are Globals
HANDLE pipin_w, pipin_r, pipout_w, pipout_r;
DWORD write, read, available;
BYTE buffer[2048];
std::string myFunction(){
std::string out="";
PeekNamedPipe ( pipout_r, buffer, sizeof(buffer), &read, &available, NULL);
sleep(300);
do {
ZeroMemory(*buffer, sizeof(buffer));
ReadFile( pipout_r, buffer, sizeof(buffer), &read, NULL);
if (!read) { return std::string("error"); }
buffer[read]=0;
out += (char*)buffer;
} while(read >= sizeof(buffer));
return out;
}

前两个调用的响应正确,而返回的是"error"

我无法使用和理解标准库函数,因为我没有C++编程经验。我想做的是填充大小为2048的BYTE缓冲区。

此代码适用于前两个调用,然后read变量被损坏。我知道我的初始化是正确的,因为我能够连接到在任务管理器中打开自己的进程,也能够从中检索数据,但在两次调用后,read变量会损坏。

这会导致我的代码挂起或崩溃。这个代码有一些地方我不喜欢。例如,我无法使用像fstream这样的标准库函数,所以我决定暂时使用此设置。此外,我不知道用ReadFile()函数从流程中读取是否正确,但这种方法确实有效。while循环让我感到很不舒服,我不明白为什么我需要它。

任何想知道我是如何初始化这个代码的人,都可以问,我会提供每一个缺失的信息,但我不认为这是一个问题,因为我可以从过程本身进行一些解读。我可以提供一个链接到我正在使用的源代码,因为这是一个公共源代码存储库。

可能被问到的问题(来自你(:

  1. 您的流程支持读取吗?

    是的,它做

  2. 您是否有足够的权限运行和读取该进程?

    是的,我有

  3. 也许你需要写一些数据来告诉开始沟通的过程。。

    事实并非如此,我有另一个写数据的函数,在这次调用之前我使用了它,但即使我不写,我仍然会收到数据

  4. 您是如何创建流程的?

    我可以提供这个片段,只要问我,但重要的是,我创建了两个管道,一个用于阅读,另一个用于写作,然后我通过调用CreateProcess来启动这个过程,这很有效。

  5. 你想用你的代码做什么?

    我正在尝试用c++构建一个类,它可以在Windows平台环境中处理进程的创建、写入和读取,仅此而已。。

什么可能导致read变量损坏?我很难理解这一点,以及我如何避免这种情况。此外,如果有人能向我解释这种情况下的良好做法,我真的很感激,或者至少能链接到我可以查看的一些资源,或者研究它是如何工作的。

  • ZeroMemory(*buffer, sizeof(buffer));应该是ZeroMemory(buffer, sizeof(buffer));
    在其当前状态下,读取buffer中的第一个BYTE,并将其用作开始归零的地址。这会导致未定义的行为
  • buffer[read]=0;可能写入越界。如果您已经阅读了2048BYTEs,那么您有未定义的行为
  • out += (char*)buffer;读取buffer,直到找到——但没有必要这样做,因为您已经知道自己读取了多少BYTE

修复:

  • 删除ZeroMemory-您将只读取由ReadFile填充的内存,因此先将其清零只是浪费时间
  • 替换
    buffer[read]=0;
    out += (char*)buffer;
    
    具有
    out.append(reinterpret_cast<char*>(buffer), read);
    

此外,请检查您调用的函数的返回值。例如CCD_ 23可能会失败。

崩溃都消失了,在我将强制转换恢复为char指针后,我不太理解强制转换,但由于我首先将char指针初始化为nullptr来分配内存,然后我使用memset来分配更大的缓冲区,不知怎的,我的方法适用于这种情况,因为如果我需要的话,我不会在代码中的其他地方使用它,我只是使用std::string将它复制到一个新的初始化字符串中,这样就解决了连续崩溃的问题,而且我无法找到更好的方法。

接下来,我预测的也是一个崩溃,它实际上是ReadFile函数的一个无限循环,它发生在两种情况下。

  1. 当我传递一个"错误"的字符串与它通信时,一些特殊的字符(如\或/(

  2. 当缓冲区没有可从应用程序读取的内容,并且应用程序返回空输出时

仍然不确定如何处理第二种情况:(但至少我可以继续调试…:(

最新更新