Function to unpack a Zip File

I have seen that there is a Function to create a Zip File and I wondered why there is no Function to unpack a ZipFile as well?

I could use one because I need to add .cab Files with long File names which I can’t copy normaly because the exeed Path length Limits and I would of course prefer a PSADT built in Function.

See Zip missing in toolkit - The Toolkit / Extensions - PSAppDeployToolkit Community

NOTE: the post above is a bit old so if someone has a better way to extract ZIP/CAB files, please share.

FYI: The .net method to unzip is known to be weak. (e.g. can’t handle slightly corrupted ZIP files)
A more reliable solution would be to use 7zip.

Hi!

In my environment, I used WIMs instead of zips. I used the script from Sune, found here.

I made it into a custom functions in the AppDeployToolkitExtensions.ps1, code below:

Mounting Function:

Blockquote
Function MountWIMImage {
[CmdletBinding(SupportsShouldProcess = $False)]Param (
[Parameter(Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]
[String]$SourceWIM,

    [Parameter(Mandatory = $True)]
    [ValidateNotNullOrEmpty()]
    [System.IO.FileInfo]
    [String]$MountDir
)

# Function Variables
$ReturnCode = "0"

Write-Log -Message "  - Directory mount verification . . ."
# Trying to create mount directory if it does not exist
If (!(Test-Path -Path "$MountDir")) {
    Try {
        Write-Log -Message "  - A mount directory was not found. Trying to create mount directory:  $($MountDir)" -Severity 2
        New-Item -Path $MountDir -ItemType Directory | Out-Null
        Write-Verbose "MountWIMImageountImage - Mount Directory:  $($MountDir)"
        Write-Log -Message "  - Creation of the mount directory was successful"
    }
    Catch {
        # Mount directory creation failed. Set return code and write log entry.
        $Script:ReturnCode = 1
        Write-Verbose "MountWIMImage - Return code:  $($ReturnCode)"
        Write-Log -Message "  - Mount directory creation failed. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)" -Severity 3
    }
}
Else {
    Write-Verbose "MountWIMImage - Mount Directory:  $($MountDir)"
    Write-Log -Message "  - A mount directory was found:  $($MountDir)"
}

If (($ReturnCode -eq 0)) {
    # Checking for already mounted images.
    Write-Log -Message "  - Checking for already mounted images . . ."
    $CheckMount = Get-WindowsImage -Mounted
    If (($CheckMount)) {
        Write-Log -Message "  - A mounted image was found." -Severity 2
        Write-Log -Message "  - Path:  $($CheckMount.path)" -Severity 2
        Write-Log -Message "  - ImagePath:  $($CheckMount.ImagePath)" -Severity 2
        Write-Log -Message "  - ImageIndex:  $($CheckMount.ImageIndex)" -Severity 2
        Write-Log -Message "  - MountMode:  $($CheckMount.MountMode)" -Severity 2
        Write-Log -Message "  - MountStatus:  $($CheckMount.MountStatus)" -Severity 2
        Write-Log -Message "  - Trying to unmount image:  $($CheckMount.ImagePath)"

        Get-WindowsImage -Mounted | ForEach-Object { $_ | Dismount-WindowsImage -Discard -ErrorVariable wimerr | Out-Null; if ([bool]$wimerr) { $errflag = $true } }; If (-not $errflag) { Clear-WindowsCorruptMountPoint | Out-Null }

        # Checking for already mounted images again.
        $CheckMount = Get-WindowsImage -Mounted
        If (!($CheckMount)) {
            Write-Log -Message "  - Image unmount was successful"
            Write-Log -Message "  - Trying to mount image:  $($SourceWIM)"
        }
        Else {
            Write-Log -Message "  - Image unmount failed. But the script will try to mount image:  $($SourceWIM)"
        }
    }
    Else {
        Write-Log -Message "  - No mounted images were found. Trying to mount image:  $($SourceWIM)"
    }

    Try {
        # Trying to mount image
        Mount-WindowsImage -ImagePath "$SourceWIM" -Index 1 -Path $MountDir | Out-Null
        Write-Verbose "MountWIMImage - Mounted Image:  $($SourceWIM)"
        Write-Log -Message "  - Image mount was successful"
    }
    Catch {
        # Image mount failed. Set return code and provide help for further investigation.
        $Script:ReturnCode = 1
        Write-Verbose "MountWIMImage - Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)"
        Write-Verbose "MountWIMImage - Return code:  $($ReturnCode)"
        Write-Log -Message "  - Image mount failed. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)" -Severity 3
        If (($_.Exception.Message -Match "wim is already mounted") -or ($_.Exception.Message -Match "wim er allerede tilsluttet") -or ($_.Exception.Message -Match "wim er allerede montert")) {
            Write-Log -Message "For further information, please examine the DISM log:  C:\WINDOWS\Logs\DISM\dism.log" -Severity 2
            Write-Log -Message " " -Severity 2
            Write-Log -Message "Check for mounted image with one of the below commands" -Severity 2
            Write-Log -Message "-------------------------------------------------------------------" -Severity 2
            Write-Log -Message "DISM command:  Dism /Get-MountedImageInfo" -Severity 2
            Write-Log -Message 'PowerShell command:  Get-WindowsImage -Mounted' -Severity 2
            Write-Log -Message " " -Severity 2
            Write-Log -Message "Try unmounting the image with one of the below commands" -Severity 2
            Write-Log -Message "-------------------------------------------------------------------" -Severity 2
            Write-Log -Message "DISM command:  Dism /Unmount-Image /MountDir:$($MountDir) /Discard" -Severity 2
            Write-Log -Message 'PowerShell command:  Get-WindowsImage -Mounted | ForEach-Object {$_ | Dismount-WindowsImage -Discard -ErrorVariable wimerr; if ([bool]$wimerr) {$errflag = $true}}; If (-not $errflag) {Clear-WindowsCorruptMountPoint}' -Severity 2
            Write-Log -Message " " -Severity 2
            Write-Log -Message "Please visit Microsoft Docs for further information about DISM or Get-WindowsImage." -Severity 2
            Write-Log -Message "https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism-image-management-command-line-options-s14" -Severity 2
            Write-Log -Message "https://docs.microsoft.com/en-us/powershell/module/dism/get-windowsimage" -Severity 2
        }
        Else {
            WIMCleanup
        }
    }
}

}

Unmounting Function:

Blockquote
Function UnmountWIMImage {
[CmdletBinding(SupportsShouldProcess = $False)]Param (
[Parameter(Mandatory = $True)]
[ValidateNotNullOrEmpty()]
[System.IO.FileInfo]
[String]$SourceWIM,

    [Parameter(Mandatory = $True)]
    [ValidateNotNullOrEmpty()]
    [System.IO.FileInfo]
    [String]$MountDir
)

Try {
    # Trying to unmount image
    Write-Log -Message "  - Trying to unmount image:  $($SourceWIM)"
    Dismount-WindowsImage -Path $MountDir -Discard | Out-Null
    Write-Verbose "UnmountWIMImage - Unmounting Image:  $($SourceWIM)"
    Write-Log -Message "  - Image unmount was successful"

    If ((Test-Path -Path "$MountDir")) {
        WIMCleanup
    }
}
Catch {
    # Image mount failed. Set return code and provide help for further investigation.
    $Script:ReturnCode = 1
    Write-Verbose "UnmountWIMImage - Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)"
    Write-Verbose "UnmountWIMImage - Return code:  $($ReturnCode)"
    Write-Log -Message "  - Image unmount failed. Error message at line $($_.InvocationInfo.ScriptLineNumber): $($_.Exception.Message)" -Severity 3
    Write-Log -Message "For further information, please examine the DISM log:  C:\WINDOWS\Logs\DISM\dism.log" -Severity 2
    Write-Log -Message " " -Severity 2
    Write-Log -Message "Check for mounted image with one of the below commands" -Severity 2
    Write-Log -Message "-------------------------------------------------------------------" -Severity 2
    Write-Log -Message "DISM command:  Dism /Get-MountedImageInfo" -Severity 2
    Write-Log -Message 'PowerShell command:  Get-WindowsImage -Mounted' -Severity 2
    Write-Log -Message " " -Severity 2
    Write-Log -Message "Try unmounting the image with one of the below commands" -Severity 2
    Write-Log -Message "-------------------------------------------------------------------" -Severity 2
    Write-Log -Message "DISM command:  Dism /Unmount-Image /MountDir:$($MountDir) /Discard" -Severity 2
    Write-Log -Message 'PowerShell command:  Get-WindowsImage -Mounted | ForEach-Object {$_ | Dismount-WindowsImage -Discard -ErrorVariable wimerr; if ([bool]$wimerr) {$errflag = $true}}; If (-not $errflag) {Clear-WindowsCorruptMountPoint}' -Severity 2
    Write-Log -Message " " -Severity 2
    Write-Log -Message "Please visit Microsoft Docs for further information about DISM or Get-WindowsImage." -Severity 2
    Write-Log -Message "https://docs.microsoft.com/en-us/windows-hardware/manufacture/desktop/dism-image-management-command-line-options-s14" -Severity 2
    Write-Log -Message "https://docs.microsoft.com/en-us/powershell/module/dism/get-windowsimage" -Severity 2
}

}

WIMCleanup Function:

Blockquote
Function WIMCleanup {
Try {
# Trying to cleanup the mount directory
Write-Log -Message " - Trying to cleanup the mount directory"
Remove-Item -Path $MountDir -Recurse -ErrorAction SilentlyContinue | Out-Null
Write-Verbose “WIMCleanup - Mount Cleanup: $($MountDir)”
Write-Log -Message " - Mount cleanup was successful"
}
Catch {
# Mount cleanup failed. Write log entry.
Write-Verbose “WIMCleanup - Error message at line $($.InvocationInfo.ScriptLineNumber): $($.Exception.Message)”
Write-Log -Message " - Mount cleanup was unsuccessful" -Severity 2
}
}

Code for the variables in the Deploy-Application.ps1:

Blockquote
##* WIM Varaibles
# WIM path and name
$WimDir = “$PSScriptRoot\Files\Application.wim”

# Mounted WIM location.
$WIMMountDir = "$PSScriptRoot\Files\MountedApplication"

Code in the Deploy-Application.ps1 to mount the WIM:

Blockquote
# If the WIM hasn’t already been mounted, try and mount the WIM containing the application files and folders.
# If mounting failed, log results. Exit script.
If ((Test-Path -Path “$WIMMountDir”) -eq $False) {
Try {
MountWIMImage -SourceWIM “$WimDir” -MountDir “$WIMMountDir”
}
Catch [System.Exception] {
Write-Log -Message “Mounting WIM of $apName failed with error: $_.”
Write-Log -Message “Exiting script with error.”
Exit-Script -ExitCode 1627
}
}

Code in the Deploy-Application.ps1 to unmount the WIM:

Blockquote
# If the WIM hasn’t already been unmounted, try and unmount the WIM containing the application files and folders.
# If unmounting failed, log results. Exit script.
If (Test-Path -Path “$WIMMountDir”) {
Try {
UnmountWIMImage -SourceWIM “$WimDir” -MountDir “$WIMMountDir”
}
Catch [System.Exception] {
Write-Log -Message “Unmounting WIM of $apName failed with error: $_.”
Write-Log -Message “Exiting script with error.”
Exit-Script -ExitCode 1627
}
}

Hope this helps :slight_smile: Again, big props to Sune Thomsen.

1 Like