I have a script that can open a ZIP file and modify the content of a xml file and working good I want to run for a loop at all the ZIP files and change them but I get an error
$files = Get-ChildItem -path "C:\Temp\SharedFolder\SideVIP" -filter *.VIP
write-host $files
$fileToEdit = "vip.manifest"
$replaceWithVersion = '<Prop Name="WarningDuringUpgrade" Value="False"'
Add-Type -assembly System.IO.Compression.FileSystem
foreach ($file in $files)
{
# Open zip and find the particular file (assumes only one inside the Zip file)
$zip = [System.IO.Compression.ZipFile]::Open($file,"Update")
$nuspecFile = $zip.Entries.Where({$_.name -like $fileToEdit})
# Read the contents of the file
$desiredFile = [System.IO.StreamReader]($nuspecFile).Open()
$text = $desiredFile.ReadToEnd()
$desiredFile.Close()
$desiredFile.Dispose()
$text = $text -replace '<Prop Name="WarningDuringUpgrade" Value="True"',$replaceWithVersion
#update file with new content
$desiredFile = [System.IO.StreamWriter]($nuspecFile).Open()
$desiredFile.BaseStream.SetLength(0)
# Insert the $text to the file and close
$desiredFile.Write($text)
$desiredFile.Flush()
$desiredFile.Close()
# Write the changes and close the zip file
$zip.Dispose()
Write-Host "zip file updated"
}
My guess would be that your code could be failing due to 2 possible reasons, either $nuspecFile
is $null
meaning, inside the .zip
there were no entries with name vip.manifest
or, there were more than 1 entry found. An inner loop should take care of both possibilities. Another thing to note, you're using -like
but no wildcards:
$fileToEdit = "vip.manifest"
....
....
$entries = $zip.Entries.Where({ $_.Name -like $fileToEdit })
Are you sure you didn't mean to do (note the wildcards on $fileToEdit
):
$fileToEdit = "*vip.manifest*"
....
....
$entries = $zip.Entries.Where({ $_.Name -like $fileToEdit })
If not, then you probably want to use -eq
instead of -like
for an exact match of the entry name. I have also changed -replace
for .Replace(..)
string method since, by the looks of it, you want to replace literal strings and there is no regex involved.
Add-Type -Assembly System.IO.Compression.FileSystem
$ErrorActionPreference = 'Stop'
$files = Get-ChildItem -path "C:\Temp\SharedFolder\SideVIP" -Filter *.VIP
$fileToEdit = "vip.manifest"
$toReplace = '<Prop Name="WarningDuringUpgrade" Value="True"'
$replaceWith = '<Prop Name="WarningDuringUpgrade" Value="False"'
foreach ($file in $files) {
try {
$zip = [System.IO.Compression.ZipFile]::Open($file, "Update")
$entries = $zip.Entries.Where({ $_.Name -like $fileToEdit })
foreach($entry in $entries) {
$reader = [System.IO.StreamReader]::new($entry.Open())
$content = $reader.ReadToEnd().Replace($toReplace, $replaceWith)
$writer = [System.IO.StreamWriter]::new($entry.Open())
$writer.BaseStream.SetLength(0)
$writer.Write($content)
$writer, $reader | ForEach-Object Dispose
}
}
catch {
Write-Warning $_.Exception.Message
continue
}
finally {
if($zip) {
$zip.Dispose()
}
}
}
If you're looking to simplify the process demonstrated above, reading a zip archive and replacing the content of zip archive entries, you might find it easier with the PSCompression Module (Disclaimer: I'm the author of this module).
This is how the code would look using the module:
$toReplace = '<Prop Name="WarningDuringUpgrade" Value="True"'
$replaceWith = '<Prop Name="WarningDuringUpgrade" Value="False"'
Get-ChildItem -Path 'C:\Temp\SharedFolder\SideVIP' -Filter *.VIP |
Get-ZipEntry -Include *vip.manifest* -EntryType Archive |
ForEach-Object {
$content = $_ | Get-ZipEntryContent -Raw
$content.Replace($toReplace, $replaceWith) |
Set-ZipEntryContent $_
}