<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
    <channel>
        <title>PowerShell on KnightLi的博客</title>
        <link>https://knightli.com/tags/powershell/</link>
        <description>Recent content in PowerShell on KnightLi的博客</description>
        <generator>Hugo -- gohugo.io</generator>
        <language>zh-cn</language>
        <lastBuildDate>Wed, 01 Jul 2026 10:06:48 +0800</lastBuildDate><atom:link href="https://knightli.com/tags/powershell/index.xml" rel="self" type="application/rss+xml" /><item>
        <title>Codex 大战 PowerShell：powershell-safe-invocation Skill 解决了什么</title>
        <link>https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/</link>
        <pubDate>Wed, 01 Jul 2026 10:06:48 +0800</pubDate>
        
        <guid>https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/</guid>
        <description>&lt;p&gt;最近看到一张很有节目效果的截图：Codex 在 PowerShell 里修一个 Markdown 文件，先是 here-string 没执行，接着 CRLF/LF 匹配失败，再到反引号被 PowerShell 解析、路径反斜杠处理不稳、&lt;code&gt;-split&lt;/code&gt; 参数写法踩坑。模型一路自我诊断，一路继续补脚本，最后评论区给它起了个很准确的标题：经典 GPT 5.5 大战 PowerShell。&lt;/p&gt;
&lt;p&gt;&lt;img src=&#34;https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle.jpg&#34;
	width=&#34;1080&#34;
	height=&#34;2400&#34;
	srcset=&#34;https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle_hu_5b7da40f3bf17d89.jpg 480w, https://knightli.com/2026/07/01/codex-vs-powershell-safe-invocation/codex-powershell-battle_hu_a1711b2e97eccd27.jpg 1024w&#34;
	
		loading=&#34;eager&#34;
		fetchpriority=&#34;high&#34;
		decoding=&#34;sync&#34;
	
	
		alt=&#34;Codex 在 PowerShell 中反复修脚本的截图&#34;
	
	
		class=&#34;gallery-image&#34; 
		data-flex-grow=&#34;45&#34;
		data-flex-basis=&#34;108px&#34;
	
&gt;
&lt;/p&gt;
&lt;p&gt;截图里这串连续补救很有梗，但它背后的坑并不罕见。&lt;/p&gt;
&lt;p&gt;这图好笑，是因为它太像真实开发现场。PowerShell 并不是简单的“Windows 版 Bash”。它有自己的字符串规则、参数绑定规则、cmdlet 错误模型和原生命令传参方式。Agent 一旦把 Bash 习惯带进 PowerShell，写文件、替换文本、调用外部程序这些看似普通的任务，就会变成连续小翻车。&lt;/p&gt;
&lt;p&gt;Misaka-Mikoto-Tech 的 &lt;a class=&#34;link&#34; href=&#34;https://github.com/Misaka-Mikoto-Tech/agent-skills/tree/main/skills/powershell-safe-invocation&#34;  target=&#34;_blank&#34; rel=&#34;noopener&#34;
    &gt;powershell-safe-invocation&lt;/a&gt; skill，正好把这些坑收束成了一套简洁规则。它不是教人“多背 PowerShell 语法”，而是告诉 Agent：在 Windows 上执行命令时，先选不容易出错的调用形态。&lt;/p&gt;
&lt;h2 id=&#34;最大的问题不是-powershell-难而是-agent-容易把它当-bash&#34;&gt;最大的问题不是 PowerShell 难，而是 Agent 容易把它当 Bash
&lt;/h2&gt;&lt;p&gt;截图里的几个问题很典型。&lt;/p&gt;
&lt;p&gt;第一类是字符串和换行。Markdown 里有反引号，PowerShell 也把反引号当转义符；文档可能是 CRLF，脚本却按 LF 精确匹配；here-string 的起止格式只要缩进或引号不对，就可能根本没有按预期生成文本。&lt;/p&gt;
&lt;p&gt;第二类是路径和参数。Windows 路径天然带反斜杠，目录里还常有空格、中括号和中文。把命令拼成一整串再执行，很容易让某个参数被拆开，或者让某段路径被当成转义、通配符、正则或另一个 shell 的语法。&lt;/p&gt;
&lt;p&gt;第三类是错误判断。外部程序要看 &lt;code&gt;$LASTEXITCODE&lt;/code&gt;，PowerShell cmdlet 则应该依赖终止错误和 &lt;code&gt;$ErrorActionPreference = &#39;Stop&#39;&lt;/code&gt;。如果 Agent 混用这两套模型，就会出现“命令其实没成功，但脚本以为成功了”的状态。&lt;/p&gt;
&lt;p&gt;这些都不是大故障，却很消耗注意力。Agent 还会因为“看起来已经执行过命令”而继续在错误假设上修补，越修越绕。&lt;/p&gt;
&lt;h2 id=&#34;这个-skill-的核心不要拼大字符串&#34;&gt;这个 skill 的核心：不要拼大字符串
&lt;/h2&gt;&lt;p&gt;&lt;code&gt;powershell-safe-invocation&lt;/code&gt; 里最重要的一条，是不要把可执行文件、路径、参数和引号拼成一个巨大的命令字符串。&lt;/p&gt;
&lt;p&gt;调用原生程序时，应该把每个参数作为数组里的一个独立元素：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt; 1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 8
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt; 9
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;10
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;11
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;12
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Path With Spaces\tool.exe&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$args&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;--input&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Data Folder\input.json&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;s1&#34;&gt;&amp;#39;--flag&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;&amp;amp;&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;@args&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;$LASTEXITCODE&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;-ne&lt;/span&gt; &lt;span class=&#34;mf&#34;&gt;0&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;k&#34;&gt;throw&lt;/span&gt; &lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exe&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt; failed with exit code &lt;/span&gt;&lt;span class=&#34;nv&#34;&gt;$exitCode&lt;/span&gt;&lt;span class=&#34;s2&#34;&gt;&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这段看起来比一行命令啰嗦，但它把风险拆开了：路径就是路径，参数就是参数，调用就是调用。Agent 不需要猜这一层引号是给 PowerShell 的、给 cmd 的，还是给目标程序的。&lt;/p&gt;
&lt;p&gt;对 PowerShell cmdlet，则更适合用 hashtable splatting：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;3
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;4
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;5
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;6
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;7
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;8
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$params&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;@&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;LiteralPath&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Data[1]\input.txt&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Destination&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;C:\Output&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;Force&lt;/span&gt;       &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;vm&#34;&gt;$true&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;n&#34;&gt;ErrorAction&lt;/span&gt; &lt;span class=&#34;p&#34;&gt;=&lt;/span&gt; &lt;span class=&#34;s1&#34;&gt;&amp;#39;Stop&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nb&#34;&gt;Copy-Item&lt;/span&gt; &lt;span class=&#34;nv&#34;&gt;@params&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这里的关键是 &lt;code&gt;-LiteralPath&lt;/code&gt;。真实路径默认按字面量处理，只有确实需要通配符时才使用会展开的路径参数。对 Agent 来说，这比临时判断路径里有没有 &lt;code&gt;[&lt;/code&gt;、&lt;code&gt;]&lt;/code&gt;、&lt;code&gt;*&lt;/code&gt;、&lt;code&gt;?&lt;/code&gt; 更稳。&lt;/p&gt;
&lt;h2 id=&#34;复杂命令别塞进--command&#34;&gt;复杂命令别塞进 &lt;code&gt;-Command&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;很多 Windows 自动化事故，都从这一类命令开始：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-text&#34; data-lang=&#34;text&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;cmd.exe /c pwsh.exe -Command &amp;#34;...&amp;#34;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;里面一旦出现 JSON、XML、正则、管道、重定向、多行文本、中文路径或 Markdown 反引号，转义层数就会迅速失控。对人来说难读，对 Agent 来说更容易误判。&lt;/p&gt;
&lt;p&gt;skill 给出的选择很朴素：复杂一点就写临时 &lt;code&gt;.ps1&lt;/code&gt; 文件，再用 &lt;code&gt;pwsh.exe -NoLogo -NoProfile -NonInteractive -File script.ps1&lt;/code&gt; 执行。&lt;/p&gt;
&lt;p&gt;这条规则特别适合 Agent。因为 Agent 生成脚本文件后，可以分步骤检查脚本内容、运行结果和文件差异。把所有东西塞进一条 &lt;code&gt;-Command&lt;/code&gt;，失败时只剩一团很难定位的引号和转义。&lt;/p&gt;
&lt;h2 id=&#34;powershellexe-不是-pwshexe&#34;&gt;&lt;code&gt;powershell.exe&lt;/code&gt; 不是 &lt;code&gt;pwsh.exe&lt;/code&gt;
&lt;/h2&gt;&lt;p&gt;另一个容易被忽略的点是版本。&lt;/p&gt;
&lt;p&gt;安装 PowerShell 7，并不会让 &lt;code&gt;powershell.exe&lt;/code&gt; 自动变成 PowerShell 7。通常：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;powershell.exe&lt;/code&gt; 是 Windows PowerShell 5.1&lt;/li&gt;
&lt;li&gt;&lt;code&gt;pwsh.exe&lt;/code&gt; 是 PowerShell 7&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;两者在原生命令参数传递、编码默认值和一些行为细节上并不完全相同。Agent 如果不知道自己跑在哪个 shell 里，就应该先检查：&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;div class=&#34;chroma&#34;&gt;
&lt;table class=&#34;lntable&#34;&gt;&lt;tr&gt;&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code&gt;&lt;span class=&#34;lnt&#34;&gt;1
&lt;/span&gt;&lt;span class=&#34;lnt&#34;&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class=&#34;lntd&#34;&gt;
&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-powershell&#34; data-lang=&#34;powershell&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$PSVersionTable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;py&#34;&gt;PSVersion&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nv&#34;&gt;$PSNativeCommandArgumentPassing&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;&lt;/tr&gt;&lt;/table&gt;
&lt;/div&gt;
&lt;/div&gt;&lt;p&gt;这不是仪式感。很多“我本地可以，Agent 跑不行”的问题，根源就是 shell 版本和参数传递规则不同。&lt;/p&gt;
&lt;h2 id=&#34;写文件时编码和换行要当成一等问题&#34;&gt;写文件时，编码和换行要当成一等问题
&lt;/h2&gt;&lt;p&gt;截图里最有意思的地方，是 Agent 反复围绕 Markdown 文件替换失败打转。这里面至少有三个隐含前提：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;文件实际编码是什么&lt;/li&gt;
&lt;li&gt;文件换行是 CRLF 还是 LF&lt;/li&gt;
&lt;li&gt;替换目标是否被 PowerShell 字符串语法改变过&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;中文文章、Markdown 代码块、front matter、短代码、反引号混在一起时，最好不要用随手拼出来的 PowerShell here-string 写入正文。要么使用明确编码的文件 API，要么让脚本本身只处理 ASCII 控制逻辑，把非 ASCII 正文交给更可靠的写入路径。&lt;/p&gt;
&lt;p&gt;对 Agent 工作流来说，还有一条额外经验：写完文件后立刻验证。至少检查 UTF-8 可读、front matter 闭合、Markdown 链接没有断、正文里没有连续问号或明显 mojibake。很多乱码问题越早发现越便宜。&lt;/p&gt;
&lt;h2 id=&#34;一套更稳的决策顺序&#34;&gt;一套更稳的决策顺序
&lt;/h2&gt;&lt;p&gt;这个 skill 最实用的部分，是给 Agent 一个决策顺序：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;能用 PowerShell cmdlet，就用 cmdlet。&lt;/li&gt;
&lt;li&gt;调用外部程序时，用 &lt;code&gt;&amp;amp; $exe @args&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;命令复杂时，写 &lt;code&gt;.ps1&lt;/code&gt; 文件并用 &lt;code&gt;pwsh.exe -File&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;必须精确控制进程参数时，用 &lt;code&gt;ProcessStartInfo.ArgumentList&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;只有需要新窗口、提权、脱离当前进程等特殊行为时，才用 &lt;code&gt;Start-Process&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;只有确实需要 cmd 语义时，才套 &lt;code&gt;cmd.exe /c&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Invoke-Expression&lt;/code&gt; 放到最后，且要非常克制。&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;这套顺序的好处是，它把“能跑”变成“可解释、可检查、可复现”。对人类开发者如此，对 Agent 更是如此。&lt;/p&gt;
&lt;h2 id=&#34;给-codex-的现实建议&#34;&gt;给 Codex 的现实建议
&lt;/h2&gt;&lt;p&gt;如果让 Codex 在 Windows 仓库里改文件，我会给它几条硬约束：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;不要用 Bash 风格的 &lt;code&gt;\&amp;quot;&lt;/code&gt; 去写 PowerShell。&lt;/li&gt;
&lt;li&gt;不要把路径和参数拼成一整条字符串。&lt;/li&gt;
&lt;li&gt;不要用 &lt;code&gt;Start-Process -ArgumentList&lt;/code&gt; 处理复杂参数。&lt;/li&gt;
&lt;li&gt;不要用 &lt;code&gt;cmd.exe /c&lt;/code&gt; 包一层来解决普通调用问题。&lt;/li&gt;
&lt;li&gt;对真实文件路径优先使用 &lt;code&gt;-LiteralPath&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;对复杂脚本优先写 &lt;code&gt;.ps1&lt;/code&gt;，再用 &lt;code&gt;pwsh.exe -File&lt;/code&gt; 跑。&lt;/li&gt;
&lt;li&gt;写入中文、日文等非 ASCII 内容后，必须检查编码和乱码标记。&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;PowerShell 并不是 Agent 的敌人。真正的问题是 Agent 太容易沿用“拼字符串，然后交给 shell 猜”的旧习惯。只要把调用边界拆清楚，PowerShell 反而能提供很强的结构化能力。&lt;/p&gt;
&lt;p&gt;所以这场“Codex 大战 PowerShell”的结论不是让 Agent 避开 Windows，而是给它一份战术手册：少赌引号，多用结构；少塞一行命令，多保留可检查的中间状态。&lt;/p&gt;
&lt;p&gt;笑点在截图里，经验在规则里。&lt;/p&gt;
</description>
        </item>
        
    </channel>
</rss>
