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:
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:
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:
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:
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:
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:
1function Unzip-File {
2
3<#
4.SYNOPSIS
5 Unzip-File is a function which extracts the contents of a zip file.
6
7.DESCRIPTION
8 Unzip-File is a function which extracts the contents of a zip file specified via the -File parameter to the
9location specified via the -Destination parameter. This function first checks to see if the .NET Framework 4.5
10is installed and uses it for the unzipping process, otherwise COM is used.
11
12.PARAMETER File
13 The complete path and name of the zip file in this format: C:\zipfiles\myzipfile.zip
14
15.PARAMETER Destination
16 The destination folder to extract the contents of the zip file to. If a path is no specified, the current path
17is used.
18
19.PARAMETER ForceCOM
20 Switch parameter to force the use of COM for the extraction even if the .NET Framework 4.5 is present.
21
22.EXAMPLE
23 Unzip-File -File C:\zipfiles\AdventureWorks2012_Database.zip -Destination C:\databases\
24
25.EXAMPLE
26 Unzip-File -File C:\zipfiles\AdventureWorks2012_Database.zip -Destination C:\databases\ -ForceCOM
27
28.EXAMPLE
29 'C:\zipfiles\AdventureWorks2012_Database.zip' | Unzip-File
30
31.EXAMPLE
32 Get-ChildItem -Path C:\zipfiles | ForEach-Object {$_.fullname | Unzip-File -Destination C:\databases}
33
34.INPUTS
35 String
36
37.OUTPUTS
38 None
39
40.NOTES
41 Author: Mike F Robbins
42 Website: http://mikefrobbins.com
43 Twitter: @mikefrobbins
44
45#>
46
47 [CmdletBinding()]
48 param (
49 [Parameter(Mandatory=$true,
50 ValueFromPipeline=$true)]
51 [ValidateScript({
52 If ((Test-Path -Path $_ -PathType Leaf) -and ($_ -like "*.zip")) {
53 $true
54 }
55 else {
56 Throw "$_ is not a valid zip file. Enter in 'c:\folder\file.zip' format"
57 }
58 })]
59 [string]$File,
60
61 [ValidateNotNullOrEmpty()]
62 [ValidateScript({
63 If (Test-Path -Path $_ -PathType Container) {
64 $true
65 }
66 else {
67 Throw "$_ is not a valid destination folder. Enter in 'c:\destination' format"
68 }
69 })]
70 [string]$Destination = (Get-Location).Path,
71
72 [switch]$ForceCOM
73 )
74
75 If (-not $ForceCOM -and ($PSVersionTable.PSVersion.Major -ge 3) -and
76 ((Get-ItemProperty -Path "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4\Full" -ErrorAction SilentlyContinue).Version -like "4.5*" -or
77 (Get-ItemProperty -Path "HKLM:\Software\Microsoft\NET Framework Setup\NDP\v4\Client" -ErrorAction SilentlyContinue).Version -like "4.5*")) {
78
79 Write-Verbose -Message "Attempting to Unzip $File to location $Destination using .NET 4.5"
80
81 try {
82 [System.Reflection.Assembly]::LoadWithPartialName("System.IO.Compression.FileSystem") | Out-Null
83 [System.IO.Compression.ZipFile]::ExtractToDirectory("$File", "$Destination")
84 }
85 catch {
86 Write-Warning -Message "Unexpected Error. Error details: $_.Exception.Message"
87 }
88
89 }
90 else {
91
92 Write-Verbose -Message "Attempting to Unzip $File to location $Destination using COM"
93
94 try {
95 $shell = New-Object -ComObject Shell.Application
96 $shell.Namespace($destination).copyhere(($shell.NameSpace($file)).items())
97 }
98 catch {
99 Write-Warning -Message "Unexpected Error. Error details: $_.Exception.Message"
100 }
101
102 }
103
104}
µ