Часто требуется выполнить prestage пакетов, которые нормальным образом не хотят распространяться на SCCM Distribution Point сервера. Для этого можно использовать связку утилиты PSEXEC и утилиты ExtractContent.exe, которая входит в состав установки SCCM DP сервера и выполняет prestage. Утилиту PSEXEC вы должны скачать и положить в папку Windows\System32 заранее.
Я предлагаю мной написанный скрипт, который делает все это автоматически на множественных серверах. Итак, задача: есть пакет или пакеты, которые застряли или зафейлились при распространении на DP. Необходимо сделать prestage таких пакетов на всех DP, где они застряли.
Исходные данные: на всех DP серверах есть диск M:, на который и поставлен SCCM. Файлы pkgx для prestage мы будет складывать на диске M в папку PrestagePKGX. Центральный сервер SCCM — CEN_server.mycorp, сервера, на которых будут создаваться pkgx — DP1.mycorp и DP2.mycorp (на них пакет уже должен быть распространен). Локальное хранилище пакетов pkgx будет находиться в папке M:\Prestage\ на сервере, где вы запускаете скрипт.
Скрипт работает в двух режимах: или пользователь указывает ID пакета, который необходимо запрестейджить или же он указывает *, тогда выполняется престейдж всех пакетов на указанном им DP сервере.
Set-ExecutionPolicy -ExecutionPolicy Bypass -Scope Process
#Import SCCM powershell module
Import-Module "$($ENV:SMS_ADMIN_UI_PATH)\..\ConfigurationManager.psd1" # Import the ConfigurationManager.psd1 module
Set-Location "CEN:" # Set the current location to be the site code.
$date = Get-Date
$log = "c:\temp\package_prestage_mass.txt"
"" | Out-File $log -Append
"==== $date ==== " | Out-File $log -Append
#Package ID to prestage
$PkgID = Read-Host "Enter PackageID"
if ($PkgID -ne "*")
{
#get the list of DP servers where this package failed
$query = Get-WmiObject –NameSpace Root\SMS\Site_CEN –Class SMS_DistributionDPStatus -ComputerName CEN_server.mycorp –Filter "PackageID='$PkgID'" | where MessageState -NE '1' | Select Name, ObjectTypeID
#Didn't find any DPs where this package failed.
If ($query -eq $null) {
Write-Host "No DP found with a package in pending state for this package"
Exit
}
$FileName = "M:\Prestage\$PkgID.pkgx"
$DPName = "DP1.mycorp"
$DPName2 = "DP2.mycorp"
#check if pkgx is already created and located in the storage
if (-Not (Test-Path "M:\Prestage\$PkgID.pkgx")) {
"Package $PkgID file not found in the storage. It will be created now."
$ObjType = $query.ObjectTypeID[0]
"Package Type is $ObjType"
if ($ObjType -eq "2") {
CD "$SitePath"
try {
Publish-CMPrestageContent -PackageID $PkgID -FileName $FileName -DistributionPointName $DPName
"Package $PkgID type $ObjType saved as $FileName" | Out-File $log -Append
}
catch {
Publish-CMPrestageContent -PackageID $PkgID -FileName $FileName -DistributionPointName $DPName2
"Package $PkgID type $ObjType failed on DP1, trying DP2" | Out-File $log -Append
}
}
if ($ObjType -eq "23") {
CD "$SitePath"
try {
Publish-CMPrestageContent -DriverPackageID $PkgID -FileName $FileName -DistributionPointName $DPName
"Package $PkgID type $ObjType saved as $FileName" | Out-File $log -Append
}
catch {
Publish-CMPrestageContent -DriverPackageID $PkgID -FileName $FileName -DistributionPointName $DPName2
"Package $PkgID type $ObjType failed on DP1, trying DP2" | Out-File $log -Append
}
}
if ($ObjType -eq "19") {
CD "$SitePath"
try {
Publish-CMPrestageContent -BootImageId $PkgID -FileName $FileName -DistributionPointName $DPName
"Package $PkgID type $ObjType saved as $FileName" | Out-File $log -Append
}
catch {
Publish-CMPrestageContent -BootImageId $PkgID -FileName $FileName -DistributionPointName $DPName2
"Package $PkgID type $ObjType failed on DP1, trying DP2" | Out-File $log -Append
}
}
if ($ObjType -eq "14") {
CD "$SitePath"
try {
Publish-CMPrestageContent -OperatingSystemImageId $PkgID -FileName $FileName -DistributionPointName $DPName
"Package $PkgID type $ObjType saved as $FileName" | Out-File $log -Append
}
catch {
Publish-CMPrestageContent -OperatingSystemImageId $PkgID -FileName $FileName -DistributionPointName $DPName2
"Package $PkgID type $ObjType failed on DP1, trying DP2" | Out-File $log -Append
}
}
}
else {
"Package $PkgID exists in the storage" | Out-File $log -Append
}
#Start checking every failed DP server: connection, required folders
Foreach ($DP in $query.name) {
cd c:\
"=> Server $DP" | Out-File $log -Append
"Processing server $DP"
if ((Test-Connection $DP -Count 2 -Quiet) -eq $false) {"Connection failed. Server $DP not available"}
else {
if (-Not (Test-Path "\\$DP\m$\PrestagePKGX")) {New-Item -ItemType directory -Path "\\$DP\m$\PrestagePKGX" -Force}
if (-Not (Test-Path "\\$DP\m$\PrestagePKGX\GOOD")) {New-Item -ItemType directory -Path "\\$DP\m$\PrestagePKGX\GOOD" -Force}
if (-Not (Test-Path "\\$DP\m$\PrestagePKGX\Done")) {New-Item -ItemType directory -Path "\\$DP\m$\PrestagePKGX\Done" -Force}
mi -Path \\$DP\m$\PrestagePKGX\*.pkgx -Destination \\$DP\m$\PrestagePKGX\Done -Force
if ((Test-Path "\\$DP\m$\PrestagePKGX\$PkgID.pkgx") -and ((Get-Item $FileName).length -ne (Get-Item "\\$DP\m$\PrestagePKGX\$PkgID.pkgx").length) -or (-not (Test-Path "\\$DP\m$\PrestagePKGX\$PkgID.pkgx"))) {
Copy-Item -Path "Microsoft.PowerShell.Core\FileSystem::$FileName" -Destination "Microsoft.PowerShell.Core\FileSystem::\\$DP\m$\PrestagePKGX" -Force
"$PkgID.pkgx file copied with exitcode $lastExitCode" | Out-File $log -Append
}
else {"File $PkgID.pkgx exists on remote server $DP and has the same size. Will extract it now."}
#Run ExtractContent on every DP
if (Test-Path "\\$DP\m$\SMS_DP$\sms\Tools\ExtractContent.exe")
{ psexec \\$DP /accepteula cmd /c M:\SMS_DP$\sms\Tools\ExtractContent.exe /P:M:\PrestagePKGX\$PkgID.pkgx /f /i >> $log }
else
{ psexec -s \\$DP /accepteula cmd /c M:\CM12\Bin\x64\ExtractContent.exe /P:M:\PrestagePKGX\$PkgID.pkgx /f /i >> $log }
if ($lastExitCode -eq "0") {mi -Path \\$DP\m$\PrestagePKGX\$PkgID.pkgx -Destination \\$DP\m$\PrestagePKGX\GOOD -Force}
else {mi -Path \\$DP\m$\PrestagePKGX\$PkgID.pkgx -Destination \\$DP\m$\PrestagePKGX\Done -Force}
}
}
"ExtractContent completed on $DP with exitcode $lastExitCode" | Out-File $log -Append
}
else {
$DP = Read-Host "Enter DP name"
if (Test-Path "\\$DP\m$\SMS_DP$\sms\Tools\ExtractContent.exe")
{ psexec \\$DP /accepteula cmd /c M:\SMS_DP$\sms\Tools\ExtractContent.exe /P:M:\PrestagePKGX\ /f /i >> $log }
else
{ psexec -s \\$DP /accepteula cmd /c M:\CM12\Bin\x64\ExtractContent.exe /P:M:\PrestagePKGX\ /f /i >> $log }
if ($lastExitCode -eq "0") {mi -Path \\$DP\m$\PrestagePKGX\*.pkgx -Destination \\$DP\m$\PrestagePKGX\GOOD -Force}
else {mi -Path \\$DP\m$\PrestagePKGX\*.pkgx -Destination \\$DP\m$\PrestagePKGX\Done -Force}
"ExtractContent completed on $DP with exitcode $lastExitCode" | Out-File $log -Append
}