【问题标题】:Set ProcessStartInfo.EnvironmentVariables when Verb="runas"当 Verb="runas" 时设置 ProcessStartInfo.EnvironmentVariables
【发布时间】:2012-08-03 09:03:06
【问题描述】:

我正在开发一个 C# 应用程序。

我需要创建变量并将其传递给一个新进程,我正在使用ProcessStartInfo.EnvironmentVariables 进行。

新进程必须运行提升,所以我使用 Verb = "runas"

var startInfo =  new ProcessStartInfo(command)
{
    UseShellExecute = true,
    CreateNoWindow = true,
    Verb = "runas"
};
foreach (DictionaryEntry entry in enviromentVariables)
{
    startInfo.EnvironmentVariables.Add(entry.Key.ToString(), entry.Value.ToString());
}

问题是根据msdn documentation

您必须将 UseShellExecute 属性设置为 false 才能在更改 EnvironmentVariables 属性后启动进程。如果UseShellExecute 为真,则在调用 Start 方法时会抛出 InvalidOperationException

runas 变量需要 UseShellExecute=true

有没有办法同时做到:以提升的身份运行进程并设置环境变量?

编辑

我会尝试改写我的问题...

有没有办法将参数安全地传递给另一个进程,这样只有另一个进程才能读取参数。

【问题讨论】:

  • 可能不太好,但可能会起作用:首先创建一个批处理文件并使用 setx /M 键值设置环境变量。您首先运行批处理脚本,然后运行真正的命令。不过,这会使您的机器范围内的环境变量变得混乱。
  • 谢谢,但这可能会导致安全漏洞,因为在此用户下运行的每个人都可以读取全局环境变量
  • 是的,我已经说过这不好......这是轻描淡写:-(
  • 您是否尝试设置环境变量(通过 System.Environment.SetEnvironmentVariable(key, balue));然后开始这个过程?
  • 但是当 UseShellExecute = true 时我该怎么做呢?

标签: c# environment-variables processstartinfo runas


【解决方案1】:

它可以工作,但缺点是它还显示第二个命令提示符,环境变量仅在已启动进程的上下文中设置,因此设置不会传播到整个框。

    static void Main(string[] args)
    {
        var command = "cmd.exe";
        var environmentVariables = new System.Collections.Hashtable();
        environmentVariables.Add("some", "value");
        environmentVariables.Add("someother", "value");

        var filename = Path.GetTempFileName() + ".cmd";
        StreamWriter sw = new StreamWriter(filename);
        sw.WriteLine("@echo off");
        foreach (DictionaryEntry entry in environmentVariables)
        {
            sw.WriteLine("set {0}={1}", entry.Key, entry.Value);
        } 
        sw.WriteLine("start /w {0}", command);
        sw.Close();
        var psi = new ProcessStartInfo(filename) {
            UseShellExecute = true, 
            Verb="runas"
        };
        var ps =  Process.Start(psi);
        ps.WaitForExit();
        File.Delete(filename);
    }

【讨论】:

  • 谢谢!你知道这种方法有多安全吗?
  • 非常安全或非常不安全,取决于您的上下文。你打算做非常不安全的事情吗?
  • 我正在向我的应用程序传递密码。我需要除了新进程之外没有人能够读取密码。我还在检查 exe 是否在调用它之前签名。
  • 那么不要使用临时批处理文件,因为它在程序运行期间是可读的。您可以使用通过共享内存块接收密码的自定义包装程序。 (并在收到后立即覆盖。)
  • 您打算将密码存储在哪里?
【解决方案2】:

有一个更好的答案:您仍然可以使用具有 UseShellExecute = true 的 ProcessStartInfo 调用 Process.Start(),前提是您调用它的方法已使用 [STAThread] 属性进行标记。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-03-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-13
    相关资源
    最近更新 更多