返回

Windows Sandbox 自动执行 PowerShell 脚本最佳实践

windows

Windows Sandbox 与 PowerShell:启动时自动执行脚本的正确姿势

经常有朋友问我,在 Windows Sandbox 里怎么让 PowerShell 脚本在启动时自动运行,并且确保脚本有足够的执行权限?网上的教程五花八门,有的还不管用,挺头疼的。这篇就来把这个问题彻底讲透,包教包会。

一、问题出在哪儿?

按照你提供的配置,问题主要集中在这几个方面:

  1. 执行策略的层级: Set-ExecutionPolicy 可以设置多个层级的执行策略,例如 CurrentUser, LocalMachine, Process 等。即使你设置了 CurrentUser 的策略,Process 级别的策略(默认为 Restricted)仍然可能阻止脚本执行。

  2. Sandbox 的生命周期: 每次 Sandbox 启动都是一个全新的环境。你在 start.ps1 脚本里做的设置只对那一次的 Sandbox 会话有效,关闭后就没了。下一次启动,执行策略又会恢复到默认值。

  3. WSB 配置文件的局限性 : <LogonCommand> 只在用户登录时执行一次命令。如果你在命令中使用了 start powershell 创建了新的 PowerShell 进程,那么主 PowerShell 进程中做的设置(例如通过 -ExecutionPolicy Unrestricted 传递的策略)可能不会传递给新的子进程. 而且, 因为沙盒是一个纯净环境, 上一个命令创建的临时设定是不能保存的。

  4. .ps1 文件可能根本没找到,所以不能成功执行

二、解决方案:直捣黄龙!

这里提供几个解决方案, 让你可以彻底控制沙盒里的脚本。

1. 一步到位:WSB 配置文件全搞定

直接在 .wsb 配置文件里解决所有问题,最简洁高效。

  • 原理:

    • 使用 <CommandLine> 标签,让命令在沙盒创建环境之前, 直接 以最高权限来执行。 因为这个时候并没有execution policy相关的设定产生作用。
    • 直接执行设定相关命令,跳过.ps1
  • 操作步骤:

    1. 创建一个文本文件,例如 myconfig.wsb

    2. 在文件中输入以下内容(根据你的实际情况修改路径):

      <Configuration>
        <MappedFolders>
          <HostFolder>C:\Path\To\Your\Scripts</HostFolder>
          <SandboxFolder>C:\scripts</SandboxFolder>
        </MappedFolders>
        <LogonCommand>
      	  <Command>cmd /c "powershell -executionpolicy bypass -command C:\scripts\your_script.ps1"</Command>
        </LogonCommand>
      </Configuration>
      

      这样设定, 当执行your_script.ps1, 他被默认设置拥有 bypass的执行权限.

2. 使用复合指令: 在LogonCommand中运行一切

通过一个稍微复杂的LogonCommand, 把必要的动作写全.

  • 原理 :

    把本来分散在多个步骤中的配置合并在一起。这样既让权限设定可以进行, 也能够运行脚本.
    
  • 代码示例:

     <Configuration>
       <MappedFolders>
         <HostFolder>C:\Path\To\Your\Scripts</HostFolder>
         <SandboxFolder>C:\scripts</SandboxFolder>
        </MappedFolders>
       <LogonCommand>
     		<Command>
            cmd /c "powershell -command \"Set-ExecutionPolicy Bypass -Scope Process -Force; & C:\scripts\your_script.ps1\""
          </Command>
       </LogonCommand>
      </Configuration>
    
    

    在这个方法中, LogonCommand 会先使用Set-ExecutionPolicy Bypass -Scope Process -Force强制将当下powershell进程的运行等级设置为Bypass. 然后, &符号确保随后脚本被顺利运行。

3. (进阶)永久修改 Sandbox 镜像 (非必要情况不推荐!)

警告:此方法涉及修改 Windows Sandbox 的基础镜像,有一定风险。请务必谨慎操作,并提前备份相关文件。不建议普通用户这样做!

  • 原理:

    Windows Sandbox 使用一个基础 VHDX 镜像(%ProgramFiles%\Windows Sandbox\Sandbox.vhdx)来创建每次的沙盒环境。通过离线修改这个镜像,可以永久改变 Sandbox 的默认配置,包括 PowerShell 执行策略。
    这类似于创建系统映像时候把某些设置固化下来.

  • 步骤概览 (极简版, 新手请务必搜索详细教程) :

    1. 准备工作: 安装 Windows ADK (包含 DISM 工具)。 确保你有管理员权限.

    2. 挂载 VHDX: 使用 diskpart 或 DISM 工具挂载 Sandbox.vhdx

    3. 修改注册表: 使用 reg load 将 VHDX 中的 HKLM\SOFTWARE 键加载到你的宿主机注册表中。

    4. 设置执行策略: 在加载的注册表键中,修改 HKLM\SOFTWARE\Microsoft\PowerShell\1\ShellIds\Microsoft.PowerShell 下的 ExecutionPolicy 值为 Bypass

    5. 卸载注册表和 VHDX: 使用 reg unload 卸载注册表,然后使用 diskpart 或 DISM 卸载 VHDX。
      之后重启即可.

    注意:
    因为这一方法修改了 Windows Sandbox 的基础镜像,这个更改会作用到每一次的 Windows Sandbox 会话中,并且很难恢复(除非你重新安装 Sandbox 功能或者手动恢复修改前的镜像)。 建议高手在对系统充分了解情况下才尝试。

4. (推荐方法): 将启动脚本添加到默认 PowerShell Profile

在Windows 沙盒环境中, 将你的启动命令自动加入profile.ps1文件中.

  • 原理:
    每个 PowerShell 进程启动时都会尝试加载几个特定的 “profile” 脚本。如果这些脚本存在,其中的命令会被自动执行. 通过控制此流程,我们也能实现一样的效果.

  • 代码示例:

     <Configuration>
      <MappedFolders>
          <HostFolder>C:\Path\To\Your\Scripts</HostFolder> <!-- 你的脚本所在目录 -->
          <SandboxFolder>C:\scripts</SandboxFolder>
      </MappedFolders>
        <LogonCommand>
            <Command>
              cmd /c "powershell -command \"New-Item -ItemType Directory -Force -Path 'C:\Users\WDAGUtilityAccount\Documents\WindowsPowerShell'; echo '& C:\scripts\your_startup_script.ps1' | Out-File -FilePath 'C:\Users\WDAGUtilityAccount\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1' -Encoding UTF8 -Append\""
              </Command>
        </LogonCommand>
     </Configuration>
    

    在这个方法中, LogonCommand首先尝试创建C:\Users\WDAGUtilityAccount\Documents\WindowsPowerShell, 也就是默认 PowerShell Profile 的所在目录.

    紧接着, 利用 echo '& C:\scripts\your_startup_script.ps1' | Out-File ... -Append, 我们将一行命令追加写入 Microsoft.PowerShell_profile.ps1. 下次 powershell 进程创建的时候,会尝试执行your_startup_script.ps1.
    其中, your_startup_script.ps1里可以包含一切你想运行的脚本。

安全建议(通用):

  • 最小权限原则: 尽量不要使用过于宽松的执行策略(如 Bypass)。如果可能,优先选择 RemoteSigned,并对你的脚本进行数字签名。

  • 脚本来源控制: 只运行你信任的脚本。从网络上下载的脚本务必仔细检查,防止恶意代码。

  • 沙盒隔离: 充分利用 Windows Sandbox 的隔离特性。不要在沙盒中处理敏感数据,也不要将沙盒网络配置为与宿主机共享。

  • 尽量从自己受信的来源复制脚本到沙盒

小结

把问题讲清楚,其实解决起来就没那么难了。核心还是在于理解 Windows Sandbox 的工作机制和 PowerShell 的执行策略。选择适合自己的方法,希望这篇博客能帮你少走弯路,一次成功!