使用 CreateProcess() 的唯一配置文件的多个浏览器实例未提供预期输出

Posted

技术标签:

【中文标题】使用 CreateProcess() 的唯一配置文件的多个浏览器实例未提供预期输出【英文标题】:Multiple Browser Instance of unique profiles using CreateProcess() is not giving expected output 【发布时间】:2021-03-12 04:55:52 【问题描述】:

我在 Chrome 中有多个配置文件。配置文件名称类似于 - 配置文件 0、配置文件 1、.... 我正在使用 CreateProcess() 打开具有唯一配置文件的多个 chrome 实例。之后,我使用 CreateThread() 为每个进程分配一个线程。现在,如果我想使用下面的代码打开 2 个配置文件,例如配置文件 0 和配置文件 1,发生的情况是配置文件 0 和配置文件 2 正在打开。

如果我创建一个进程然后他们创建他们的线程并且我知道哪个线程是 chrome.exe,我有一个问题。那么有什么方法可以像在 CreateThread() 中那样使用 CreateProcess() 加入函数,我们可以传递 ThreadProcedure 函数。

#include <Windows.h>
#include <iostream>
#include <tlhelp32.h>

const int s = 125;   \\length of buffer containing Path of Chrome which I am giving in Commandline not in main but direectly to Create Process and it is absolutely fine.

using namespace std;

DWORD WINAPI ThreadProc(PVOID i)

    STARTUPINFOA si;

    PROCESS_INFORMATION pi;

    ZeroMemory(&si, sizeof(si));

    si.cb = sizeof(si);

    ZeroMemory(&pi, sizeof(pi));

    DWORD dwPID = GetCurrentProcessId();

    wprintf(L"ThreadProc %d() process ID is %u\n",*(int*)i, dwPID);

    DWORD dwTID = GetCurrentThreadId();

    wprintf(L"ThreadProc %d() thread ID is %u\n",*(int*)i, dwTID);

    char cmdline[s];

    sprintf_s(cmdline,s,"C:\\Program Files\\Google\\Chrome\\Application\\chrome.exe --profile directory=\"Profile %d\" https://www.google.com", *((int*)i));

    if (CreateProcessA(0, cmdline, 0, 0, FALSE, 0, 0, 0, &si, &pi))
    
        printf("Succed creating Process %d: ",*((int*)i));
        cout << "Proc Id-" << pi.dwProcessId << " Thread Id-" << pi.dwThreadId<<endl;
    
    else
    
        printf("Failure creating Process: %d",*((int*)i));
    
    return(0);


int main()

    int profiles;
    printf("profiles count: ");
    scanf_s("%d", &profiles);  \\Number of Profiles I want to open

    DWORD* threadId=(DWORD*)malloc(sizeof(DWORD) * profiles);
    HANDLE* hThread= (HANDLE*)malloc(sizeof(HANDLE) * profiles);

    int i = 0;
    for (; i < profiles; i++)
    
        hThread[i] = CreateThread(0, 0, ThreadProc, &i,0, &threadId[i]);

        if (hThread[i] == 0)
            cout << "Thread Creation Failed and Error Number->" << GetLastError();
        else
            cout << "Thread "<<i<< " Created->" << threadId[i] << endl;

    
    WaitForMultipleObjects(i,hThread,1,INFINITE);

【问题讨论】:

在多个线程之间共享 &amp;i 而不防范对 *&amp;i 的并发访问不会有好的结果。 哦,我明白了。是的,我是第一次做多线程,Petzold 的“Windows 编程”一书中没有太多关于多线程的材料。请您简要介绍一下如何做到这一点。 既然您真正需要的只是线程过程中i,为什么不简单地传递值而不是指向值的指针呢?多线程非常简单,直到您开始使用指针/引用。 iinspectable 因为 ThreadProcedure 采用 PVOID 表示指向 void 的指针。当我传递 i 时,它给了我错误。我尝试通过将 i 类型转换为 PVOID 并在 ThreadProcedute 中将它类型转换回 int。然后它没有给出错误,但输出很奇怪。 虽然我得到了解决方案,但有人发布并删除了它。我不知道他为什么那样做。但解决方案是在 for 循环中使用 WaitForMutipleObjects() 。我在下面给出代码。 【参考方案1】:

这里的核心问题是跨线程共享内存而不保护并发访问。当外部for 循环继续旋转并更新存储在i 中的值时,生成的线程同时取消引用内存位置&amp;i

严格来说,执行此操作的行为是未定义的,但实际上,在取消引用 &amp;i 时,生成的线程将观察到 012 的值,具体取决于它们查看的时间。

这一切都不需要发生。在这种情况下,生成的线程只需要i,而不是对其的引用。修复就像传递值一样简单,而不是指向它的指针:

#include <Basetsd.h> // For the conversion helpers

DWORD WINAPI ThreadProc(PVOID pv) 
    auto const i PtrToInt(pv) ;
    // Use i
    // ...


int main() 
    // ...
    int i;
    for (; i < profiles; i++) 
        hThread[i] = CreateThread(0, 0, ThreadProc, IntToPtr(i), 0, &threadId[i]);
        // ...
    
    // ...

通过这些更改,主线程和衍生的工作线程已经解耦,任何一个都可以在不依赖任何其他线程或数据的情况下向前推进。

不需要使用PtrToIntIntToPtr 助手。类型转换可以在 C++ 中完成,但结果相当冗长:

// Inside ThreadProc
auto const i static_cast<int>(reinterpret_cast<intptr_t>(pv)) ;
// Inside main
auto const pv reinterpret_cast<void*>(static_cast<intptr_t>(i)) ;

【讨论】:

完美男人。谢谢 。您如何或从哪里获得这些知识?

以上是关于使用 CreateProcess() 的唯一配置文件的多个浏览器实例未提供预期输出的主要内容,如果未能解决你的问题,请参考以下文章

CreateProcess:没有这样的文件或目录

使用 CreateProcess 和 regedit.exe 导入 reg 密钥?

Cannot run program “git.exe”: createprocess error=2,系统找不到指定的文件

idea2021配置svn报错Cannot run program “svn“ (in directory “xxx“):CreateProcess error=2,系统找不到指定的文件

idea2021配置svn报错Cannot run program “svn“ (in directory “xxx“):CreateProcess error=2,系统找不到指定的文件

不直接使用字符串时CreateProcess@Unhandled异常