Home > Mobile >  Embed ZIP files directly within a PowerShell script, not in a separate file
Embed ZIP files directly within a PowerShell script, not in a separate file

Time:01-21

I would like to include some small archives, Zip and 7z into PS1. How to put the archive into $string for example? Or what is the best way to include the archive into the script itself, not in separate file? Thank you!

I tried this: https://github.com/AveYo/Compressed2TXT/blob/master/Compressed 2 TXT.bat

CodePudding user response:

First convert the ZIP file to base-64, by entering one of these commands into the console, depending on your PowerShell version:

# PowerShell 5.1
[convert]::ToBase64String((Get-Content 'test.zip' -Encoding byte)) | 
    Set-Content test.zip.base64 -NoNewline

# PowerShell Core 7 
[convert]::ToBase64String((Get-Content 'test.zip' -AsByteStream)) |
    Set-Content test.zip.base64 -NoNewline

Copy-paste the content of the .base64 text file into your PowerShell script and assign it to variable $zipBase64

# Base-64 encoded ZIP file, containing two files 'file1.txt' and 'file2.txt'
$zipBase64 = 'UEsDBAoAAAAAANZbNVblYOeeBQAAAAUAAAAJAAAAZmlsZTEudHh0ZmlsZTFQSwMECgAAAAAA4Vs1Vl8x7gcFAAAABQAAAAkAAABmaWxlMi50eHRmaWxlMlBLAQI/AAoAAAAAANZbNVblYOeeBQAAAAUAAAAJACQAAAAAAAAAICAAAAAAAABmaWxlMS50eHQKACAAAAAAAAEAGAC2cplqgy3ZAQAAAAAAAAAAAAAAAAAAAABQSwECPwAKAAAAAADhWzVWXzHuBwUAAAAFAAAACQAkAAAAAAAAACAgAAAsAAAAZmlsZTIudHh0CgAgAAAAAAABABgAPC3ydIMt2QEAAAAAAAAAAAAAAAAAAAAAUEsFBgAAAAACAAIAtgAAAFgAAAAAAA=='

# Convert the base-64 string into a byte array
$zipByteArray = [convert]::FromBase64String( $zipBase64 )

# Write the byte array into a ZIP file within the current directory
$zipPath = Join-Path $PWD.Path 'output.zip'
[IO.File]::WriteAllBytes( $zipPath, $zipByteArray )

# Extract the ZIP file into sub directory 'files' of the current directory
$outputDir = (New-Item 'files' -ItemType Directory -Force).FullName
Expand-Archive -Path $zipPath -DestinationPath $outputDir

This is straightforward code, but creating an intermediate ZIP file isn't always wanted.

If you have a PowerShell version available that isn't too old (I believe you need PowerShell 5 at a minimum), you can use the ZipArchive class to extract the files from the ZIP directly from an in-memory stream without first writing an intermediate ZIP file.

# Create an in-memory ZipArchive from the $zipByteArray
$zipArchive = [IO.Compression.ZipArchive]::new( [IO.MemoryStream]::new( $zipByteArray ) )

# Create the output directory
$outputDir = (New-Item 'files' -ItemType Directory -Force).FullName

# For each entry in the ZIP archive
foreach( $entry in $zipArchive.Entries ) { 
    
    # Build full output path
    $fullPath = Join-Path $outputDir $entry.FullName

    if( $fullPath.EndsWith('\') ) {
        # This is a directory
        $null = New-Item $fullPath -ItemType Directory -Force
    }
    else {
        # Create output file
        $fileStream = [IO.File]::OpenWrite( $fullPath )
        try {
            # Extract file from ZIP
            $entryStream = $entry.Open()
            $entryStream.CopyTo( $fileStream )
        }
        finally {
            # Make sure to always close the output file otherwise
            # you could end up with an incomplete file.
            $fileStream.Dispose()
        }
    }
}

If you only want to get the content of the files within the ZIP without extracting them to files on disk, you could read the data from the $entryStream in the above example. See System.IO.Stream for available methods to read data from the stream.

  • Related