param( [Parameter(Mandatory=$true)] [string]$Command, [string]$WorkDir = $null ) # 1. 处理工作目录 if ([string]::IsNullOrEmpty($WorkDir)) { $WorkDir = $PSScriptRoot } else { # 如果 WorkDir 里包含变量(如 $env:APPDATA),展开它 $WorkDir = $ExecutionContext.InvokeCommand.ExpandString($WorkDir) } # 确保目录存在,否则命令会报错 if (-not (Test-Path $WorkDir)) { Write-Warning "`n[CMD] WARNING: The work dir does not exist, using ($WorkDir)" $WorkDir = $PSScriptRoot } # 2. 处理命令中的环境变量 $ProjectRoot = Split-Path $PSScriptRoot -Parent # === 替换 $PSScriptRoot 为实际的绝对路径 === # 注意:要处理反斜杠转义问题,直接用字符串替换最安全 if ($Command.Contains('$PSScriptRoot')) { $Command = $Command.Replace('$PSScriptRoot', $ProjectRoot) } # 这一步很关键,让你可以写 "echo $env:USERNAME" $Command = $ExecutionContext.InvokeCommand.ExpandString($Command) Write-Host "`n[CMD] Execute: $Command" -ForegroundColor Gray # 3. 启动进程 # /c 表示执行完命令后关闭 cmd 窗口 # /s 开启参数的一般处理(忽略第一个和最后一个引号,为了兼容复杂引号情况) $processOptions = @{ FilePath = "cmd.exe" ArgumentList = "/s", "/c", "`"$Command`"" WorkingDirectory = $WorkDir Wait = $true NoNewWindow = $true PassThru = $true } try { $proc = Start-Process @processOptions # 4. 检查退出代码 (ExitCode) if ($proc.ExitCode -ne 0) { Write-Error "`n[CMD] Failed to execute, exit code: $($proc.ExitCode)" } } catch { Write-Error "`n[CMD] Failed to start process: $_" }