[英]PowerShell : Script unable to open native file in archive, but able for newly created file
嗨,大家好 !
我创建了一个 powershell 脚本,它通过一些存档文件在其中一个文件中进行一些简单的文本编辑。
我的问题很简单,当我想打开和编辑 xxx.ini 时,它失败了。 然而,当我添加一个 test.ini (或删除 xxx.ini,然后将其重新添加)并尝试在这个新文件上运行完全相同的脚本时,它就可以工作了。
我尝试查找IsReadOnly属性,但它返回 false。
有人能帮忙吗?
if ($f -notmatch "bulkPrefEditor"){
# The zip file to be updated
$file = $f
# Is the file read only ? Let's try to force that to false
$isReadOnly = Get-ItemProperty -Path $file | Select-Object IsReadOnly
Write-Log "Is $file Read-Only : $isReadOnly" "INFO" $logfile
Set-ItemProperty -Path $file -Name IsReadOnly -Value $false
Write-Log "Editing following file : $f" "INFO" $logfile
# Load ZipFile (Compression.FileSystem) if necessary
try { $null = [IO.Compression.ZipFile] }
catch { [System.Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') }
# Open zip file with update mode (Update, Read, Create -- are the options)
try {
$fileZip = [System.IO.Compression.ZipFile]::Open( $file, 'Update' )
}
catch {
Write-Log "Another process has locked the '$file' file." "ERROR" $logfile
Write-Log "Another process has locked the '$file' file."
continue
}
# Finding the specific file within the zip file
try{
$fileZip.Entries | Where-Object { $_.FullName -match "$innerpath" }
} catch {
Write-Log "Could not find $filepath\$innerpath in $f , have you used anti-slash instead of slash ?" "WARN" $logfile
Write-Log "Could not find $filepath\$innerpath in $f , have you used anti-slash instead of slash "
continue
}
pause
# If needed, read the contents of specific file to $text and release the file so to use streamwriter later
try{
$desiredFile = [System.IO.StreamReader]($fileZip.Entries | Where-Object { $_.FullName -match "$innerpath" }).Open()
$text = $desiredFile.ReadToEnd()
$desiredFile.Close()
$desiredFile.Dispose()
}
catch {
Write-Log "Could not read $f/$innerpath in $f " "WARN" $logfile
Write-Log "Could not read $f/$innerpath in $f "
continue
}
我在脚本中添加了一些简单的日志:
2019/11/21 18:40:12 INFO ################### 启动脚本... ############## ###### 2019/11/21 18:40:12 INFO 此脚本将对 C:\Users\pfournet\Documents\Factory\BulkPrefEditor 中包含的文件进行操作 2019/11/21 18:40:12 INFO 此脚本可以看到(4)个文件。 2019/11/21 18:40:12 INFO List of available files (single line): 20191119-123448387 - Copie (2).zip 20191119-123448387 - Copie.zip 20191119-123448387.zip BulkPrefEditor.ps1 BulkPrefEditor_Zip.ps1 2019/ 11/21 18:40:12信息已找到此文件:20191119-123448387 -Copie(2).zip 2019/2021/21/21/21/21/21 18:40:12 INFO THIN222221B. 2011BIE:20191119-119-123488888888888888884888484848484848484848484848484848484848484848484848484848488848 lar /11/21 18:40:12 INFO 此文件已找到:20191119-123448387.zip 2019/11/21 18:40:12 INFO 此脚本将替换此行:use-compression = true 与 use-compression = false 2019/11/21 18:40:12 INFO ################### 开始运营################ ### 2019/11/21 18:40:12 INFO 是 20191119-123448387 - 副本 (2).zip 只读:@{IsReadOnly=False} 2019/11/21 18:40:12 INFO 编辑以下文件: 2 0191119-123448387 - 复制 (2).zip 2019/11/21 18:40:13 警告无法读取 20191119-123448387 - 复制 (2).zip/ul-flow/plugins/19-191.ini in 24481721 (2)。 -123448387 - Copie.zip 2019/11/21 18:40:13 WARN Could not read 20191119-123448387 - Copie.zip/ul-flow/plugins/interactivedata.ini in 20191119-123448387 - Copie.zip 2019/11/21 18:40:13 INFO Is 20191119-123448387.zip Read-Only: @{IsReadOnly=False} 2019/11/21 18:40:13 INFO Editing following file: 20191119-123448387.zip 2019/11/21 18:40 :14 WARN 无法读取 20191119-123448387.ZADCDBD79A8D84 中的 20191119-123448387.zip/ul-flow/plugins/interactivedata.ini 175C229B192AADC02F2Z 2019/11/21 18:40:14 信息 #################### 结束脚本... ############# #######
正如 Rich Moss 在他们的评论中提到的那样,您编写的脚本不会处理对象,并且您正在锁定 zip 文件。 我最初的解决方案是从存档中提取所有文件,修改您需要的文件,然后重新压缩。
Add-Type -AssemblyName System.IO.Compression.FileSystem
$file = Get-ChildItem C:\temp\test3.zip
$tempOutputFolder = "c:\temp\$(New-Guid)"
[System.IO.Compression.ZipFile]::ExtractToDirectory($file.FullName, $tempOutputFolder)
$zippedFilesToEdit = Get-ChildItem $tempOutputFolder -Recurse -File | Where-Object { $_.Name -eq "new 1" }
foreach ($zippedFile in $zippedFilesToEdit){
#Modifiy your file, and save it
Get-Content $zippedFile | for-each {$_ -replace "Pattern","ReplaceWith"} | Out-File $zippedFile.FullName
}
Remove-Item $file.FullName
[System.IO.Compression.ZipFile]::CreateFromDirectory($tempOutputFolder,$file.FullName)
这不如直接从存档中修改文件 object 灵活。 如果你有一个很大的存档/文件,这将花费太长时间,所以我坐下来通过 stream 来完成它。 该脚本有效,但我相信可能会有改进。 (我认为我们实际上可以直接编辑 stream)此外,错误处理可能会更好。 我们希望确保在失败完成时关闭/处理所有对象,因此我们需要一个 try/catch/finally 块围绕整个事物,这需要我们检查单个错误,重新打包并抛出(`Write- Error -ErrorAction Stop) 再次。 这会使调试更加困难,因为您不会看到错误的实际行号。 您必须确保在捕获错误时正确处理预期和意外错误。
这适用于我在 Win 10/PS 5.1 上运行。
编辑我在开头和结尾添加了代码,它将通过创建一个包含 10 个生成文件的 zip 存档来测试这一点,报告大小,然后执行编辑操作并解压缩以检查修改文件的大小。 此代码将从 $Test* 位置删除文件。 在运行之前阅读脚本,以便在按下 F5 之前知道它会做什么
$TestPath = "C:\temp\zipTest"
$testZipPath = "C:\temp\ZipTest.zip"
$filePathToFind = "test 1.txt"
If (-not (Test-Path $TestPath)){New-Item -Path $TestPath -ItemType Directory}
foreach( $i in 1..10){
"Some Text/file contents" | Set-Content -Path "$TestPath\test $i.txt"
}
Remove-Item -Path $testZipPath -Force -ErrorAction SilentlyContinue | Out-Null
[System.IO.Compression.ZipFile]::CreateFromDirectory($TestPath,$testZipPath)
Write-Host "File sizes before any operation: "
Get-ChildItem $testZipPath | foreach { Write-Host "filename: $($_.Name), length: $($_.Length)"}
Write-Host "test zip file size: $(Get-ChildItem $testZipPath | select -ExpandProperty Length)"
$file = $testZipPath
Write-Host ""
Write-Host "Running the opertion to modify the file in the archive"
try{
# Check if zip files exists, and can open the file, then open if possible
If(-not (Test-Path $file)){Write-Error "Zip File does not exist" -ErrorAction Stop}
try { $fileZip = [System.IO.Compression.ZipFile]::Open( $file, 'Update' ) }
catch { Write-Error "Another process has locked the '$file' file." -ErrorAction Stop }
# Finding the specific file within the zip file
try{ $fileZip.Entries | Where-Object { $_.FullName -eq $filePathToFind } | Out-Null}
catch { Write-Error "Could not find $filePathToFind in $file." -ErrorAction Stop }
# If needed, read the contents of specific file to $text and release the file so to use streamwriter later
#Get the entry in the archive that you want to modify
$zippedEntry = $fileZip.Entries | Where-Object { $_.FullName -eq $filePathToFind }
if($zippedEntry -eq $null){Write-Error "Could not find entry in zip file" -ErrorAction Stop}
#Open the file as a stream
$desiredFile = [System.IO.StreamReader]($zippedEntry).Open()
#Read the entire contents to a string variable (Maybe you could manipulate the stream but not sure how to do that)
$text = $desiredFile.ReadToEnd()
#Cleanup
$desiredFile.Close() | Out-Null
$desiredFile.Dispose()| Out-Null
#Modify the contents as needed. In this case I am just setting the contents to a bunch of numbers
[string]$newText = ((1..1000) | % {"$_`n"})
#Delete the entry in the archive
$zippedEntry.Delete()
#Create a new (empty) entry at the path inside the archive
$newEntry = $fileZip.CreateEntry($filePathToFind)
#Open the new entry as a stream and write the new text to it
$stream = [System.IO.StreamWriter] $newEntry.Open()
$stream.Write($newText)
$stream.Close()
}
catch {
throw
}
finally{
# You want to dispose of everything in a finally block so that the objects get removed even if an error is thrown
$desiredFile.Close() | Out-Null
$desiredFile.Dispose()| Out-Null
$stream.Close() | Out-Null
$fileZip.Dispose()| Out-Null
}
Write-Host "Zipped file update complete"
Write-Host ""
# Check zip size and individual file sizes after operation (Just to test. Will delete files on your computer!!!!)
Write-Host "test zip file size after replacement: $(Get-ChildItem $testZipPath | select -ExpandProperty Length)"
$FollowUpTestPath = "$(Split-Path $testZipPath -Parent)\FollowUpTest"
Remove-Item $FollowUpTestPath -Recurse -Force -ErrorAction SilentlyContinue
If(-not (Test-Path $FollowUpTestPath)){New-Item -Path $FollowUpTestPath -ItemType Directory | Out-Null}
[System.IO.Compression.ZipFile]::ExtractToDirectory($testZipPath, $FollowUpTestPath)
Write-Host "File sizes after operation: "
Get-ChildItem $FollowUpTestPath | foreach { Write-Host "filename: $($_.Name), length: $($_.Length)"}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.