如何使用CreateProcessAsUserA添加过程参数

问题描述

我从中弄清楚了如何使用CreateProcessAsUserA()打开一个进程:

example code: A service calls CreateProcessAsUser() I want the process to run in the user's session,not session 0

现在,我需要添加过程参数以正确运行程序,我的意思是像-steam这样的参数。

我在Google上找不到任何解决方案。请帮助我。

解决方法

API is defined如此:

BOOL CreateProcessAsUserA(
  HANDLE                hToken,LPCSTR                lpApplicationName,LPSTR                 lpCommandLine,LPSECURITY_ATTRIBUTES lpProcessAttributes,LPSECURITY_ATTRIBUTES lpThreadAttributes,BOOL                  bInheritHandles,DWORD                 dwCreationFlags,LPVOID                lpEnvironment,LPCSTR                lpCurrentDirectory,LPSTARTUPINFOA        lpStartupInfo,LPPROCESS_INFORMATION lpProcessInformation
);

您可以将命令行附加到目标EXE的末尾。

因此,使用上面的示例,它看起来像这样:

rc = CreateProcessAsUserA(hUserToken,// user token
                       0,// app name
                       (LPSTR)"c:\\foo.exe -steam",// command line
                       0,// process attributes
                       0,// thread attributes
                       FALSE,// don't inherit handles
                       DETACHED_PROCESS,// flags
                       0,// environment block
                       0,// current dir
                       &si,// startup info
                       &pi);

对于lpCommandLine,此方法的“ A”版本不必为非常量,而另一方面,“ W”版本则为非常量。

如果可执行文件的路径中包含空格,则将其用引号引起来:

(LPSTR)"\"c:\\my files\\foo.exe\" -steam"

ETA:

对于如何为目标程序生成命令行存在一些困惑。为了使事物保持C样式(argv[0]是目标可执行文件的路径),您不应使用lpApplication参数,并且如果这样做,您仍希望lpCommandLine看起来就像上面一样。

文档中的信息:

如果lpApplicationNamelpCommandLine都不为NULL,则*lpApplicationName指定要执行的模块,而*lpCommandLine指定命令行。新进程可以使用GetCommandLine来检索整个命令行。用C编写的控制台进程可以使用argcargv参数来解析命令行。因为argv[0]是模块名称,所以C程序员通常将模块名称作为命令行中的第一个标记重复。

,

如果发现正确地引用正确的技巧,则可以创建一个函数来实现。

C ++ 17:

#include <initializer_list>
#include <string_view>
#include <utility>

// A function to prepare a commandline for execution by quoting
auto prep_cmd(std::initializer_list<std::string_view> args) {
    if(args.size()==0) throw std::runtime_error("No command,no fun");

    auto it = args.begin();

    std::string AppName(*it);                 // AppName is returned unchanged
    std::string CmdLine('"' + AppName + '"'); // but quoted when used in the commandline

    for(++it; it != args.end(); ++it) {
        CmdLine += ' ' + std::string(*it);            // add argument unquoted
        // CmdLine += " \"" + std::string(*it) + '"'; // or quote the argument too
    }
    return std::pair{AppName,CmdLine};               // return the result
}

然后称呼它:

auto[AppName,CmdLine] = prep_cmd({
    R"aw(C:\Program Files (x86)\Steam\steamapps\common\Counter-Strike Global Offensive\csgo.exe)aw","-steam"
});

使用结果:

    CreateProcessAsUserA(
        hToken,AppName.c_str(),// const char*
        CmdLine.data(),// char*
        ...
    );