You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell脚本执行后无法退出,子进程未终止致删除步骤阻塞

问题解决:PowerShell远程安装软件后无法删除安装文件

问题概述

PowerShell脚本从机器A向机器B推送并静默安装软件,安装完成后尝试删除远程机器上的安装文件时失败,脚本卡住无法退出。经排查,原因是安装程序启动的子进程未正常退出,导致安装文件被占用。

原脚本代码

# Define the remote computer name and Software installation package path
$ComputerName = "user1"
$DestFolderPath = "C:\Temp\Test.exe"
$FilePath ="C:\temp\test.exe"

# Create a new PowerShell session to the remote computer
$Session = New-PSSession -ComputerName $ComputerName

#Create the destination folder if not already exist
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
param($DestFolderPath)
if (!(Test-Path $DestFolderPath)) {
}
} -ArgumentList $DestFolderPath

# Copy the software installation package to the remote computer
Copy-Item $FilePath -Destination $DestFolderPath -ToSession $Session

# Install the Software silently on the remote computer
Invoke-Command -Session $Session -ScriptBlock {
param($DestFolderPath)
Start-Process -FilePath $DestFolderPath -ArgumentList "/silent" -wait} -ArgumentList $DestFolderPath

# Remove the installation package from the remote computer
Invoke-Command -ComputerName $ComputerName -ScriptBlock { 
param($DestFolderPath) 
Remove-Item $DestFolderPath -Force -Recurse } -ArgumentList $DestFolderPath

# Close the PowerShell session to the remote computer
Remove-PSSession $Session

解决方法

1. 修复创建文件夹的空逻辑

原脚本中创建目标文件夹的代码块无实际执行语句,先补上这部分确保目录存在:

# Create the destination folder if not already exist
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
    param($DestFolderPath)
    $destDir = Split-Path $DestFolderPath -Parent
    if (!(Test-Path $destDir)) {
        New-Item -ItemType Directory -Path $destDir -Force
    }
} -ArgumentList $DestFolderPath

2. 等待安装程序的所有子进程退出

Start-Process -Wait仅等待主安装进程退出,若存在未终止的子进程会占用安装文件。修改安装步骤,主动检测并处理子进程:

# Install the Software silently on the remote computer
Invoke-Command -Session $Session -ScriptBlock {
    param($DestFolderPath)
    # 启动安装程序并获取进程对象
    $installProcess = Start-Process -FilePath $DestFolderPath -ArgumentList "/silent" -PassThru -Wait
    
    # 查找并等待所有子进程退出,超时后强制终止
    $childProcesses = Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $installProcess.Id }
    foreach ($child in $childProcesses) {
        if (Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue) {
            Wait-Process -Id $child.ProcessId -Timeout 30 -ErrorAction SilentlyContinue
            if (Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue) {
                Stop-Process -Id $child.ProcessId -Force -ErrorAction SilentlyContinue
            }
        }
    }
} -ArgumentList $DestFolderPath

3. 删除文件时添加重试机制

针对偶发的文件占用问题,在删除步骤中加入重试逻辑:

# Remove the installation package from the remote computer
Invoke-Command -ComputerName $ComputerName -ScriptBlock { 
    param($DestFolderPath)
    $retryCount = 3
    $retryDelay = 5
    do {
        try {
            Remove-Item $DestFolderPath -Force -Recurse -ErrorAction Stop
            break
        }
        catch {
            Write-Host "删除失败,重试中... ($retryCount次剩余)"
            Start-Sleep -Seconds $retryDelay
            $retryCount--
        }
    } while ($retryCount -gt 0)
} -ArgumentList $DestFolderPath

完整修复后的脚本

# Define the remote computer name and Software installation package path
$ComputerName = "user1"
$DestFolderPath = "C:\Temp\Test.exe"
$FilePath ="C:\temp\test.exe"

# Create a new PowerShell session to the remote computer
$Session = New-PSSession -ComputerName $ComputerName

# Create the destination folder if not already exist
Invoke-Command -ComputerName $ComputerName -ScriptBlock {
    param($DestFolderPath)
    $destDir = Split-Path $DestFolderPath -Parent
    if (!(Test-Path $destDir)) {
        New-Item -ItemType Directory -Path $destDir -Force
    }
} -ArgumentList $DestFolderPath

# Copy the software installation package to the remote computer
Copy-Item $FilePath -Destination $DestFolderPath -ToSession $Session

# Install the Software silently on the remote computer
Invoke-Command -Session $Session -ScriptBlock {
    param($DestFolderPath)
    $installProcess = Start-Process -FilePath $DestFolderPath -ArgumentList "/silent" -PassThru -Wait
    
    # 查找并等待所有子进程退出
    $childProcesses = Get-CimInstance Win32_Process | Where-Object { $_.ParentProcessId -eq $installProcess.Id }
    foreach ($child in $childProcesses) {
        if (Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue) {
            Wait-Process -Id $child.ProcessId -Timeout 30 -ErrorAction SilentlyContinue
            if (Get-Process -Id $child.ProcessId -ErrorAction SilentlyContinue) {
                Stop-Process -Id $child.ProcessId -Force -ErrorAction SilentlyContinue
            }
        }
    }
} -ArgumentList $DestFolderPath

# Remove the installation package from the remote computer
Invoke-Command -ComputerName $ComputerName -ScriptBlock { 
    param($DestFolderPath)
    $retryCount = 3
    $retryDelay = 5
    do {
        try {
            Remove-Item $DestFolderPath -Force -Recurse -ErrorAction Stop
            break
        }
        catch {
            Write-Host "删除失败,重试中... ($retryCount次剩余)"
            Start-Sleep -Seconds $retryDelay
            $retryCount--
        }
    } while ($retryCount -gt 0)
} -ArgumentList $DestFolderPath

# Close the PowerShell session to the remote computer
Remove-PSSession $Session

内容的提问来源于stack exchange,提问作者Anthony

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.13 07:57:08