本文介绍了使用 CreateProcess 运行批处理文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 CreateProcess 来启动一个新的环境块并在新的环境块中运行一个批处理文件.我已经阅读了 CreateProcess 的 msdn 示例,并得出了如下所示的代码.

I am trying to use CreateProcess to start a new environment block and run a batch file in the new environment block. I've read through the msdn example for CreateProcess, and came up with the code shown below.

发生了什么,它会打开新的命令提示符,然后停在那里.由于某种原因,它不会运行我的 .bat 文件.使用 system("CALL path") 将调用 .bat 文件.

What is happening, it will open the new command prompt, and stop there. It will not run my .bat file for some reason. Using system("CALL path") will call the .bat file.

#include <iostream>

#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>

#include <strsafe.h>

#define BUFSIZE 4096

int main()
{
    //system("CALL C:\HFSS\setup_vars.bat");

    //return 0;

    LPWCH chNewEnv;
    LPTSTR lpszCurrentVariable;
    DWORD dwFlags = 0;
    TCHAR szAppName[] = TEXT("C:\windows\system32\cmd.exe");
    TCHAR cmdArgs[] = TEXT("C:\HFSS\setup_var.bat");

    STARTUPINFO si;
    PROCESS_INFORMATION pi;
    BOOL fSuccess;

    // Copy environment strings into an environment block.
    chNewEnv = GetEnvironmentStrings();

    lpszCurrentVariable = (LPTSTR)chNewEnv;
    if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MySetting=A"))))
    {
        printf("String copy failed
");
        return FALSE;
    }

    lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
    if (FAILED(StringCchCopy(lpszCurrentVariable, BUFSIZE, TEXT("MyVersion=2"))))
    {
        printf("String copy failed
");
        return FALSE;
    }

    // Terminate the block with a NULL byte.

    lpszCurrentVariable += lstrlen(lpszCurrentVariable) + 1;
    *lpszCurrentVariable = (TCHAR)0;

    // Create the child process, specifying a new environment block.

    SecureZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb = sizeof(STARTUPINFO);

#ifdef UNICODE
    dwFlags = CREATE_UNICODE_ENVIRONMENT;
#endif

    fSuccess = CreateProcess(szAppName, cmdArgs, NULL, NULL, TRUE, dwFlags,
        (LPVOID)chNewEnv,   // new environment block
        NULL, &si, &pi);

    if (!fSuccess)
    {
        printf("CreateProcess failed (%d)
", GetLastError());
        return FALSE;
    }

    std::cout << "In new environment
";
    WaitForSingleObject(pi.hProcess, INFINITE);

    return TRUE;
}

推荐答案

一些问题:

  1. 您需要将 /C 选项传递给 cmd.exe 以使其执行 .bat 文件.
  2. CreateProcess 的第二个参数必须是可修改的字符串.不是字面意思.
  3. 您需要对文字中的反斜杠字符进行转义.
  4. lpszCurrentVariable 指向 GetEnvironmentStrings 返回的缓冲区.您不能修改该缓冲区.您需要分配一个足够长的新缓冲区并将环境复制到其中.然后添加您的修改.
  5. 环境块是双空终止的.标准字符串函数不适用于双空终止字符串.
  6. 使用StringCchCopy 之类的函数而不是C 运行时函数只是令人困惑.不要将 MSDN 示例代码视为风格的典范.
  7. C 字符串是要使用的绑定.但是你使用 C++ 所以使用 std::wstring 和其他标准库类和函数.
  8. 您需要在导入Windows.h之前定义WINDOWS_LEAN_AND_MEAN.
  9. 对于 C++,int main(void) 是不正确的.无参数 mainint main().
  1. You need to pass the /C option to cmd.exe in order to make it execute the .bat file.
  2. The second parameter to CreateProcess must be a modifiable string. Not a literal.
  3. You need to escape backslash characters in literals.
  4. lpszCurrentVariable points to the buffer returned by GetEnvironmentStrings. You cannot modify that buffer. You need to allocate a new buffer of sufficient length and copy the environment into it. Then add your modifications.
  5. Environment blocks are double null terminated. Standard string functions are of no use with double null terminated strings.
  6. Using functions like StringCchCopy rather than C runtime functions is just confusing. Don't take MSDN example code as being the paragon of style.
  7. C strings are a bind to work with. But you use C++ so use std::wstring and other standard library classes and function.
  8. You need to define WINDOWS_LEAN_AND_MEAN before importing Windows.h.
  9. For C++, int main(void) is incorrect. The no argument main is int main().

以下代码向您展示了如何执行此操作:

The following code shows you how to do this:

#include <cstring>
#include <string>
#include <iostream>

#define WINDOWS_LEAN_AND_MEAN
#include <Windows.h>

std::wstring GetEnvString()
{
    wchar_t* env = GetEnvironmentStrings();
    if (!env)
        abort();
    const wchar_t* var = env;
    size_t totallen = 0;
    size_t len;
    while ((len = wcslen(var)) > 0)
    {
        totallen += len + 1;
        var += len + 1;
    }
    std::wstring result(env, totallen);
    FreeEnvironmentStrings(env);
    return result;
}

int main()
{
    std::wstring env = GetEnvString();
    env += L"myvar=boo";
    env.push_back(''); // somewhat awkward way to embed a null-terminator

    STARTUPINFO si = { sizeof(STARTUPINFO) };
    PROCESS_INFORMATION pi;

    wchar_t cmdline[] = L"cmd.exe /C C:\Desktop\MyBatFile.bat";

    if (!CreateProcess(NULL, cmdline, NULL, NULL, false, CREATE_UNICODE_ENVIRONMENT,
        (LPVOID)env.c_str(), NULL, &si, &pi))
    {
        std::cout << GetLastError();
        abort();
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);
}

这篇关于使用 CreateProcess 运行批处理文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-29 16:10
查看更多