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

使用PowerShell调用GPG加密文件无输出问题排查

Windows Server 2019下PowerShell调用GPG加密无输出文件的问题排查

问题描述

在Windows Server 2019上通过PowerShell脚本调用GPG自动加密指定文件夹的.dat文件,调用gpg.exe后无异常提示,但始终未生成加密输出文件。相关脚本代码如下:

[CmdletBinding()]
param()

Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser

$key      = "test@test.com"
$GpgPath  = "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
$localuser = "local@local.com"
$outputdir = "D:\ToBeEncrypted\Output\"
$archivedir = "D:\ToBeEncrypted\Archive\"
$passPhrase = "password"
$sourcePath = "D:\ToBeEncrypted\*.dat"

$filearray  = Get-ChildItem -Path $sourcePath

foreach ($file in $filearray) {

$fileName = $file.Name

$encryptedFileName = "$outputdir" + $fileName + ".txt"

Write-Verbose "Encrypted name: $encryptFileName"

try
    {
    Write-Verbose "GPG Execution Started $file to $encryptedFileName"
    Start-Process -FilePath $GpgPath -ArgumentList "--pinentry-mode=loopback --passphrase $passPhrase --compress-algo 1 --cipher-algo cast5 --armor --recipient $key --local-user $localuser --output $encryptedFileName -se $file"
}
 catch [Exception]
{
    Write-Verbose $_.Exception.Message
    exit 1
}
Write-Verbose "GPG Execution Completed"

}

错误点分析

  1. 变量拼写错误:Write-Verbose中使用了未定义的$encryptFileName,正确变量应为$encryptedFileName,虽不影响加密执行,但会导致日志输出异常,无法确认输出路径是否正确。
  2. 参数传递方式错误:直接将所有GPG参数拼接为字符串传递给Start-Process,若路径、密码包含空格,会被GPG解析为多个无效参数,导致执行失败。
  3. GPG参数顺序错误:-se(签名加密)的位置不符合GPG参数规范,GPG要求输入文件放在参数列表最后,否则无法正确识别要加密的文件。
  4. 未等待进程执行完成:默认Start-Process是异步执行,脚本会直接继续后续逻辑,可能GPG还未完成加密,脚本就已结束,导致输出文件未生成。
  5. 未捕获GPG内部错误:未收集GPG的错误输出,无法得知GPG执行过程中是否出现密钥不匹配、权限不足等问题。
  6. 未确保输出目录存在:如果$outputdir指定的目录不存在,GPG无法写入输出文件,但不会抛出明显异常。

修正后的脚本

[CmdletBinding()]
param()

# 可选:仅当当前用户执行策略不是Unrestricted时才设置,避免重复执行
# if ((Get-ExecutionPolicy -Scope CurrentUser) -ne 'Unrestricted') {
#     Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Scope CurrentUser -Force
# }

$key      = "test@test.com"
$GpgPath  = "C:\Program Files (x86)\GnuPG\bin\gpg.exe"
$localuser = "local@local.com"
$outputdir = "D:\ToBeEncrypted\Output\"
$archivedir = "D:\ToBeEncrypted\Archive\"
$passPhrase = "password"
$sourcePath = "D:\ToBeEncrypted\*.dat"

# 确保输出目录存在,不存在则创建
if (-not (Test-Path -Path $outputdir)) {
    New-Item -ItemType Directory -Path $outputdir | Out-Null
}

$filearray  = Get-ChildItem -Path $sourcePath

foreach ($file in $filearray) {
    $fileName = $file.Name
    # 使用Join-Path拼接路径,避免手动拼接的分隔符问题
    $encryptedFileName = Join-Path -Path $outputdir -ChildPath "$fileName.txt"

    Write-Verbose "Encrypted name: $encryptedFileName"

    try {
        Write-Verbose "GPG Execution Started: $($file.FullName) to $encryptedFileName"
        
        # 用数组传递参数,确保每个参数被GPG正确解析
        $gpgArgs = @(
            "--pinentry-mode=loopback",
            "--passphrase", $passPhrase,
            "--compress-algo", "1",
            "--cipher-algo", "cast5",
            "--armor",
            "--recipient", $key,
            "--local-user", $localuser,
            "--output", $encryptedFileName,
            "-se",
            $file.FullName
        )

        # 启动GPG进程并等待完成,捕获退出码和错误输出
        $process = Start-Process -FilePath $GpgPath -ArgumentList $gpgArgs -Wait -NoNewWindow -PassThru -RedirectStandardError "$outputdir\$fileName.err"
        
        # 检查进程退出码,非0表示加密失败
        if ($process.ExitCode -ne 0) {
            Write-Verbose "GPG加密失败,退出码:$($process.ExitCode),错误日志:$outputdir\$fileName.err"
            exit 1
        }
    }
    catch [Exception] {
        Write-Verbose "脚本执行异常:$($_.Exception.Message)"
        exit 1
    }
    Write-Verbose "GPG执行完成:$fileName"
}

关键修正说明

  • 使用Join-Path拼接输出路径,避免手动拼接导致的路径分隔符错误
  • 改用数组传递GPG参数,彻底解决含空格的参数解析问题
  • 添加-Wait参数等待GPG进程执行完毕,确保加密完成后再继续脚本逻辑
  • 通过-PassThru获取进程退出码,明确判断加密是否成功
  • 重定向GPG错误输出到单独日志文件,方便排查密钥、权限等内部问题
  • 提前检查并创建输出目录,避免因目录不存在导致的写入失败
  • 修正变量拼写错误,确保日志输出准确

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.20 19:18:36