powershellziparchive7zip

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


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%202%20TXT.bat


Solution

  • First convert the ZIP file to base-64, by entering this command into the console:

    # Encode the ZIP as base-64 text file with a maximum line length of 76 chars
    [convert]::ToBase64String([IO.File]::ReadAllBytes("$PWD/test.zip"), 'InsertLineBreaks') | Set-Content test.zip.base64
    

    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 = @'
    UEsDBAoAAAAAANZbNVblYOeeBQAAAAUAAAAJAAAAZmlsZTEudHh0ZmlsZTFQSwMECgAAAAAA4Vs1
    Vl8x7gcFAAAABQAAAAkAAABmaWxlMi50eHRmaWxlMlBLAQI/AAoAAAAAANZbNVblYOeeBQAAAAUA
    AAAJACQAAAAAAAAAICAAAAAAAABmaWxlMS50eHQKACAAAAAAAAEAGAC2cplqgy3ZAQAAAAAAAAAA
    AAAAAAAAAABQSwECPwAKAAAAAADhWzVWXzHuBwUAAAAFAAAACQAkAAAAAAAAACAgAAAsAAAAZmls
    ZTIudHh0CgAgAAAAAAABABgAPC3ydIMt2QEAAAAAAAAAAAAAAAAAAAAAUEsFBgAAAAACAAIAtgAA
    AFgAAAAAAA==
    '@
    
    # 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( [IO.Path]::DirectorySeparatorChar ) ) {
            # 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.