在VC ++中获取子进程的环境变量

时间:2014-01-19 20:28:05

标签: windows winapi visual-c++

好的,这基本上就是我想要做的。我有一个流程P1。此过程需要在单独的进程cl.exe中调用Visual Studio命令行编译器P2(显然)。但是,正如使用Visual Studio命令行编译器的每个人都知道的那样,您不能简单地调用cl.exe并期望获得良好的体验。您必须首先运行批处理脚本%VSXXXCOMNTOOLS%\vsvars32.bat(其中XXX是Visual Studio版本号)。此脚本设置编译器使用的一些关键环境变量(例如用作包含路径的内容)。使用批处理脚本,这很容易做到:

call "%VS110COMNTOOLS%\vsvars32.bat"
...
cl Foo.cpp Bar.cpp ...

因为只是从批处理脚本调用批处理文件在同一个进程中运行(因此添加的环境变量是持久的)。在我意识到我需要更多的灵活性并决定将我的脚本移植到C ++之前,这是我过去常常做的事情,到目前为止,C ++运行得非常好。也就是说,直到我达到我需要实现实际编译的程度。

所以,这是我最终要解决的问题。我提出的最好的想法是使用cmd.exe /c "%VS110COMNTOOLS%\vsvars32.bat"在单独的进程P3中调用CreateProcess,等待该进程终止,然后从该子进程中提取修改后的环境变量。也就是说,P1创建P3并等待它完成。 P1然后将P3的环境变量设置为自己的。 P1然后创建P2并设置这些环境变量。所以代码看起来大致如下(减去所有错误检查):

...
CreateProcess(TEXT("cmd"), TEXT("/c \"%VS110COMNTOOLS%\vsvars32.bat\""), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

WaitForSingleObject(pi.hProcess, INFINITE);

/* Set current process environment using pi.hProcess */
CloseHandle(pi.hProcess);

...

CreateProcess(TEXT("cl"), TEXT("..."), NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi);

这将是首选解决方案。我不完全确定这样的事情是否可行,但根据我的研究,似乎有一种方法可以在.NET中执行此操作,而ProcessExplorer似乎能够读取任意环境过程,所以我认为这样的解决方案是可能的。我似乎无法找到任何能够从子进程获取环境变量的文档化函数。还有一个旧的讨论与MSDN上的类似。其中一个回复提到将Merge Environment设置为yes。任何人都知道那是什么意思?我似乎无法找到任何文件。

如果事实证明这是不可能的,我想到的替代解决方案是:(1)编写一个简单调用vsvars32.bat的批处理脚本,然后使用输入参数调用cl.exe,(2)调用cmd而不是cl使用参数运行vsvars32.bat然后编译(类似于1,但更具可扩展性......但不确定是否可行),或(3 )将环境变量打印到文件中然后读取它们。如果可能,我宁愿不使用任何此类解决方案。

我也愿意接受其他建议。只要知道我需要做的99%已经完成,所以首选干净,非黑客的解决方案。

2 个答案:

答案 0 :(得分:4)

执行此操作的干净方法是运行vcvars32以设置所有环境变量,然后运行您的流程P1

cmd /C vcvars32.bat && P1

请注意,用户无需手动执行此操作。使用此目标创建快捷方式:

cmd /C ""C:\Some Path\vcvarsall.bat" && start /separate C:\SomeOtherPath\YourGui.exe"

设置环境变量,然后启动GUI应用程序。一旦GUI应用程序启动,start /separate就会停止命令提示符。如果您还希望从命令行运行方便,可以将其全部放在批处理文件中。

如果由于某种原因您不想这样做,从批处理脚本获取环境变量的最简单方法是运行:

cmd /U /C vcvars32.bat && set

这会将值写入Unicode中的标准输出。您可以使用管道来检索值。这比尝试从另一个进程的内存中检索变量要小得多。

N.B。如果要在命令提示符下对此进行测试,则需要运行:

cmd /U /C "vcvars32.bat && set"

引号确保set在子命令处理器中运行。

答案 1 :(得分:1)

不要跨进程边界检索和设置环境变量。在同一过程中运行vsvars32.batcl.exe,就像它们的目的一样。 cmd.exe允许您使用&&运算符一次执行多个命令:

cmd.exe /c "\"%VS110COMNTOOLS%\vsvars32.bat\" && cl ..."
相关问题