[英]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.