Is there a way of manipulating zip file contents in memory with Powershell?

后端 未结 3 1774
时光说笑
时光说笑 2021-01-03 06:46

I\'m currently trying to write a powershell function which works with the output of the Lync powershell cmdlet \"Export-CsConfiguration -AsBytes\". When using implicit Power

3条回答
  •  春和景丽
    2021-01-03 07:13

    Making the "Made up Powershell function" a reality:

    #
    #   .SYNOPSIS
    #       Extract a file from a byte[] zip file
    #   
    #   .DESCRIPTION
    #       Extracts a file from a byte[] zip file as byte[]
    #   
    #   .PARAMETER ByteArray
    #       Byte array containing zip file
    #   
    #   .PARAMETER FileInsideZipIWant
    #       The file inside zip I want
    #   
    #   .PARAMETER utf8
    #       If the file is UTF-8 encoded, use this switch to get a string
    #   
    #   .EXAMPLE
    #       PS C:\> $utf8str = Extract-FileFromInMemoryZip -ByteArray $ZipFileBytes -FileInsideZipIWant "DocItemSet.xml" -utf8
    #       PS C:\> $utf8str = Extract-FileFromInMemoryZip $ZipFileBytes "DocItemSet.xml" -utf8
    #       PS C:\> $bs = Extract-FileFromInMemoryZip $ZipFileBytes "DocItemSet.xml"        
    #   
    #   .OUTPUTS
    #       string, byte[]
    #   
    #   .NOTES
    #       Exactly as desired. You may want to change the name of the "FileInsideZipIWant" parameter.
    #       Don't plan on extracting files larger than 2GB.
    #
    function Extract-FileFromInMemoryZip
    {
        [CmdletBinding(DefaultParameterSetName = 'raw')]
        [OutputType([string], ParameterSetName = 'utf8')]
        [OutputType([byte[]], ParameterSetName = 'raw')]
        param
        (
            [Parameter(Mandatory, ValueFromPipelineByPropertyName, Position = 0,
                       HelpMessage = 'Byte array containing zip file')]
            [byte[]]$ByteArray,
            [Parameter(Mandatory, ValueFromPipelineByPropertyName, Position = 1,
                       HelpMessage = 'Single file to extract')]
            [string]$FileInsideZipIWant,
            [Parameter(ParameterSetName = 'utf8')]
            [switch]$utf8
        )
    
        BEGIN { Add-Type -AN System.IO.Compression -ea:Stop } # Stop on error
    
        PROCESS {
            $entry = (
                New-Object System.IO.Compression.ZipArchive(
                    New-Object System.IO.MemoryStream ( ,$ByteArray)
                )
            ).GetEntry($FileInsideZipIWant)
    
            # Note ZipArchiveEntry.Length returns a long (rather than int),
            # but we can't conveniently construct arrays longer than System.Int32.MaxValue
            $b = [byte[]]::new($entry.Length)
    
            # Avoid StreamReader to (dramatically) improve performance
            # ...but it may be useful if the extracted file has a BOM header
            $entry.Open().Read($b, 0, $b.Length)
    
            write $(
                if ($utf8) { [System.Text.Encoding]::UTF8.GetString($b) }
                else { $b }
            )
        }
    }
    

提交回复
热议问题