New-Cabinet - Easily create CAB files.

Discussion in 'Scripting' started by GodHand, Nov 10, 2018.

  1. GodHand

    GodHand MDL Senior Member

    Jul 15, 2016
    400
    444
    10
    A small function that will quickly create CAB files from any type of source.

    - Uses the StringBuilder class to build the directive file used to create the CAB file due to its ability to concatenate and build very large strings. It then appends and formats the directive file.

    - CAB files can be used to apply packages, files, folders. etc to Windows images, or just to save due to its lossless data compression.

    Code:
    Function New-CabinetFile
    {
    <#
        .SYNOPSIS
            Create compressed Cabinet (CAB) files.
        
        .DESCRIPTION
            Create compressed Cabinet (CAB) files utilizing lossless data compression.
        
        .PARAMETER SourcePath
            The full path to the file, folder or directory that will be compressed into a CAB file.
        
        .PARAMETER DestinationPath
            The full path to where the CAB file will be saved to.  If no destination is entered, the CAB file will be saved to the location the function is run in.
        
        .EXAMPLE
            PS C:\> New-CabinetFile -SourcePath "$HOME\Desktop"
    #>
        
        [CmdletBinding()]
        Param
        (
            [Parameter(Mandatory = $true,
                       ValueFromPipeline = $true,
                       ValueFromPipelineByPropertyName = $true,
                       HelpMessage = 'The full path to the file, folder or directory that will be compressed into a CAB file.')]
            [ValidateNotNullOrEmpty()]
            [string]$SourcePath,
            [Parameter(Mandatory = $false,
                       HelpMessage = 'The full path to where the CAB file will be saved to.')]
            [string]$DestinationPath
        )
        
        Begin
        {
            If (!$DestinationPath) { $DestinationPath = (Get-Location).Path }
            $SourceName = (Get-Item -LiteralPath $SourcePath).Name
            $SourcePath = (Get-Item -LiteralPath $SourcePath).FullName
            $DestinationPath = (Get-Item -LiteralPath $DestinationPath).FullName
            $CabinetName = $SourceName + '.cab'
            $DDFPath = Join-Path -Path $DestinationPath -ChildPath ($SourceName + '.ddf')
        }
        Process
        {
            $DDF = [System.Text.StringBuilder]::New()
            [void]$DDF.AppendLine('.OPTION EXPLICIT')
            [void]$DDF.AppendLine(".Set CabinetNameTemplate=$CabinetName")
            [void]$DDF.AppendLine(".Set DiskDirectory1=$DestinationPath")
            [void]$DDF.AppendLine('.Set Cabinet=ON')
            [void]$DDF.AppendLine('.Set Compress=ON')
            [void]$DDF.AppendLine('.Set CompressionType=LZX')
            [void]$DDF.AppendLine('.Set CabinetFileCountThreshold=0')
            [void]$DDF.AppendLine('.Set FolderFileCountThreshold=0')
            [void]$DDF.AppendLine('.Set FolderSizeThreshold=0')
            [void]$DDF.AppendLine('.Set MaxCabinetSize=0')
            [void]$DDF.AppendLine('.Set MaxDiskFileCount=0')
            [void]$DDF.AppendLine('.Set MaxDiskSize=0')
            Get-ChildItem -Path $SourcePath -Recurse | Unblock-File
            Try
            {
                Get-ChildItem -Path $SourcePath -Recurse | Where-Object { (!$_.PsIsContainer) } | Select-Object -ExpandProperty Fullname |
                Foreach-Object -Process { [void]$DDF.AppendLine("""$_"" ""$($_.SubString($SourcePath.Length + 1))""") } -ErrorAction Stop
                $DDF.ToString() | Out-File -FilePath $DDFPath -Encoding UTF8 -ErrorAction Stop
                $MakeCabinet = Start-Process -FilePath MAKECAB -ArgumentList ("/F `"$DDFPath`"") -Wait -ErrorAction Stop
            }
            Catch
            {
                $MakeCabinet = "Process failed, Error $($_)"
                Write-Warning $MakeCabinet
            }
        }
        End
        {
            Remove-Item -Path $DDFPath -Force -ErrorAction SilentlyContinue
            Remove-Item -Path "$($DestinationPath)\setup.inf" -Force -ErrorAction SilentlyContinue
            Remove-Item -Path "$($DestinationPath)\setup.rpt" -Force -ErrorAction SilentlyContinue
        }
    }