PSWinRAR.psm1
function Compress-WinRAR(){ <# .SYNOPSIS Compress the specified directory into the specified .rar archive .DESCRIPTION Compress the specified directory into the specified .rar archive .PARAMETER DirectoryToCompress Directory which will be compressed into the Archive .PARAMETER ArchivePath Path to .rar file into which the directory will be compressed .PARAMETER CompressionLevel Level of compression. Higher values use more compute power and will possibly result in lower archive size. Permitted Values 0-5 .PARAMETER DictionarySize Size of dictionary to use while compressing. A bigger dictionary results in higher RAM usage and possibly lower archive size. Permitted values are 1-1024 .PARAMETER DictionarySizeUnit Unit for parameter DictionarySize. Possible values are 'k', 'm' and 'g' for kilobytes, megabytes and gigabytes respectively .PARAMETER Threads Number of Threads to use for compression. Permitted values are 1 up to the number of threads of the system .PARAMETER Password Password to be set for the .rar file .PARAMETER ErrorLogFile Path to file where errors will be logged .PARAMETER FileMask Filter files to include .PARAMETER RecoveryPercentage Percentage of archive size that will be dedicated to recovery data .PARAMETER Delete Delete original directory after compression .PARAMETER SafeDelete Move original directory to recycle bin after compression .PARAMETER IgnoreEmptyDirectories Ignore empty directories in the source directory and not adding them to the archive .PARAMETER Recurse Recurse the source directory .PARAMETER SolidArchive Create a solid archive. Results in smaller size but slower read/modify speeds for the archive .PARAMETER TestArchive Test the archive after creation .PARAMETER StructureInArchive Set the directory structure in the Archive. # 'Flat' moves all files into the root of the archive. # 'Relative' moves all files into the archive with their relative paths to the root directory into the archive # 'Full' includes the full path of every file in the archive # 'DriveLetter' acts like 'Full' but also includes the drive letter .PARAMETER UseRAR4 Use older RAR4 compression method instead of RAR5 .PARAMETER PassThruParameters This string gets passed through to the winrar command line tools .INPUTS Pipeline inputs get used as DirectoryToCompress .OUTPUTS Returns the archive Path .EXAMPLE Compress-WinRAR ./Directory/ ./Archive.rar -Threads 8 #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0, Mandatory, ValueFromPipeline)] [Alias("Directory")] [String] $DirectoryToCompress, [Parameter(Position = 1, Mandatory)] [Alias("Archive")] [ValidatePattern(".*\.rar")] [String] $ArchivePath, [Parameter(Position = 2)] [ValidateRange(0,5)] [Byte] $CompressionLevel = 3, [Parameter(Position = 3)] [ValidateRange(1,[Int32]::MaxValue)] [Int32] $DictionarySize = 128, [Parameter(Position = 4)] [ValidateSet("k", "m", "g")] [String] $DictionarySizeUnit = "m", [Parameter(Position = 5)] [ValidateScript({$_ -gt 0 -and $_ -le $Env:NUMBER_OF_PROCESSORS})] [Int16] $Threads = 1, [Parameter(Position = 6)] [ValidateSet("Relative", "Full", "Flat", "DriveLetter")] [String] $ArchiveFileStructure = "Relative", [Parameter(Position = 7)] [ValidateRange(0, 1000)] [Int16] $RecoveryPercentage, [ValidateSet("Store", "Lowest", "Low", "Medium", "High", "Highest")] [String] $Preset, [String] $Password, [String] $ErrorLogFile, [String] $FileMask, [String] $PassThruParameters, [Switch] $Delete, [Switch] $SafeDelete, [Switch] $IgnoreEmptyDirectories, [Switch] $NoRecurse, [Switch] $SolidArchive, [Switch] $TestArchive, [Switch] $UseRAR4 ) $PresetValues = @{ Store = @{ CompressionLevel = 0 DictionarySize = 0 DictionarySizeUnit = "k" Threads = 1 } Lowest = @{ CompressionLevel = 1 DictionarySize = 128 DictionarySizeUnit = "k" Threads = 1 } Low = @{ CompressionLevel = 2 DictionarySize = 1 DictionarySizeUnit = "m" Threads = if($Env:NUMBER_OF_PROCESSORS -gt 1){2}else{1} } Medium = @{ CompressionLevel = 3 DictionarySize = 128 DictionarySizeUnit = "m" Threads = if($Env:NUMBER_OF_PROCESSORS -gt 1){2}else{1} } High = @{ CompressionLevel = 4 DictionarySize = [Math]::Truncate((Get-CIMInstance Win32_OperatingSystem -Verbose:$false -Debug:$false).FreePhysicalMemory / 8) DictionarySizeUnit = "k" Threads = if($Env:NUMBER_OF_PROCESSORS -gt 4){4}else{$Env:NUMBER_OF_PROCESSORS} } Highest = @{ CompressionLevel = 5 DictionarySize = [Math]::Truncate((Get-CIMInstance Win32_OperatingSystem -Verbose:$false -Debug:$false).FreePhysicalMemory / 4) DictionarySizeUnit = "k" Threads = if($Env:NUMBER_OF_PROCESSORS -gt 1){$Env:NUMBER_OF_PROCESSORS - 1}else{1} } } if($Preset){ Write-Verbose "Applying preset $Preset" "CompressionLevel", "DictionarySize", "DictionarySizeUnit", "Threads" | ForEach-Object { if(!$PSBoundParameters[$_]){ Write-Verbose "Setting $_ to $($PresetValues[$Preset][$_]) because of preset $Preset" Set-Variable -Name $_ -Value $PresetValues[$Preset][$_] -Scope "Local" } } } if(!$ArchivePath){ $ArchivePath = $DirectoryToCompress.TrimEnd("\") } if(!$NoRecurse){ $Switches = "$Switches -r" Write-Verbose "Setting parameter -r since switch Recursive is set" } if($Delete){ $Switches = "$Switches -df" Write-Verbose "Setting parameter -df since switch Delete is set" } if($SafeDelete){ $Switches = "$Switches -dr" Write-Verbose "Setting parameter -dr since switch SafeDelete is set" } if($IgnoreEmptyDirectories){ $Switches = "$Switches -ed" Write-Verbose "Setting parameter -ed since switch IgnoreEmptyDirectories is set" } if($ErrorLogFile){ $Switches = "$Switches -ilog$ErrorLogFile" Write-Verbose "Setting parameter -ilog$ErrorLogFile since parameter ErrorLogFile is set" } if($FileMask){ $Switches = "$Switches -n$FileMask" Write-Verbose "Setting parameter -n$FileMask since parameter FileMask is set" } if($Password){ $Switches = "$Switches -p$Password" Write-Verbose "Setting parameter -p$Password since parameter Password is set" } if($RecoveryPercentage){ $Switches = "$Switches -rr$($RecoveryPercentage)p" Write-Verbose "Setting parameter -rr$($RecoveryPercentage)p since parameter RecoveryPercentage is set" } if($SolidArchive){ $Switches = "$Switches -s" Write-Verbose "Setting parameter -s since switch SolidArchive is set" } if($TestArchive){ $Switches = "$Switches -t" Write-Verbose "Setting parameter -t since switch TestArchive is set" } if($Confirm){ $Switches = "$Switches -y" Write-Verbose "Setting parameter -y since switch Confirm is set" } if($UseRAR4){ $Switches = "$Switches -ma4" Write-Verbose "Setting parameter -ma4 since switch UseRAR4 is set" } else{ $Switches = "$Switches -ma5" Write-Verbose "Setting parameter -ma5 since switch UseRAR4 is not set" } switch($ArchiveFileStructure){ "Flat"{ $Switches = "$Switches -ep" Write-Verbose "Setting parameter -ep since StructureInArchive is set to 'Flat'" } "Relative"{ $Switches = "$Switches -ep1" Write-Verbose "Setting parameter -ep1 since StructureInArchive is set to 'Relative'" } "Full"{ $Switches = "$Switches -ep2" Write-Verbose "Setting parameter -ep2 since StructureInArchive is set to 'Full'" } "DriveLetter"{ $Switches = "$Switches -ep3" Write-Verbose "Setting parameter -ep3 since StructureInArchive is set to 'DriveLetter'" } } $Switches = "$Switches -m$CompressionLevel" Write-Verbose "Setting parameter -m$CompressionLevel with value from parameter CompressionLevel" $Switches = "$Switches -md$DictionarySize$DictionarySizeUnit" Write-Verbose "Setting parameter -md$DictionarySize$DictionarySizeUnit with value from parameter DictionarySize" $Switches = "$Switches -mt$Threads" Write-Verbose "Setting parameter -mt$Threads with value from parameter Threads" Write-Verbose "Calling WinRAR via command line: Start-Process -FilePath '$(Get-WinRARPath -ErrorAction "Stop")\Rar.exe' -ArgumentList 'a $PassThruParameters $Switches $ArchivePath $DirectoryToCompress' -Wait -PassThru" $ExitCode = (Start-Process -FilePath "$(Get-WinRARPath -ErrorAction "Stop")\Rar.exe" -ArgumentList "a $PassThruParameters $Switches $ArchivePath $DirectoryToCompress" -Wait -PassThru).ExitCode if($ExitCode -ne 0){ throw "Winrar stopped with exit code $ExitCode" } return $ArchivePath } function Expand-WinRAR(){ <# .SYNOPSIS Expand ("Decompress") a .rar archive into a directory .DESCRIPTION Expand ("Decompress") the specified .rar file into the specified directory .PARAMETER ArchivePath Path to .rar file which will be expanded ("Decompressed") .PARAMETER TargetDirectory Directory into which the contents of the file specified in ArchivePath will be moved. If it does not exist, it will be created .PARAMETER Password Password for the .rar file .INPUTS Pipeline inputs get used as ArchivePath .OUTPUTS Returns the directory path .EXAMPLE Expand-WinRAR ./Archive.rar ./Directory/ #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, HelpMessage = "Path to .rar file which will be decompressed")] [Alias("Archive", "Path")] [ValidatePattern(".*\.rar")] [String] $ArchivePath, [Parameter(Position = 1, Mandatory = $true, HelpMessage = "Directory into which the archive will be decompressed")] [Alias("Target", "Directory")] [String] $TargetDirectory, [Parameter(Position = 2, HelpMessage = "Password to the .rar file")] [String] $Password ) if(!(Test-Path $TargetDirectory)){ New-Item $TargetDirectory -ItemType Directory -Force } if($Password){ $Switches = "$Switches -p$Password" Write-Verbose "Setting parameter -p$Password since parameter Password is set" } if($Confirm){ $Switches = "$Switches -y" Write-Verbose "Setting parameter -y since switch Confirm is set" } Write-Verbose "Calling WinRAR via command line: Start-Process -FilePath '$(Get-WinRARPath -ErrorAction "Stop")\UnRAR.exe' -ArgumentList 'x $Switches $ArchivePath $TargetDirectory' -Wait -PassThru" $ExitCode = (Start-Process -FilePath "$(Get-WinRARPath -ErrorAction "Stop")\UnRAR.exe" -ArgumentList "x $Switches $ArchivePath $TargetDirectory" -Wait -PassThru).ExitCode if($ExitCode -ne 0){ throw "Winrar stopped with exit code $ExitCode" } return $TargetDirectory } function Test-WinRAR(){ <# .SYNOPSIS Test a .rar archive for validity .DESCRIPTION Test a .rar archive for validity .PARAMETER ArchivePath Path to .rar file which will be tested .PARAMETER Password Password for the .rar file .PARAMETER GetReturnCode Pass through the return code from the winrar command line tool instead of $true/$false .INPUTS Pipeline inputs get used as ArchivePath .OUTPUTS Returns $true if the archive is valid, $false if the archive is invalid If the parameter -GetReturnCode is set, the returncode from the winrar command line tool will be passed through instead .EXAMPLE Test-WinRAR ./Archive.rar -GetReturnCode #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, HelpMessage = "Path to .rar file which will be tested")] [Alias("Archive", "Path")] [String] $ArchivePath, [Parameter(Position = 1, HelpMessage = "Password to .rar file")] [String] $Password, [Parameter(HelpMessage = "Return the returncode from the winrar executable instead of true/false")] [Switch] $GetReturnCode ) if($Password){ $Switches = "$Switches -p$Password" Write-Verbose "Setting parameter -p$Password since parameter Password is set" } Write-Verbose "Calling WinRAR via command line: Start-Process -FilePath $(Get-WinRARPath -ErrorAction "Stop")\Rar.exe -ArgumentList t $Switches $ArchivePath -PassThru -Wait" $ReturnCode = (Start-Process -FilePath "$(Get-WinRARPath -ErrorAction "Stop")\Rar.exe" -ArgumentList "t $Switches $ArchivePath" -PassThru -Wait).ExitCode if($GetReturnCode){ return $ReturnCode } else{ if($ReturnCode -eq 0){ return $true } else{ return $false } } } function Repair-WinRAR(){ <# .SYNOPSIS Repair a .rar archive .DESCRIPTION Repair a .rar archive .PARAMETER ArchivePath Path to .rar file which will be repaired .PARAMETER Password Password for the .rar file .PARAMETER GetReturnCode Pass through the return code from the winrar command line tool instead of $true/$false .INPUTS Pipeline inputs get used as ArchivePath .OUTPUTS Returns $true if the archive was repaired successfully, $false if the archive was not repaired If the parameter -GetReturnCode is set, the returncode from the winrar command line tool will be passed through instead .EXAMPLE Test-WinRAR ./Archive.rar -GetReturnCode #> [CmdletBinding(SupportsShouldProcess)] param( [Parameter(Position = 0, Mandatory = $true, ValueFromPipeline = $true, HelpMessage = "Path to .rar file which will be tested")] [Alias("Archive", "Path")] [String] $ArchivePath, [Parameter(Position = 1, HelpMessage = "Password to .rar file")] [String] $Password, [Parameter(HelpMessage = "Return the returncode from the winrar executable instead of true/false")] [Switch] $GetReturnCode ) if($Password){ $Switches = "$Switches -p$Password" Write-Verbose "Setting parameter -p$Password since parameter Password is set" } Write-Verbose "Calling WinRAR via command line: Start-Process -FilePath $(Get-WinRARPath -ErrorAction "Stop")\Rar.exe -ArgumentList r $Switches $ArchivePath -PassThru -Wait" Push-Location (Split-Path $ArchivePath) $ReturnCode = (Start-Process -FilePath "$(Get-WinRARPath -ErrorAction "Stop")\Rar.exe" -ArgumentList "r $Switches $ArchivePath" -PassThru -Wait).ExitCode Pop-Location if($GetReturnCode){ return $ReturnCode } else{ if($ReturnCode -eq 0){ return $true } else{ return $false } } } function Get-WinRARPath(){ [CmdletBinding(SupportsShouldProcess)] param() if(Test-Path "C:\Program Files\WinRAR"){ return "C:\Program Files\WinRAR" } if(Test-Path "C:\Program Files (x86)\WinRAR"){ return "C:\Program Files (x86)\WinRAR" } throw "WinRAR installation not found" } #Check for WinRAR directory on module install and abort installation when WinRAR is not installed if(!(Get-WinRARPath -ErrorAction SilentlyContinue)){ throw "WinRAR installation not found, aborting module installation" } |