如何解决更改调用过程的环境变量
| 这个看似微不足道,但是答案已经使我隐瞒了几天。 我有一个Windows批处理文件,该文件调用C#程序执行无法在批处理文件中完成的额外验证。验证完成后,我需要将状态和字符串返回给调用shell。 现在返回值是微不足道的,并且我的C#控制台应用程序只需设置一个返回值(如果愿意,可以设置退出代码)。而且我认为这串菜也将是小菜一碟。我试图使用以下命令定义一个新的shell变量:Environment.SetEnvironmentVariable(\"ERR\",\"Some text\");
该调用应该(并且确实)在当前进程中定义一个shell变量-这就是创建变量的C#进程。一旦C#应用程序终止并且创建C#应用程序的外壳对该变量一无所知,该值就会丢失。所以...没有特殊用途的调用...完全...除非除非我从C3应用程序创建了一个子进程,否则它可能会继承我的变量。
SetEnvironmentVariable调用的EnvironmentVariableTarget.Machine和EnvironmentVariableTarget.User目标也不能解决问题,因为只有新创建的进程才能从注册表中获取这些新值。
因此,我能想到的唯一可行的解决方案是:
写入标准输出
写入文件
将额外的含义编码为返回值
前两个有点难看,最后一个有其局限性和问题。
还有其他想法(如何在父进程中设置shell变量)?也许这样的shell变量修改是出于安全考虑(请考虑PATH)...
感谢您的时间。
解决方法
我遇到了与Ryan相同的问题,作为解决方法,我想到的唯一一件事就是错误地写出一个批处理来设置变量并从该批处理中调用它。
ConsoleApplication1.exe:
\'put some sensible code here
\'put result in variable myResult
Dim myResult As String = Guid.NewGuid().ToString(\"D\").ToUpperInvariant()
Console.WriteLine(\"Normal output from the consonle app\")
Console.Error.WriteLine(\"@ECHO OFF\")
Console.Error.WriteLine(\"SET zzzResult={0}\",myResult)
Test.cmd(调用批处理):
@ECHO OFF
:Jump to folder of batch file
PUSHD %~d0%~p0
:Define a temp file
SET zzzTempFile=%TEMP%\\TMP%Random%.CMD
:Call .NET console app
ConsoleApplication1.exe 2>%zzzTempFile%
:Call the generated batch file
CALL %zzzTempFile%
:Clean up temp file
DEL %zzzTempFile%
:Clean up variable
SET zzzTempFile=
:Do something with the result
ECHO Yeah,we finally got it!
ECHO:
ECHO The value is \"%zzzResult%\".
ECHO:
:Clean up result variable
SET zzzResult=
:Go back to original folder
POPD
这应该够了吧。是的,我的确知道这是一篇老文章,而Ryan现在正在解决其他问题,但是可能还有其他人存在相同的问题...
,您要问的是能够任意写入正在运行的进程的内存空间。出于充分的原因,没有SeDebugPrivilege是不可能的。
您列出的三种解决方案中的任何一种都可以使用。 Stdout是与批处理脚本进行通信的标准方法。
顺便说一句,您正在编写Windows批处理文件。我很确定这艘船已经驶过“有点难看”了。
,如果要在批处理中将某些输出的值放入变量中,则可以使用以下构造:
FOR /F \"usebackq tokens=4 delims=\\[\\] \" %i IN (`ver`) DO set VERSION=%i
ECHO %VERSION%
我的操作系统上的输出:
6.1.7601
\'usebackq \'表示我们正在使用反引号,从而可以在命令中使用双引号将文件集使用。您可能不需要这个。 \'tokens'表示要在结果字符串数组中选择的索引(可以是M-N范围)。如果您需要跳过行,请使用\'skip = X \')。 \'delims \'是要使用的字符串分隔符(如.Net中的string-Split())。
您将放置控制台应用程序而不是\'ver \',并修改定界符和标记以匹配您的特定输出。如果要填充的变量更多,则需要使if稍微复杂一些,但这应该是一个好的开始。
,我的BAT有点生锈,但是我认为可以从外部运行的进程(可能通过via5)检索“退出”代码。如果是这种情况,请确保通过退出程序
Environment.Exit(123); // where 123 = error code
您无法添加任何消息,因此必须在.bat文件中进行添加。
如果不是这种情况,则stdout可能是最好的方法。
,在我自己也对此有所迷恋之后,我想到了这种方法。我所做的是使用Process类运行bat文件,即
// Spawn your process as you normally would... but also have it dump the environment varaibles
Process process = new Process();
process.StartInfo.FileName = mybatfile.bat;
process.StartInfo.Arguments = @\"&&set>>envirodump.txt\";
process.StartInfo.UseShellExecute = false;
process.StartInfo.RedirectStandardOutput = true;
process.StartInfo.RedirectStandardError = false;
process.Start();
string output = process.StandardOutput.ReadToEnd();
process.WaitForExit();
// Read the environment variable lines into a string array
string[] envirolines = File.ReadAllLines(\"envirodump.txt\");
File.Delete(\"envirodump.txt\");
// Now simply set the environment variables in the parent process
foreach(string line in a)
{
string var = line.Split(\'=\')[0];
string val = line.Split(\'=\')[1];
Environment.SetEnvironmentVariable(var,val);
}
这似乎对我有用。这不是最干净的方法,但可以绑定使用。 :)
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。