Home > Back-end >  Modify txt file inside a ZIP file in PowerShell
Modify txt file inside a ZIP file in PowerShell

Time:02-24

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 enter image description here

$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"
}

CodePudding user response:

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")
    }
    catch {
        Write-Warning $_.Exception.Message
        continue
    }
    $entries = $zip.Entries.Where({ $_.Name -like $fileToEdit })
    foreach($entry in $entries) {
        $reader = [System.IO.StreamReader]::new($entry.Open())
        $content = $reader.ReadToEnd().Replace($toReplace, $replaceWith)
        $reader.Close()
        $reader.Dispose()
        $writer = [System.IO.StreamWriter]::new($entry.Open())
        $writer.BaseStream.SetLength(0)
        $writer.Write($content)
        $writer.Flush()
        $writer.Close()
        $writer.Dispose()
    }
    $zip.Dispose()
}
  • Related