You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

PowerShell执行策略已设置,从.NET程序调用时却不生效

解决管理员身份运行EXE时PowerShell脚本执行被禁用的问题

嘿,我来帮你排查这个头疼的问题!你遇到的情况其实挺典型的,核心原因主要有三个:32/64位PowerShell执行策略不共享启动参数格式有坑,还有管理员运行时工作目录跑偏。咱们一步步来解决:

1. 先搞懂执行策略的“双版本”陷阱

Windows里的PowerShell分32位和64位,它们的执行策略是分开存储的!你手动右键运行脚本时,大概率打开的是默认的64位PowerShell,但你的EXE如果是32位程序,以管理员身份运行时会调用32位PowerShell——而你之前设置的执行策略只对64位生效,32位那边还是保持禁用状态。

临时解决(或验证)办法:

  • 以管理员身份打开32位PowerShell(路径是C:\Windows\SysWOW64\WindowsPowerShell\v1.0\powershell.exe
  • 执行命令:Set-ExecutionPolicy Unrestricted -Scope CurrentUser(如果需要全局生效,把CurrentUser改成LocalMachine

不过更稳妥的方式是在启动PowerShell时直接绕过执行策略,不用改全局设置,看下面的代码修改。

2. 修正PowerShell启动参数的写法

你原来的参数写法有引号嵌套问题,很容易因为路径里的空格或特殊字符导致解析失败。而且直接用-File参数调用脚本比用&符号更可靠、不容易出错。

把原来的参数行改成:

process.StartInfo.Arguments = $"-ExecutionPolicy Bypass -File \"{strCmdText}\"";

-ExecutionPolicy Bypass会临时绕过当前会话的执行策略,不用修改系统全局设置,既安全又能解决问题。

3. 确保脚本路径绝对正确

管理员身份运行EXE时,进程的当前工作目录可能不是EXE所在的文件夹(默认会跳到C:\Windows\System32),这时候Directory.GetCurrentDirectory()就会返回错误路径,导致找不到脚本。

改成用程序集的位置来获取EXE所在目录:

string exeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
string strCmdText = Path.Combine(exeDir, "LiveSiteTests.ps1");

完整修改后的代码

if (File.Exists("LiveSiteTests.ps1")) 
{
    // 获取EXE所在目录,避免管理员运行时工作目录错误
    string exeDir = Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location);
    string strCmdText = Path.Combine(exeDir, "LiveSiteTests.ps1");

    var process = new Process();
    process.StartInfo.UseShellExecute = false;
    process.StartInfo.RedirectStandardOutput = true;
    // 注意:如果你的EXE是64位,用System32下的PowerShell;32位用SysWOW64下的
    process.StartInfo.FileName = @"C:\windows\system32\windowspowershell\v1.0\powershell.exe";
    // 临时绕过执行策略,用-File参数直接调用脚本
    process.StartInfo.Arguments = $"-ExecutionPolicy Bypass -File \"{strCmdText}\"";
    
    process.Start();
    string s = process.StandardOutput.ReadToEnd();
    process.WaitForExit();
    
    // 把输出文件也放到EXE目录,方便查看结果
    using (StreamWriter outfile = new StreamWriter(Path.Combine(exeDir, "StandardOutput.txt"), true))
    {
        outfile.Write(s);
    }
}

为什么之前的方式不行?

  • 执行策略分版本:32位和64位PowerShell的执行策略是独立存储的,你手动设置的是64位,但管理员运行32位EXE时调用的是32位PowerShell,之前的设置没生效。
  • 参数格式错误:原来的"&'" + strCmdText + "'"写法容易因为路径中的特殊字符导致解析失败,-File参数是调用脚本的标准方式,更稳定。
  • 工作目录问题:管理员身份运行时,当前目录默认是System32,不是EXE所在文件夹,导致脚本路径错误。

内容的提问来源于stack exchange,提问作者Michael Piraner

火山引擎 最新活动