PowerShell Function to Unzip Files Using the .NET Framework 4.5 with Fallback to COM

A few days ago, I saw a tweet about someone needing to extract a zip file with PowerShell and wanting to accomplish the task without loading any third party extensions so I thought I would write a function to accomplish the task.

I start out by declaring the function followed by its name, it includes comment based help which is collapsed in the following image, then the [CmdletBinding()] attribute is specified to define this function as an advanced function. Then the param block is opened which is where the parameters are defined:

unzip-file2

The first parameter is “File” which is for the complete path including the name of the zip file. This parameter is mandatory and is also accepted via the pipeline. ValidateScript is used to make sure the value provided is a valid leaf object and that it also at least ends in .zip otherwise an exception is thrown:

unzip-file3

The second parameter is for the “Destination” folder path of where to extract the items contained in the zip file. [ValidateNotNullOrEmpty()] prevents the value specified for this parameter from being just that (the input cannot be Null or Empty). The path is validated to be a container otherwise an exception is thrown. If this parameter is not specified, the current path is used as the default value:

unzip-file4

The last parameter is a switch parameter which means it’s on or off (true or false). This parameter will be used to force the use of COM for the extraction process. Lastly, the param block is closed with a closing parenthesis:

unzip-file5

There’s a lot going on in the “If” block. First, $ForceCOM is checked to make sure it wasn’t specified, then whether or not PowerShell version 3 or greater is being used is checked, and either the full or client profile version of the .NET Framework 4.5 must be present so that’s a total of three things that have to evaluate to true in order for the code inside the “If” block to be executed:

unzip-file6a

If the user of this function specified the $ForceCOM switch parameter, or if a version of PowerShell less than version 3 is being used (PowerShell version 2 would generate an error with the code that’s in the “If” block) or if the .NET Framework 4.5 isn’t installed on the machine this function is being run on, the else block will be executed which uses COM to perform the zip file extraction process:

unzip-file7

I decided to post the code for this function on the TechNet Script Repository so it would be easier to download. You can also download it from here:

µ

5 Comments

  1. Peter Kriegel

    Hi Mike!
    Needful Post!

    I f you dont want to distinct between PowerShell 2.0 and 3.0 you can Zip and unzip files without 3th party tools with .NET 3.0. .Net 3.0 installs the System.IO.Packaging namespace and the ZipPackage class stored in the WindowsBase.DLL: C:Program FilesReference AssembliesMicrosoftFrameworkv3.0WindowsBase.dll

    See: http://thewalkingdev.blogspot.de/2012/07/powershellzip.html
    And: with reflection: http://www.codeproject.com/Articles/209731/Csharp-use-Zip-archives-without-external-libraries

    Reply
  2. randy

    Good stuff. Would be even better if it could handle a password protected files.

    Reply
  3. Thierry Servolle

    Hi Mike,
    Thanks a lot for this.
    However i have an issue that i do not understand. You maybe faced the same issue

    The result on my case is the following

    WARNING: Unexpected Error. Error details: You cannot call a method on a null-valued expression..Exception.Message

    I run your function calling it with a Destination folder which already exist and with a Zip file which i am able to open from UI (so not corrupted)
    I am in a Windows 2008 server

    Reply
  4. Miroslaw

    thanks for this function but when I downloaded it in march 2016, there was already .net 4.6 (w10) and so decided to update your script:
    L88: ((Get-ItemProperty -Path “HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4\Full” -ErrorAction SilentlyContinue).Version -match ‘(4\.[5-9])|(5.+)’ -or
    L89: (Get-ItemProperty -Path “HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4\Client” -ErrorAction SilentlyContinue).Version -match ‘(4\.[5-9])|(5.+)’)) {
    L91: Write-Verbose -Message “Attempting to Unzip $File to location $Destination using .NET $Matches[0]”

    Lines 71-78: added routine to create directory if it is not present during param[ValidateScript]
    Try {
    $_ -match ‘([a-z]:\\)(.*)’
    new-item -path $matches[1] -name $matches[2] -itemtype directory -force
    $true
    }
    catch {
    Write-Warning -Message “Unexpected Error. Error details: $_.Exception.Message”
    }
    Line 109: Respond with “Yes to All” when dialog box asks for it
    $shell.Namespace($destination).copyhere(($shell.NameSpace($file)).items(),16)

    Reply

Leave a Reply

%d bloggers like this: