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

PowerShell中Add-Type加载程序集仅第二次运行脚本才生效问题

问题原因

PowerShell执行脚本前会先完成全脚本的语法解析,其中对[System.IO.Compression.ZipArchiveMode]、[System.IO.Compression.ZipArchive]这类强类型引用的校验,发生在Add-Type代码行实际执行之前。首次运行时程序集还未被加载,语法校验阶段就会抛出类型找不到的错误;第一次运行失败后,Add-Type其实已经完成了程序集加载,程序集被缓存在当前PowerShell会话中,第二次执行时语法校验阶段就能找到对应类型,所以可以正常运行。
另外还有一个隐藏问题:你只加载了System.IO.Compression.FileSystem程序集,而ZipArchive、ZipArchiveMode等基础类型定义在System.IO.Compression程序集中,部分.NET环境下加载前者不会自动关联加载后者,也会加剧这个问题。

解决方法

可以任选以下一种方案修复:

方案1:改用解析前加载的程序集声明

在脚本最开头添加#Requires指令,该指令会在脚本语法解析阶段就完成程序集加载,早于类型校验步骤:

#Requires -Assembly System.IO.Compression
#Requires -Assembly System.IO.Compression.FileSystem

# 后续原有代码保持不变

方案2:移除强类型声明

去掉变量前的强类型标注,避免解析阶段的类型校验,运行到对应代码行时Add-Type已经完成加载,就能正常识别类型:
把原来的

[System.IO.Compression.ZipArchive] $arch = [System.IO.Compression.ZipFile]::Open("$pathforfile",[System.IO.Compression.ZipArchiveMode]::Update)

改成

$arch = [System.IO.Compression.ZipFile]::Open("$pathforfile",[System.IO.Compression.ZipArchiveMode]::Update)

方案3:使用PowerShell原生压缩cmdlet

PowerShell 5.1及以上版本自带Compress-Archivecmdlet,无需手动加载程序集,代码更简洁,也不会出现加载顺序问题,优化后的代码如下:

$Date = (Get-Date).AddMonths(-6)
$path = "xxxx"
$dateforfile = $Date.ToString("yyyyMM")
$pathforfile = Join-Path $path "XML-$dateforfile.zip"

# 单次查询获取符合条件的XML文件
$items = Get-ChildItem -Path $path -Filter "*.xml" -File | Where-Object { $_.LastWriteTime -le $Date }

if ($items.Count -gt 0) {
    # 直接打包文件
    $items | Compress-Archive -DestinationPath $pathforfile -Update
    # 删除源文件
    $items | Remove-Item -Force
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 17:45:05