
很多人“会用脚本”,但说不清脚本。
真正的差距,往往从 bat 和 ps1 的理解深度 开始拉开。
一、为什么 Windows 会同时存在 .bat 和 .ps1?
这是一个历史 + 架构演进的问题。
.ps1是 PowerShell 脚本文件的扩展名,用于编写和执行 PowerShell 脚本。.bat是 Windows 批处理脚本文件的扩展名,用于编写和执行一系列 Windows 命令。
1️⃣ .bat 的诞生背景
.bat(Batch File)来自 DOS 时代,核心设计目标只有一个:
把人工在命令行里敲的命令,一次性自动执行
所以它的设计思想是:
命令逐行执行
一切皆字符串
几乎没有“语言设计”
2️⃣ .ps1 的出现原因
随着 Windows 成为服务器操作系统、企业级平台,仅靠 bat 已经不够:
需要批量管理服务
需要操作注册表、AD、WMI
需要结构化数据(XML / JSON)
需要远程管理
于是 PowerShell 诞生了,而 .ps1 是它的脚本载体。
PowerShell 不是 CMD 的升级版,而是全新的自动化平台

二、.bat 是什么?
1️⃣ 执行模型
执行程序:
cmd.exe执行方式:逐行解释
失败不会自动终止(除非你自己判断)
cmd.exe /c test.bat2️⃣ 核心特征(记住这 4 点)
无对象概念
变量全是字符串
依赖系统内置命令
错误处理极弱
3️⃣ bat 的“变量系统”
set VAR=value
echo %VAR%⚠️ 注意:
%VAR%是文本替换不是运行时计算
循环里要用
!VAR!(延迟展开)
三、.bat 的完整语法体系
1️⃣ 基本结构
@echo off
rem 这是注释
echo Hello World
pause2️⃣ 条件判断(if)
if exist test.txt (
echo 文件存在
) else (
echo 文件不存在
)常见判断:
exist==errorlevel
if %errorlevel% neq 0 echo 执行失败这是 bat 最容易写出 bug 的地方。
3️⃣ 循环(for)
for %%i in (*.log) do echo %%ifor /f(最反人类的语法):
for /f "tokens=2 delims=:" %%i in ('ipconfig') do echo %%i📌 bat 最大的痛点:
能做的事 ≠ 好做的事
四、.ps1 是什么?
1️⃣ 本质定位
.ps1 是 PowerShell 脚本文件
而 PowerShell 本身是:
基于 .NET 的面向对象自动化语言
这句话极其重要。
2️⃣ 执行模型
执行程序:
powershell.exe/pwsh.exe命令返回的不是文本,而是 对象
Get-Service返回的是:
System.ServiceProcess.ServiceController而不是字符串。

五、.ps1 的语法体系
1️⃣ 变量与类型
$name = "Windows"
$count = 10支持强类型:
[int]$port = 4432️⃣ 条件判断(if)
if ($port -eq 443) {
Write-Host "HTTPS"
} else {
Write-Host "Other"
}对比 bat:可读性直接碾压
3️⃣ 循环(foreach / for)
foreach ($svc in Get-Service) {
if ($svc.Status -eq "Stopped") {
Write-Host $svc.Name
}
}📌 这里 $svc 是对象,不是字符串。
4️⃣ 管道(PowerShell 灵魂)
Get-Service | Where-Object Status -eq "Running"这就是 PowerShell 能彻底干掉 bat 的原因。

5️⃣ 函数(企业级脚本必备)
function Restart-MyService {
param($Name)
Restart-Service $Name
}六、执行策略(为什么 ps1 默认跑不了)
1️⃣ 执行策略是什么?
PowerShell 引入了 Execution Policy:
防止脚本被恶意执行
常见策略:
2️⃣ 企业最常用方式
powershell -ExecutionPolicy Bypass -File deploy.ps1📌 注意:这是“临时放行”,不改系统策略。
七、.bat 与 .ps1 的工程级对比
一句话总结:
bat 能跑
ps1 能长期维护
八、真实企业场景建议
❌ 不要再用 bat 的场景
安全整改脚本
批量系统配置
运维巡检
自动化部署
✅ ps1 的黄金场景
等保 / 分保脚本
批量漏洞修复
服务巡检
日志采集
AD / 注册表管理
九、一个现实真相
很多“只会 bat 的运维”,
本质上还停留在 人工命令自动化阶段
而 PowerShell 做的是:
系统能力的程序化控制
这是两个时代。
十、总结
.bat是历史的产物.ps1是 Windows 自动化的基石懂 bat 是入门
精通 ps1 才是职业护城河
十一、【实战】Windows信息检查脚本
功能说明:
检查Windows主机的硬件配置,系统安装时间,系统版本,硬件序列号等。
具体脚本内容:
GetSystemInfo.ps1文件内容如下所示
# ========================================================
# 版权所有 © 2025 笨熊呆呆瓜
# 联系方式:842668578@qq.com
# 用途:收集本机系统信息(时间、主机名、用户、BIOS、硬盘、IP与MAC等)
# ========================================================
# 确保脚本路径正确
$scriptDir = if ($PSScriptRoot) { $PSScriptRoot } else { Get-Location }
Set-Location -Path $scriptDir
# 获取时间、主机名、用户、操作系统信息
$timestamp = Get-Date -Format "yyyy-MM-dd_HH-mm-ss"
$hostname = $env:COMPUTERNAME
$username = $env:USERNAME
$osinfo = Get-CimInstance Win32_OperatingSystem
$osname = $osinfo.Caption
$installTime = $osinfo.InstallDate.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss")
# 构造输出文件路径
$outputFile = Join-Path $scriptDir "system_info_${hostname}_${timestamp}.txt"
# 初始化输出
Set-Content -Path $outputFile -Value "===== 系统信息收集 =====" -Encoding UTF8
Add-Content -Path $outputFile -Value "导出时间:$timestamp" -Encoding UTF8
Add-Content -Path $outputFile -Value "系统安装时间:$installTime" -Encoding UTF8
Add-Content -Path $outputFile -Value "主机名:$hostname" -Encoding UTF8
Add-Content -Path $outputFile -Value "当前用户:$username" -Encoding UTF8
Add-Content -Path $outputFile -Value "操作系统:$osname" -Encoding UTF8
Add-Content -Path $outputFile -Value "" -Encoding UTF8
# BIOS 序列号
Add-Content -Path $outputFile -Value "[设备序列号 - BIOS SerialNumber]" -Encoding UTF8
(Get-CimInstance Win32_BIOS).SerialNumber | Add-Content -Path $outputFile -Encoding UTF8
Add-Content -Path $outputFile -Value "" -Encoding UTF8
# 物理硬盘序列号
Add-Content -Path $outputFile -Value "[硬盘序列号 - Disk Serial Numbers]" -Encoding UTF8
Get-PhysicalDisk | ForEach-Object {
"硬盘: $($_.FriendlyName) - 序列号: $($_.SerialNumber)" |
Add-Content -Path $outputFile -Encoding UTF8
}
Add-Content -Path $outputFile -Value "" -Encoding UTF8
# 网卡 IP 和 MAC 配对输出(清晰配对)
Add-Content -Path $outputFile -Value "[网络接口 - IP 与 MAC 地址配对]" -Encoding UTF8
$adapters = Get-NetAdapter | Where-Object { $_.Status -eq "Up" }
foreach ($adapter in $adapters) {
$name = $adapter.Name
$mac = $adapter.MacAddress
$ips = Get-NetIPAddress -InterfaceAlias $name -AddressFamily IPv4 | Where-Object { $_.IPAddress -ne $null }
if ($ips.Count -eq 0) {
Add-Content -Path $outputFile -Value "接口: $name" -Encoding UTF8
Add-Content -Path $outputFile -Value " IP地址: 无" -Encoding UTF8
Add-Content -Path $outputFile -Value " MAC地址: $mac" -Encoding UTF8
} else {
foreach ($ip in $ips) {
Add-Content -Path $outputFile -Value "接口: $name" -Encoding UTF8
Add-Content -Path $outputFile -Value " IP地址: $($ip.IPAddress)" -Encoding UTF8
Add-Content -Path $outputFile -Value " MAC地址: $mac" -Encoding UTF8
}
}
Add-Content -Path $outputFile -Value "" -Encoding UTF8
}
# 控制台驻留(兼容所有 PowerShell 版本)
Write-Host "`n系统信息已导出到:" -NoNewline
Write-Host "$outputFile" -ForegroundColor Green
Write-Host "请按任意键退出..."
[void][System.Console]::ReadKey($true)
BAT文件RunSystemInfo.bat内容如下所示
@echo off
:: ========================================================
:: 版权所有 © 2025 笨熊呆呆瓜
:: 联系方式:842668578@qq.com
:: 用途:调用 PowerShell 脚本收集本机系统信息
:: ========================================================
powershell -ExecutionPolicy Bypass -NoExit -File "%~dp0GetSystemInfo.ps1"
运行BAT文件

执行过程如下所示

生成如下结果文件

文件内容如下所示
