针对遗留服务器:如何在PowerShell v2.0中压缩文件为ZIP?
兄弟,我太懂这种遗留系统的痛点了!Compress-Archive确实是PowerShell 5.0才新增的cmdlet,在v2.0里完全没法用。不过不用慌,我们有两种系统自带的方案,既能实现ZIP压缩,还能满足你原来的-Update需求——也就是覆盖更新现有压缩包里的文件。
方案1:用Windows Shell组件(强烈推荐,零依赖)
这个方法靠Windows自带的Shell.Application COM对象实现,几乎所有Windows系统都支持,不需要装任何额外软件,完美适配v2.0。
实现单个文件压缩+更新ZIP的代码
# 先定义你的路径,替换成实际值 $rootFolder = "C:\你的文件夹路径" $sourceFile = Join-Path $rootFolder "temp-file.csv" $destinationZip = Join-Path $rootFolder "temp-file.zip" # 如果ZIP文件不存在,先创建一个空的(必须写ZIP文件头,否则Shell识别不了) if (-not (Test-Path $destinationZip)) { $null = New-Item -Path $destinationZip -ItemType File -Force # 写入ZIP格式的文件头 $zipHeader = [byte[]]@(80, 75, 5, 6) + [byte[]]::CreateInstance([byte], 18) [System.IO.File]::WriteAllBytes($destinationZip, $zipHeader) } # 调用Shell组件处理压缩 $shell = New-Object -ComObject Shell.Application $zipContainer = $shell.NameSpace((Resolve-Path $destinationZip).Path) $fileToCompress = $shell.NameSpace((Resolve-Path $sourceFile).Path).Items() # 复制文件到ZIP,参数4代表覆盖现有文件(对应原来的-Update) $zipContainer.CopyHere($fileToCompress, 4) # 注意:CopyHere是异步执行的,加个短暂等待确保操作完成(大文件可以延长时间) Start-Sleep -Seconds 2 # 用完释放COM对象,避免内存泄漏 [System.Runtime.Interopservices.Marshal]::ReleaseComObject($shell) | Out-Null
这里的关键是CopyHere的参数4,它的作用就是覆盖ZIP里已有的同名文件,完全匹配你原来-Update的需求。
方案2:用.NET Framework(需.NET 4.5+)
如果你的服务器已经安装了.NET Framework 4.5或更高版本(比如Windows Server 2012及以上默认自带,2008 R2需要手动升级),可以用.NET的压缩类来实现,这种方法是同步执行的,不需要等待,逻辑更清晰。
实现代码
# 加载.NET压缩相关的程序集 Add-Type -AssemblyName System.IO.Compression.FileSystem # 定义路径 $rootFolder = "C:\你的文件夹路径" $sourceFile = Join-Path $rootFolder "temp-file.csv" $destinationZip = Join-Path $rootFolder "temp-file.zip" # 打开ZIP文件(不存在则创建),使用Update模式 $zipMode = [System.IO.Compression.ZipArchiveMode]::Update using ($zipArchive = [System.IO.Compression.ZipFile]::Open($destinationZip, $zipMode)) { # 检查ZIP里是否已有目标文件,有的话先删除 $existingEntry = $zipArchive.GetEntry((Split-Path $sourceFile -Leaf)) if ($existingEntry) { $existingEntry.Delete() } # 添加新文件到ZIP [System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile( $zipArchive, $sourceFile, (Split-Path $sourceFile -Leaf) ) }
这个方法不需要处理异步等待的问题,代码更严谨,但前提是服务器必须有.NET 4.5+,如果是特别老的系统可能不适用。
内容的提问来源于stack exchange,提问作者Kerbol




