Private/New-CabinetFile.ps1
|
function New-CabinetFile { <# .SYNOPSIS Creates a .cab file from a directory, preserving its folder structure. .DESCRIPTION Generates a temporary DDF (Directive Definition File) listing all files under SourceDirectory with their relative paths, then calls makecab.exe to produce the cabinet archive. The DDF is removed after the process completes. .PARAMETER SourceDirectory Root directory whose contents (recursively) will be packed into the cabinet. .PARAMETER Destination Full path for the output .cab file (e.g. C:\Temp\Logs-Parsed.cab). .OUTPUTS [string] The full path of the created .cab file. #> [CmdletBinding()] param( [Parameter(Mandatory)] [string] $SourceDirectory, [Parameter(Mandatory)] [string] $Destination ) $cabName = Split-Path $Destination -Leaf $cabDir = Split-Path $Destination -Parent $ddfPath = [System.IO.Path]::GetTempFileName() + '.ddf' $files = Get-ChildItem -Path $SourceDirectory -Recurse -File if (-not $files) { throw "No files found in '$SourceDirectory'. Cannot create cabinet." } $ddfLines = [System.Collections.Generic.List[string]]::new() $ddfLines.Add('.OPTION EXPLICIT') $ddfLines.Add(".Set CabinetNameTemplate=$cabName") $ddfLines.Add(".Set DiskDirectoryTemplate=$cabDir") $ddfLines.Add('.Set MaxDiskSize=0') $ddfLines.Add('.Set CompressionType=MSZIP') $ddfLines.Add('.Set Cabinet=on') $ddfLines.Add('.Set Compress=on') foreach ($file in $files) { $relativePath = $file.FullName.Substring($SourceDirectory.TrimEnd('\').Length + 1) $ddfLines.Add("`"$($file.FullName)`" `"$relativePath`"") } [System.IO.File]::WriteAllLines($ddfPath, $ddfLines) try { # Run makecab with WorkingDirectory set to $cabDir so that the side files # it always generates (setup.inf, setup.rpt) land in a known location # and can be cleaned up reliably. $proc = Start-Process -FilePath 'makecab.exe' ` -ArgumentList "/F `"$ddfPath`"" ` -WorkingDirectory $cabDir ` -Wait ` -PassThru ` -WindowStyle Hidden if ($proc.ExitCode -ne 0) { throw "makecab.exe exited with code $($proc.ExitCode). Cabinet creation failed." } } finally { # Remove the temp DDF and the makecab side files (setup.inf, setup.rpt). Remove-Item -LiteralPath $ddfPath -Force -ErrorAction SilentlyContinue Remove-Item -LiteralPath (Join-Path $cabDir 'setup.inf') -Force -ErrorAction SilentlyContinue Remove-Item -LiteralPath (Join-Path $cabDir 'setup.rpt') -Force -ErrorAction SilentlyContinue } if (-not (Test-Path -LiteralPath $Destination)) { throw "makecab.exe completed but output file not found at '$Destination'." } return $Destination } |