<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>脚本 on Liangweidong's blog</title><link>https://liangweidonggood.github.io/tags/%E8%84%9A%E6%9C%AC/</link><description>Recent content in 脚本 on Liangweidong's blog</description><generator>Hugo -- gohugo.io</generator><language>zh-cn</language><lastBuildDate>Sat, 15 Mar 2014 00:00:00 +0800</lastBuildDate><atom:link href="https://liangweidonggood.github.io/tags/%E8%84%9A%E6%9C%AC/index.xml" rel="self" type="application/rss+xml"/><item><title>bat 脚本监控与排查：wmic + taskkill 进程管理实战</title><link>https://liangweidonggood.github.io/p/windows-bat-monitor-2014/</link><pubDate>Sat, 15 Mar 2014 00:00:00 +0800</pubDate><guid>https://liangweidonggood.github.io/p/windows-bat-monitor-2014/</guid><description>&lt;img src="https://liangweidonggood.github.io/p/windows-bat-monitor-2014/image/cover.jpg" alt="Featured image of post bat 脚本监控与排查：wmic + taskkill 进程管理实战" /&gt;&lt;h2 id="一为什么-2024-年还在写-bat-脚本"&gt;一、为什么 2024 年还在写 bat 脚本
&lt;/h2&gt;&lt;p&gt;2014 年的 Windows 自动化基本是 bat + VBScript 双雄；2018 年之后 PowerShell Core 跨平台，bat 看起来&amp;quot;该退休&amp;quot;了。但实际场景里：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;老旧 Windows Server 2008 R2 / 2012 R2 默认没装 PowerShell 5&lt;/strong&gt;，bat 仍是首选&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;计划任务里挂的&amp;quot;老脚本&amp;quot;没人敢动&lt;/strong&gt;，出问题了又得维护&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;NSSM 注册服务&lt;/strong&gt;的某些参数只能传 bat 路径&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;第三方工具的安装脚本&lt;/strong&gt;（很多 CAD / 工控软件）就是 bat，你绕不开&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;所以&amp;quot;bat 找 PID + 杀进程&amp;quot;是必须会的硬功夫。本文以两个高频需求切入：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;找到后台跑的 bat 进程&lt;/strong&gt;（常见：监控 / 重启脚本卡死）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;结束指定进程&lt;/strong&gt;（常见：清残留）&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="二找后台运行的-bat-进程"&gt;二、找后台运行的 bat 进程
&lt;/h2&gt;&lt;h3 id="21-用-wmic-找-bat-进程"&gt;2.1 用 wmic 找 bat 进程
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cmd" data-lang="cmd"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;wmic process get commandline,processid &lt;span class="p"&gt;|&lt;/span&gt; findstr 监控重启.bat &lt;span class="p"&gt;|&lt;/span&gt; findstr /v findstr
&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;strong&gt;逐步拆解&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;code&gt;wmic process get commandline,processid&lt;/code&gt; —— 列出所有进程的&amp;quot;完整命令行&amp;quot;和&amp;quot;PID&amp;quot;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;findstr 监控重启.bat&lt;/code&gt; —— 过滤出命令行里含&amp;quot;监控重启.bat&amp;quot;的行&lt;/li&gt;
&lt;li&gt;&lt;code&gt;findstr /v findstr&lt;/code&gt; —— 排除掉 &amp;ldquo;findstr 自身&amp;rdquo; 那一行（&lt;strong&gt;否则你会看到 findstr 自己的命令行&lt;/strong&gt;）&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;输出形如：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;cmd.exe /c &amp;#34;D:\scripts\监控重启.bat&amp;#34; 4620
&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;4620&lt;/code&gt; 就是 bat 对应的 PID（其实是 &lt;code&gt;cmd.exe&lt;/code&gt; 的 PID，因为 bat 是 cmd 解释执行的）。&lt;/p&gt;
&lt;h3 id="22-用-powershell-等价推荐"&gt;2.2 用 PowerShell 等价（推荐）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-CimInstance&lt;/span&gt; &lt;span class="n"&gt;Win32_Process&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Where-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;CommandLine&lt;/span&gt; &lt;span class="o"&gt;-like&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;*监控重启.bat*&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Select-Object&lt;/span&gt; &lt;span class="n"&gt;ProcessId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;CommandLine&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;PowerShell 的优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;对象化输出&lt;/strong&gt;，可以直接 &lt;code&gt;| Stop-Process&lt;/code&gt; 一气呵成&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;不像 wmic 那样返回字符串&lt;/strong&gt;，&lt;strong&gt;不依赖解析列宽&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Unicode 中文文件名不会乱码&lt;/strong&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;wmic 在 Win 10 21H1 起开始被标记为 deprecated（&lt;strong&gt;最终会从 Windows 中移除&lt;/strong&gt;），强烈建议新写的脚本用 PowerShell CIM。&lt;/p&gt;
&lt;h3 id="23-用-get-process-按名字找不推荐"&gt;2.3 用 Get-Process 按名字找（不推荐）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-Process&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Where-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;MainWindowTitle&lt;/span&gt; &lt;span class="o"&gt;-like&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;*监控*&amp;#39;&lt;/span&gt; &lt;span class="p"&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;缺点：&lt;strong&gt;&lt;code&gt;cmd.exe&lt;/code&gt; 的所有实例都返回&lt;/strong&gt;（10 个 cmd 窗口就有 10 条），需要再过滤窗口标题，对纯后台运行的 bat 不适用。&lt;/p&gt;
&lt;h2 id="三结束进程"&gt;三、结束进程
&lt;/h2&gt;&lt;h3 id="31-taskkillcmd-原生"&gt;3.1 taskkill（cmd 原生）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cmd" data-lang="cmd"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;taskkill /f /pid 4620
&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;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;/f&lt;/code&gt; —— 强制结束（&lt;strong&gt;不弹确认&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/pid&lt;/code&gt; —— 按 PID&lt;/li&gt;
&lt;li&gt;&lt;code&gt;/im&lt;/code&gt; —— 按镜像名（&lt;code&gt;taskkill /f /im cmd.exe&lt;/code&gt; 会杀掉所有 cmd 窗口，&lt;strong&gt;慎用&lt;/strong&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="32-杀进程并确认"&gt;3.2 杀进程并确认
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-cmd" data-lang="cmd"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;taskkill /f /pid 4620
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;%errorlevel%&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; 0 &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; 杀进程成功
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; 杀进程失败，可能权限不够
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;h3 id="33-powershell-一行杀"&gt;3.3 PowerShell 一行杀
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-CimInstance&lt;/span&gt; &lt;span class="n"&gt;Win32_Process&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Where-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;CommandLine&lt;/span&gt; &lt;span class="o"&gt;-like&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;*监控重启.bat*&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;ForEach-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nb"&gt;Stop-Process&lt;/span&gt; &lt;span class="n"&gt;-Id&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;ProcessId&lt;/span&gt; &lt;span class="n"&gt;-Force&lt;/span&gt; &lt;span class="p"&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;或者用更直观的 &lt;code&gt;Get-Process&lt;/code&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nb"&gt;Get-Process&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="n"&gt;cmd&lt;/span&gt; &lt;span class="n"&gt;-ErrorAction&lt;/span&gt; &lt;span class="n"&gt;SilentlyContinue&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Where-Object&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nv"&gt;$_&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;Path&lt;/span&gt; &lt;span class="o"&gt;-eq&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;C:\Windows\System32\cmd.exe&amp;#39;&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Stop-Process&lt;/span&gt; &lt;span class="n"&gt;-Force&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;h2 id="四实战监控重启脚本"&gt;四、实战：监控重启脚本
&lt;/h2&gt;&lt;h3 id="41-需求"&gt;4.1 需求
&lt;/h3&gt;&lt;p&gt;写一个 bat 监控某个进程（如 &lt;code&gt;myapp.exe&lt;/code&gt;），如果挂了自动重启。&lt;/p&gt;
&lt;h3 id="42-朴素版轮询"&gt;4.2 朴素版（轮询）
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;echo&lt;/span&gt; off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;INTERVAL&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;30
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nl"&gt;loop&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;tasklist &lt;span class="p"&gt;|&lt;/span&gt; findstr /i &lt;span class="s2"&gt;&amp;#34;myapp.exe&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;nul
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;%errorlevel%&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; 0 &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;%date%&lt;/span&gt; &lt;span class="nv"&gt;%time%&lt;/span&gt; myapp.exe 正常运行
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;%date%&lt;/span&gt; &lt;span class="nv"&gt;%time%&lt;/span&gt; myapp.exe 已挂，重启中...
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;start&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&amp;#34;&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\apps\myapp.exe&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;timeout /t &lt;span class="nv"&gt;%INTERVAL%&lt;/span&gt; /nobreak &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;nul
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;goto&lt;/span&gt; &lt;span class="nl"&gt;loop&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;strong&gt;关键点&lt;/strong&gt;：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;tasklist | findstr /i&lt;/code&gt; —— 查进程是否存在&lt;/li&gt;
&lt;li&gt;&lt;code&gt;if %errorlevel% == 0&lt;/code&gt; —— 找到就是 0&lt;/li&gt;
&lt;li&gt;&lt;code&gt;start &amp;quot;&amp;quot;&lt;/code&gt; —— &lt;strong&gt;空标题必须&lt;/strong&gt;，否则会报错&lt;/li&gt;
&lt;li&gt;&lt;code&gt;timeout /t N /nobreak&lt;/code&gt; —— 等 N 秒，不响应 Ctrl+C（&lt;strong&gt;比 &lt;code&gt;ping -n&lt;/code&gt; 更精确&lt;/strong&gt;）&lt;/li&gt;
&lt;/ul&gt;
&lt;h3 id="43-改进版按需触发"&gt;4.3 改进版（按需触发）
&lt;/h3&gt;&lt;p&gt;如果只想要&amp;quot;挂了再启动，不轮询&amp;quot;，可以用 &lt;code&gt;WaitForSingleObject&lt;/code&gt; 思路，但 bat 实现不了，&lt;strong&gt;这种场景请用 nssm 注册成 Windows 服务&lt;/strong&gt;（详见 0.4 批次的 2022-12-15《Windows 系统管理员实战》）。&lt;/p&gt;
&lt;h3 id="44-用-powershell-写监控脚本"&gt;4.4 用 PowerShell 写监控脚本
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt; 1
&lt;/span&gt;&lt;span class="lnt"&gt; 2
&lt;/span&gt;&lt;span class="lnt"&gt; 3
&lt;/span&gt;&lt;span class="lnt"&gt; 4
&lt;/span&gt;&lt;span class="lnt"&gt; 5
&lt;/span&gt;&lt;span class="lnt"&gt; 6
&lt;/span&gt;&lt;span class="lnt"&gt; 7
&lt;/span&gt;&lt;span class="lnt"&gt; 8
&lt;/span&gt;&lt;span class="lnt"&gt; 9
&lt;/span&gt;&lt;span class="lnt"&gt;10
&lt;/span&gt;&lt;span class="lnt"&gt;11
&lt;/span&gt;&lt;span class="lnt"&gt;12
&lt;/span&gt;&lt;span class="lnt"&gt;13
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$target&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;myapp&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$interval&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="mf"&gt;30&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="nv"&gt;$exe&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;C:\apps\myapp.exe&amp;#39;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="vm"&gt;$true&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-not&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;Get-Process&lt;/span&gt; &lt;span class="n"&gt;-Name&lt;/span&gt; &lt;span class="nv"&gt;$target&lt;/span&gt; &lt;span class="n"&gt;-ErrorAction&lt;/span&gt; &lt;span class="n"&gt;SilentlyContinue&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-Host&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;Get-Date&lt;/span&gt; &lt;span class="n"&gt;-Format&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;yyyy-MM-dd HH:mm:ss&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt; 已挂，重启&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Start-Process&lt;/span&gt; &lt;span class="n"&gt;-FilePath&lt;/span&gt; &lt;span class="nv"&gt;$exe&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Write-Host&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;&lt;/span&gt;&lt;span class="p"&gt;$(&lt;/span&gt;&lt;span class="nb"&gt;Get-Date&lt;/span&gt; &lt;span class="n"&gt;-Format&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;yyyy-MM-dd HH:mm:ss&amp;#39;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="s2"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$target&lt;/span&gt;&lt;span class="s2"&gt; 正常&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="nb"&gt;Start-Sleep&lt;/span&gt; &lt;span class="n"&gt;-Seconds&lt;/span&gt; &lt;span class="nv"&gt;$interval&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;PowerShell 优势：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;Get-Process&lt;/code&gt; 比 &lt;code&gt;tasklist | findstr&lt;/code&gt; 更可靠（&lt;strong&gt;处理特殊字符不挂&lt;/strong&gt;）&lt;/li&gt;
&lt;li&gt;&lt;code&gt;Start-Sleep&lt;/code&gt; 比 &lt;code&gt;timeout&lt;/code&gt; 更可编程&lt;/li&gt;
&lt;li&gt;异常可以用 &lt;code&gt;try/catch&lt;/code&gt; 包裹&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="五批处理编码与中文乱码"&gt;五、批处理编码与中文乱码
&lt;/h2&gt;&lt;h3 id="51-bat-文件默认编码"&gt;5.1 bat 文件默认编码
&lt;/h3&gt;&lt;p&gt;bat 在 &lt;strong&gt;中文 Windows 下默认是 GBK&lt;/strong&gt; 编码。&lt;strong&gt;如果你用 UTF-8 编码的 bat 直接运行，中文会乱码&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;两种处理方式&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;保存为 GBK / ANSI 编码&lt;/strong&gt;（最稳）—— 用 VS Code 右下角&amp;quot;UTF-8&amp;quot;点开选&amp;quot;Save with Encoding&amp;quot;→&amp;ldquo;GBK&amp;quot;或&amp;quot;Chinese Simplified (GB2312)&amp;rdquo;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;保存为 UTF-8 BOM 编码&lt;/strong&gt; —— Windows 10 1809+ 能识别 BOM 自动用 UTF-8 解释&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;在 bat 顶部加 &lt;code&gt;chcp 65001 &amp;gt;nul&lt;/code&gt;&lt;/strong&gt; —— 切换控制台代码页到 UTF-8，但&lt;strong&gt;这不会改变 bat 源文件的解释编码&lt;/strong&gt;，对 bat 里的中文 echo 没有帮助，仅对 bat 调用的外部命令的输出有影响&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="52-输出-utf-8-到文件"&gt;5.2 输出 UTF-8 到文件
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;chcp 65001 &lt;span class="p"&gt;&amp;gt;&lt;/span&gt;nul
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;echo&lt;/span&gt; 你好，世界 &lt;span class="p"&gt;&amp;gt;&lt;/span&gt; output.txt
&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;strong&gt;注意&lt;/strong&gt;：&lt;code&gt;&amp;gt;&lt;/code&gt; 重定向输出的 &lt;code&gt;output.txt&lt;/code&gt; 会带 UTF-8 BOM（如果 cmd 默认按 ANSI 解释 echo 命令后再输出）。&lt;strong&gt;最稳的办法&lt;/strong&gt;是用 PowerShell：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-powershell" data-lang="powershell"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="s2"&gt;&amp;#34;你好，世界&amp;#34;&lt;/span&gt; &lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="nb"&gt;Out-File&lt;/span&gt; &lt;span class="n"&gt;-FilePath&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="py"&gt;txt&lt;/span&gt; &lt;span class="n"&gt;-Encoding&lt;/span&gt; &lt;span class="n"&gt;UTF8&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;h3 id="53-bat-里包含中文路径"&gt;5.3 bat 里包含中文路径
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;cd&lt;/span&gt; /d &lt;span class="s2"&gt;&amp;#34;D:\我的文档\脚本&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;call&lt;/span&gt; 启动.bat
&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;strong&gt;用双引号包起来&lt;/strong&gt;就不会出错。&lt;strong&gt;&lt;code&gt;/d&lt;/code&gt; 开关&lt;/strong&gt;让你不用先 &lt;code&gt;D:&lt;/code&gt; 切盘符。&lt;/p&gt;
&lt;h2 id="六批处理常见错误与排查"&gt;六、批处理常见错误与排查
&lt;/h2&gt;&lt;h3 id="61-错误级别errorlevel"&gt;6.1 错误级别（&lt;code&gt;%errorlevel%&lt;/code&gt;）
&lt;/h3&gt;&lt;p&gt;每条命令执行后，cmd 设置一个 errorlevel：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;0&lt;/code&gt; —— 成功&lt;/li&gt;
&lt;li&gt;&lt;code&gt;非 0&lt;/code&gt; —— 失败（具体值看命令）&lt;/li&gt;
&lt;/ul&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;echo&lt;/span&gt; off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;xcopy C:\source D:\dest /E /I
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nv"&gt;%errorlevel%&lt;/span&gt; &lt;span class="ow"&gt;neq&lt;/span&gt; 0 &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; 拷贝失败，错误码 &lt;span class="nv"&gt;%errorlevel%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;exit&lt;/span&gt; /b &lt;span class="nv"&gt;%errorlevel%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;h3 id="62-延迟扩展setlocal-enabledelayedexpansion"&gt;6.2 延迟扩展（&lt;code&gt;setlocal enabledelayedexpansion&lt;/code&gt;）
&lt;/h3&gt;&lt;p&gt;bat 里的 &lt;code&gt;if&lt;/code&gt; 块、&lt;code&gt;for&lt;/code&gt; 块&lt;strong&gt;默认不实时展开变量&lt;/strong&gt;。典型坑：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;echo&lt;/span&gt; off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;/l&lt;/span&gt; &lt;span class="se"&gt;%%&lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;,&lt;span class="mi"&gt;1&lt;/span&gt;,&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="k"&gt;/a&lt;/span&gt; &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; 当前 COUNT=&lt;span class="nv"&gt;%COUNT%&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;&lt;strong&gt;输出&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-fallback" data-lang="fallback"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前 COUNT=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前 COUNT=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前 COUNT=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前 COUNT=0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;当前 COUNT=0
&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;%COUNT%&lt;/code&gt; 在 for 块开始时就被展开为 &lt;code&gt;0&lt;/code&gt;，后续 &lt;code&gt;set /a&lt;/code&gt; 修改的 COUNT &lt;strong&gt;没被重新读取&lt;/strong&gt;。&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;正确写法&lt;/strong&gt;：&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;span class="lnt"&gt;3
&lt;/span&gt;&lt;span class="lnt"&gt;4
&lt;/span&gt;&lt;span class="lnt"&gt;5
&lt;/span&gt;&lt;span class="lnt"&gt;6
&lt;/span&gt;&lt;span class="lnt"&gt;7
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&gt;@&lt;/span&gt;&lt;span class="k"&gt;echo&lt;/span&gt; off
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;setlocal&lt;/span&gt; enabledelayedexpansion
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="p"&gt;=&lt;/span&gt;0
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="k"&gt;/l&lt;/span&gt; &lt;span class="se"&gt;%%&lt;/span&gt;i &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;,&lt;span class="mi"&gt;1&lt;/span&gt;,&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;set&lt;/span&gt; &lt;span class="k"&gt;/a&lt;/span&gt; &lt;span class="nv"&gt;COUNT&lt;/span&gt;&lt;span class="o"&gt;+=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt; &lt;span class="k"&gt;echo&lt;/span&gt; 当前 COUNT=&lt;span class="nv"&gt;!COUNT!&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="p"&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;&lt;strong&gt;关键点&lt;/strong&gt;：&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;顶部加 &lt;code&gt;setlocal enabledelayedexpansion&lt;/code&gt;&lt;/strong&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;块内用 &lt;code&gt;!VAR!&lt;/code&gt; 而非 &lt;code&gt;%VAR%&lt;/code&gt;&lt;/strong&gt; 来读取最新值&lt;/li&gt;
&lt;/ol&gt;
&lt;h3 id="63-路径里的空格"&gt;6.3 路径里的空格
&lt;/h3&gt;&lt;div class="highlight"&gt;&lt;div class="chroma"&gt;
&lt;table class="lntable"&gt;&lt;tr&gt;&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code&gt;&lt;span class="lnt"&gt;1
&lt;/span&gt;&lt;span class="lnt"&gt;2
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/td&gt;
&lt;td class="lntd"&gt;
&lt;pre tabindex="0" class="chroma"&gt;&lt;code class="language-batch" data-lang="batch"&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;cd&lt;/span&gt; &lt;span class="s2"&gt;&amp;#34;C:\Program Files\MyApp&amp;#34;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class="line"&gt;&lt;span class="cl"&gt;&lt;span class="k"&gt;cd&lt;/span&gt; &lt;span class="nv"&gt;%PROGRAMFILES%&lt;/span&gt;\MyApp
&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;strong&gt;用双引号包路径&lt;/strong&gt;最稳。第二种用环境变量展开也 OK，但&lt;strong&gt;路径里有 &lt;code&gt;&amp;amp;&lt;/code&gt; 之类特殊字符必须用引号&lt;/strong&gt;。&lt;/p&gt;
&lt;h2 id="七批处理的替代方案"&gt;七、批处理的替代方案
&lt;/h2&gt;&lt;table&gt;
	&lt;thead&gt;
			&lt;tr&gt;
					&lt;th&gt;场景&lt;/th&gt;
					&lt;th&gt;替代方案&lt;/th&gt;
			&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
			&lt;tr&gt;
					&lt;td&gt;简单文件操作 / 启停服务&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;bat 仍是最简方案&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;跨平台脚本&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;PowerShell Core / pwsh&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;复杂文本处理&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;PowerShell / Python&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;长任务调度&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Windows 任务计划程序 + bat/ps1&lt;/strong&gt;&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;常驻服务&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;nssm 注册成服务&lt;/strong&gt;（详见 2022-12-15 那篇）&lt;/td&gt;
			&lt;/tr&gt;
			&lt;tr&gt;
					&lt;td&gt;配置中心&lt;/td&gt;
					&lt;td&gt;&lt;strong&gt;Ansible&lt;/strong&gt;（WinRM 协议）&lt;/td&gt;
			&lt;/tr&gt;
	&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2 id="八常见-5-个坑"&gt;八、常见 5 个坑
&lt;/h2&gt;&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;wmic&lt;/code&gt; 在新 Windows 上 deprecated&lt;/strong&gt;——新写脚本用 &lt;code&gt;Get-CimInstance&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中文乱码&lt;/strong&gt;——bat 源文件保存为 GBK / ANSI 编码最稳。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;for&lt;/code&gt; 块内 &lt;code&gt;%VAR%&lt;/code&gt; 不刷新&lt;/strong&gt;——用 &lt;code&gt;setlocal enabledelayedexpansion&lt;/code&gt; + &lt;code&gt;!VAR!&lt;/code&gt;。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code&gt;taskkill /f /im cmd.exe&lt;/code&gt; 把所有 cmd 窗口都杀了&lt;/strong&gt;——按 PID 杀更精准。&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;bat 里的&amp;quot;后台进程&amp;quot;实际是 &lt;code&gt;cmd.exe&lt;/code&gt;&lt;/strong&gt;——wmic 找到的 PID 是 cmd 解释器的，杀它才能停 bat。&lt;/li&gt;
&lt;/ol&gt;
&lt;h2 id="九总结"&gt;九、总结
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;找后台 bat 进程&lt;/strong&gt;：&lt;code&gt;wmic process get commandline,processid | findstr xxx.bat&lt;/code&gt;（老方案）；&lt;code&gt;Get-CimInstance&lt;/code&gt;（推荐）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;杀进程&lt;/strong&gt;：&lt;code&gt;taskkill /f /pid PID&lt;/code&gt;（cmd）；&lt;code&gt;Stop-Process&lt;/code&gt;（PowerShell）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;监控 + 自动重启&lt;/strong&gt;：&lt;code&gt;tasklist | findstr&lt;/code&gt; 轮询（朴素）；&lt;code&gt;nssm&lt;/code&gt; 注册服务（推荐）&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;中文乱码&lt;/strong&gt;：bat 源文件&lt;strong&gt;保存为 GBK / ANSI&lt;/strong&gt;最稳&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;延迟变量&lt;/strong&gt;：&lt;code&gt;setlocal enabledelayedexpansion&lt;/code&gt; + &lt;code&gt;!VAR!&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;新写脚本优先用 PowerShell&lt;/strong&gt;（pwsh 跨平台），bat 留给&amp;quot;老系统 / 老脚本维护&amp;quot;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2 id="参考资料"&gt;参考资料
&lt;/h2&gt;&lt;ul&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/taskkill" target="_blank" rel="noopener"
 &gt;Microsoft Docs - taskkill&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/zh-cn/powershell/module/cimcmdlets/get-ciminstance" target="_blank" rel="noopener"
 &gt;Microsoft Docs - Get-CimInstance&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://learn.microsoft.com/zh-cn/windows-server/administration/windows-commands/setlocal" target="_blank" rel="noopener"
 &gt;Windows bat 脚本延迟变量&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a class="link" href="https://ss64.com/nt/" target="_blank" rel="noopener"
 &gt;ss64 - CMD 命令参考&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</description></item></channel></rss>