PowerShell提取ZIP中文件版本与修改日期及定位问题求助
问题:从ZIP包提取二进制文件版本及SQL文件修改日期失败
问题背景
我需要从ZIP压缩包中的EXE、DLL提取文件版本,同时获取SQL文件的修改日期,但遇到了文件定位失败的问题:
- 指定ZIP文件:
$vipFile = Get-ChildItem -ErrorAction Stop -Path "C:\Patch_2029274.vip" - 目标SQL文件名:
$file = 'Pulling%20AD_Domain_Stored%20Procedures_PullAD-sp.sql'
当前ReadFileContentFromArchive函数无法定位目标文件,原因是ZIP条目包含完整路径而非仅文件名。$zipReader的Entries内容如下:
Entries Mode ------- ---- {IDUDatabase_4.0.0.131/IDUDatabase/AD_Domain_Stored%20Procedures_DerivedRelations-sp.sql, IDUDatabase_4.0.0.131/IDUDatabase/Pulling%20AD_Domain_Stored%20Procedures_PullAD-sp.sql, IDUDatabase_4.0.0.131/filesSources.txt, vip.manifest...} Read
当前函数代码
function ReadFileContentFromArchive { param ( [Parameter(Mandatory=$true)][string]$ZipFile, [Parameter(Mandatory=$true)][string]$TargetFile ) #workaround because this fails: [Void][Reflection.Assembly]::LoadWithPartialName('System.IO.Compression') #Add-Type -Path "C:\Program Files (x86)\Reference Assemblies\Microsoft\Framework\.NETFramework\v4.5\System.IO.Compression.FileSystem.dll" $zipReader = [System.IO.Compression.ZipFile]::OpenRead($zipFile) $zipEntry = $zipReader.GetEntry($targetFile) }
调用方式:
$FileInfo = ReadFileContentFromArchive -ZipFile $vipFile -TargetFile $file
解决方案
1. 修复文件定位及功能实现
针对ZIP条目含完整路径的问题,通过提取文件名忽略路径来匹配目标文件,同时实现二进制文件版本提取和SQL文件修改日期获取的功能:
function ReadFileContentFromArchive { param ( [Parameter(Mandatory=$true)][string]$ZipFile, [Parameter(Mandatory=$true)][string]$TargetFile ) # PowerShell 5+默认已加载该程序集,若报错可取消下面注释 # Add-Type -AssemblyName System.IO.Compression.FileSystem $zipReader = [System.IO.Compression.ZipFile]::OpenRead($zipFile) try { # 遍历ZIP条目,匹配文件名(忽略路径) $zipEntry = $zipReader.Entries | Where-Object { [System.IO.Path]::GetFileName($_.FullName) -eq $TargetFile } | Select-Object -First 1 if (-not $zipEntry) { Write-Error "目标文件 $TargetFile 在ZIP包中未找到" return $null } # 根据文件类型执行不同逻辑 $fileExtension = [System.IO.Path]::GetExtension($zipEntry.FullName).ToLower() switch ($fileExtension) { '.sql' { # 直接返回ZIP条目的修改时间作为SQL文件的修改日期 return [PSCustomObject]@{ FileType = 'SQL' ModifyDate = $zipEntry.LastWriteTime EntryFullPath = $zipEntry.FullName } } { $_ -in '.exe', '.dll' } { # 临时解压二进制文件到临时目录,提取版本信息后删除临时文件 $tempFile = [System.IO.Path]::GetTempFileName() try { [System.IO.Compression.ZipFileExtensions]::ExtractToFile($zipEntry, $tempFile, $true) $versionInfo = (Get-Item $tempFile).VersionInfo return [PSCustomObject]@{ FileType = 'Binary' FileVersion = $versionInfo.FileVersion ProductVersion = $versionInfo.ProductVersion ModifyDate = $zipEntry.LastWriteTime EntryFullPath = $zipEntry.FullName } } finally { Remove-Item $tempFile -Force -ErrorAction SilentlyContinue } } default { Write-Warning "不支持处理的文件类型:$fileExtension" return $null } } } finally { # 确保释放ZIP阅读器资源 $zipReader.Dispose() } }
2. 调用示例
$vipFile = Get-ChildItem -ErrorAction Stop -Path "C:\Patch_2029274.vip" $file = 'Pulling%20AD_Domain_Stored%20Procedures_PullAD-sp.sql' $FileInfo = ReadFileContentFromArchive -ZipFile $vipFile.FullName -TargetFile $file # 查看结果 $FileInfo
关键说明
- 使用
[System.IO.Path]::GetFileName()提取ZIP条目的纯文件名,解决路径不一致导致的定位失败问题。 - SQL文件无需解压,直接读取ZIP条目的
LastWriteTime作为修改日期。 - EXE/DLL文件临时解压到系统临时目录,提取版本信息后自动清理临时文件,避免磁盘占用。
- 添加
finally块确保ZIP阅读器资源被正确释放,防止内存泄漏。
内容的提问来源于stack exchange,提问作者Bandit
相关产品推荐
相关产品推荐

