Поделиться через


Скрипты: извлечение MSU и .cab-файлов

В этой статье содержится руководство по использованию скрипта PowerShell для извлечения .msu и .cab файлов в указанный каталог. Сценарий предназначен для обработки различных сценариев, обеспечения плавного извлечения и даже создания каталогов при необходимости.

Общие сведения о сценариях

Сценарий должен иметь два обязательных параметра:

  • Путь к файлу или .cab файлу .msu
  • Путь назначения, в котором будут храниться извлеченные файлы

Скрипт проверяет наличие указанного файла и целевого каталога и создает целевой каталог, если он не существует. Затем скрипт переходит к извлечению содержимого .msu или .cab файлов и обрабатывает вложенные .cab файлы в процессе.

Пошаговые инструкции по использованию скрипта

  1. Подготовьте скрипт.

    Скопируйте предоставленный скрипт PowerShell в .ps1 файл (например, Extract-MSUAndCAB.ps1).

  2. Выполните скрипт.

    Откройте PowerShell от имени администратора. Перейдите в каталог, в котором сохраняется скрипт. В этом примере выполните скрипт, выполнив команду .\Extract-MSUAndCAB.ps1.

  3. Укажите пути к файлам.

    При появлении запроса укажите пути к .msu извлеченным файлам или .cab файлам. Укажите путь назначения, в котором должны быть сохранены извлеченные файлы.

Пример использования этой команды:

powershell -ExecutionPolicy Bypass -File .\Extract-MSUAndCAB.ps1 -filePath "C:\<path>\<yourfile>.msu" -destinationPath "C:\<path>\<destination>"

Внимание

Этот пример скрипта не поддерживается в любой стандартной программе или службе поддержки Майкрософт.

Пример сценария приводится в виде "как есть", без каких-либо гарантий. Кроме того, корпорация Microsoft отказывается от всех подразумеваемых гарантий, включая в том числе все подразумеваемые гарантии пригодности для продажи или определенной цели.

Весь риск, возникающий из использования или производительности примеров скриптов и документации, остается с вами. Корпорация Майкрософт, ее штатные авторы и другие лица, принимающие участие в создании, подготовке и выпуске сценариев, ни при каких обстоятельствах не несут ответственность за какой-либо ущерб (в том числе, ущерб, вызванный потерей доходов предприятия, остановкой его работы, потерей бизнес-данных и другими материальными потерями), вызванный использованием или неспособностью использовать примеры сценариев и документацию, даже если корпорации Майкрософт известно о возможности нанесения такого ущерба.

param (
    [Parameter(Mandatory = $true)]
    [string]$filePath,
    [Parameter(Mandatory = $true)]
    [string]$destinationPath
)

# Display the note to the user
Write-Host "==========================="
Write-Host
Write-Host -ForegroundColor Yellow "Note: Do not close any Windows opened by this script until it is completed."
Write-Host
Write-Host "==========================="
Write-Host


# Remove quotes if present
$filePath = $filePath -replace '"', ''
$destinationPath = $destinationPath -replace '"', ''

# Trim trailing backslash if present
$destinationPath = $destinationPath.TrimEnd('\')

if (-not (Test-Path $filePath -PathType Leaf)) {
    Write-Host "The specified file does not exist: $filePath"
    return
}

if (-not (Test-Path $destinationPath -PathType Container)) {
    Write-Host "Creating destination directory: $destinationPath"
    New-Item -Path $destinationPath -ItemType Directory | Out-Null
}

$processedFiles = @{}

function Extract-File ($file, $destination) {
    Write-Host "Extracting $file to $destination"
    Start-Process -FilePath "cmd.exe" -ArgumentList "/c expand.exe `"$file`" -f:* `"$destination`" > nul 2>&1" -Wait -WindowStyle Hidden | Out-Null
    $processedFiles[$file] = $true
    Write-Host "Extraction completed for $file"
}

function Rename-File ($file) {
    if (Test-Path -Path $file) {
        $newName = [System.IO.Path]::GetFileNameWithoutExtension($file) + "_" + [System.Guid]::NewGuid().ToString("N") + [System.IO.Path]::GetExtension($file)
        $newPath = Join-Path -Path ([System.IO.Path]::GetDirectoryName($file)) -ChildPath $newName
        Write-Host "Renaming $file to $newPath"
        Rename-Item -Path $file -NewName $newPath
        Write-Host "Renamed $file to $newPath"
        return $newPath
    }
    Write-Host "File $file does not exist for renaming"
    return $null
}

function Process-CabFiles ($directory) {
    while ($true) {
        $cabFiles = Get-ChildItem -Path $directory -Filter "*.cab" -File | Where-Object { -not $processedFiles[$_.FullName] -and $_.Name -ne "wsusscan.cab" }

        if ($cabFiles.Count -eq 0) {
            Write-Host "No more CAB files found in $directory"
            break
        }

        foreach ($cabFile in $cabFiles) {
            Write-Host "Processing CAB file $($cabFile.FullName)"
            $cabFilePath = Rename-File -file $cabFile.FullName

            if ($cabFilePath -ne $null) {
                Extract-File -file $cabFilePath -destination $directory
                Process-CabFiles -directory $directory
            }
        }
    }
}

try {
    # Initial extraction
    if ($filePath.EndsWith(".msu")) {
        Write-Host "Extracting .msu file to: $destinationPath"
        Extract-File -file $filePath -destination $destinationPath
    } elseif ($filePath.EndsWith(".cab")) {
        Write-Host "Extracting .cab file to: $destinationPath"
        Extract-File -file $filePath -destination $destinationPath
    } else {
        Write-Host "The specified file is not a .msu or .cab file: $filePath"
        return
    }

    # Process all .cab files recursively
    Write-Host "Starting to process CAB files in $destinationPath"
    Process-CabFiles -directory $destinationPath
}
catch {
    Write-Host "An error occurred while extracting the file. Error: $_"
    return
}

Write-Host "Extraction completed. Files are located in $destinationPath"
return $destinationPath