将新环境变量添加到ProcessStartInfo.LoadUserProfile启动的进程中

时间:2010-12-22 16:39:09

标签: c# environment-variables

我使用用户'podosta'

登录我的电脑

这样可以正常使用

ProcessStartInfo p = new ProcessStartInfo("c:\myapp.exe");
p.UserName = "myuser";
p.Domain = "mydomain";
p.Password = SecureString;
p.UseShellExecute = false;
p.LoadUserProfile = true;
Process.Start(p);

进程的环境变量是用户'myuser'的环境变量 例如:%USERPROFILE%指向'myuser'

的个人资料

这不起作用

ProcessStartInfo p = new ProcessStartInfo("c:\myapp.exe");
p.UserName = "myuser";
p.Domain = "mydomain";
p.Password = SecureString;
p.UseShellExecute = false;
p.LoadUserProfile = true;
p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT");
Process.Start(p);

过程的环境变量是我'podosta'的环境变量 例如:%USERPROFILE%指向我的个人资料'podosta' 顺便说一句,%MY_NEW_VARIABLE%已创建

为什么会出现这种情况? 我需要使用RunAs启动一个应用程序,具有已运行用户的环境并向该进程添加一些额外的环境变量。

由于

1 个答案:

答案 0 :(得分:0)

您所看到的行为基本上是MSDNCreateProcessWithLogon Win32函数的文档,该函数在为其他用户启动进程时使用后台工作(使用System.Diagnostics.Process):< / p>

  

指向新进程的环境块的指针。如果这   参数为NULL,新进程使用从中创建的环境   由lpUsername指定的用户的配置文件。

因此,只要为新流程指定单个环境变量,就需要全部指定它们。

现在的问题是ProcessStartInfo.EnvironmentVariables属性。一旦您第一次访问它(对于给定的ProcessStartInfo实例),它将自动填充当前用户的完整环境(ref)。

选择此行,该行在用户“podosta”的上下文中运行:

p.EnvironmentVariables.Add("MY_NEW_VARIABLE", "SOME_TEXT");

它做了两件事:

  1. 使用“podosta”(包括“USERPROFILE = ... podosta”)的环境填充p.EnvironmentVariables
  2. 添加新变量“MY_NEW_VARIABLE = SOME_TEXT”。
  3. 然后将这个组合集传递给作为“myuser”启动的进程,从而获得“USERPROFILE”的“错误”(更好:意外)值。

    如果您想确保将NULL环境块传递给基础Win32函数,为了获得上面引用中描述的行为,您不能“触摸”EnvironmentVariables属性 - 甚至没有迭代并转储它以用于记录目的。

    EnvironmentVariables.Clear()也不够。这不会将内部字段设置为null,而CreateProcessWithLogon函数只是传递一个空的环境块,而不是空的。

    如果你没有这样做,你会得到各种有趣的行为,例如,当时正在执行的过程将具有USERPROFILE的值,即开始该过程的用户的值等。

    您可以通过p / invoke调用CreateEnvironmentBlock,根据需要添加环境变量,然后调用CreateProcessAsUser(也通过p / invoke),传递修改后的环境来解决这些问题。这不是一件容易的事,特别是当你想要Process类的所有功能时,比如输出重定向等等。

    ProcessStartInfo.EnvironmentVariables属性的工作原理很不幸。