Skip to content

Instantly share code, notes, and snippets.

@altrive
Last active December 14, 2015 17:39
Show Gist options
  • Save altrive/5124149 to your computer and use it in GitHub Desktop.
Save altrive/5124149 to your computer and use it in GitHub Desktop.
Windows Server 2012のWinSxSフォルダをインストールメディアから抽出、指定のディレクトリにコピーするPowerShellコマンドです。 インターネット未接続環境において、ディスク上から削除されている機能をインストールする際にこのWinSxsフォルダが必要となります (例:ServerCoreへの機能追加等) WIMイメージのマウント(Mount-WindowsImage)は時間がかかるので、事前にWinSxSフォルダを抽出しネットワーク共有にコピーしておくと便利です。
<#
.Synopsis
Extract WinSxS data from Windows Image and copy to destination folder
.Description
WinSxS is used to enable Windows features which removed from disk.
In offline environment. Enable feature in ServerCore installation need
WinSxS data that included in full installer image.
WIM extract takes long times operation
so, extract WinSxs and copy to network share and reuse it.
.Parameter MediaPath
ISO Media Image Path or Install Media Drive Root Path E:\
.Parameter WimIndex
Specify Windows Image Index in WIM file.
if you need to enable features in ServerCore OS
you need to select correspod *Full* OS image Index.
* 1: Windows Server 2012 Standard Core
* 2: Windows Server 2012 Standard Full
* 3: Windows Server 2012 Datacenter Core
* 4: Windows Server 2012 Datacenter Full
.Parameter Destination
Target directory to copy WinSxs directory
.Example
$params=@{
MediaPath = [ISO Media Path]
WimIndex = 4 #Windows Server 2012 Datacenter Image Index
Destination = [Copy Destination Path]
}
#Short Path
Copy-WindowsImageSxS @params
#>
function Copy-WindowsImageSxS
{
param(
[Parameter(Mandatory=$true)]
[string]$MediaPath,
[Parameter(Mandatory=$true)]
[int]$WimIndex,
[Parameter(Mandatory=$true)]
[string]$Destination
)
Set-StrictMode -Version Latest
$ErrorActionPreference = "Stop"
#Create SxS distinaion Directory
if(!(Test-Path $Destination))
{
New-Item -Type Directory -Path $Destination | Out-Null
}
try{
#Mount ISO Image or Resolve Media Drive
if([IO.Path]::GetExtension($MediaPath) -eq ".iso")
{
Mount-DiskImage $MediaPath
$driveLetter = (Get-DiskImage $MediaPath | Get-Volume).DriveLetter
$wimPath= "{0}:\sources\install.wim" -f $driveLetter
}
else
{
$wimPath= Join-Path $MediaPath "sources\install.wim" -Resolve
}
#Create Temp Directory to mount Windows Image
#if use GUID to directorynName, PathTooLongException occuer when call GetChildItem
$tempDir = [IO.Path]::GetTempFileName()
Remove-Item -Path $tempdir
New-Item -Type Directory -Path $tempdir | Out-Null #Create Directory(May Conflict Occured?)
#Mount Windows Image
Write-Verbose "Mounting Windows Image..."
Mount-WindowsImage -Path $tempDir -ImagePath $wimPath -Index $wimIndex -ReadOnly -Verbose:$False | Out-Null
#Copy WinSxS Directory
$fromDir = "$($tempDir)\Windows\WinSxS"
$totalSize = (Get-ChildItem $fromDir -Recurse | Measure-Object -Property Length -Sum).Sum
Write-Verbose ("WinSxs Folder Total Size: {0:N2} GB" -f ($totalSize / 1GB))
Write-Verbose "Executing comand robocopy.exe $fromDir $Destination /S "
Write-Progress -Activity "Copying WinSxS Folder..." -Status "Start Copy" -PercentComplete 0
$job = Start-Job {robocopy.exe $args[0] $args[1] /S | Out-Null} -ArgumentList $fromDir,$Destination
while ($job.State -ne "Completed" )
{
$items = (Get-ChildItem $Destination -Recurse | Measure-Object -Property Length -Sum)
if($items -ne $null)
{
Write-Progress -Activity "Copying WinSxS Folder..." -Status "Copying Files" -PercentComplete (($items.Sum/$totalSize)*100)
}
sleep 5
}
Write-Verbose "Copy Operation Finished"
Write-Progress -Activity "Copying WinSxS Folder..." -Completed
}
finally{
#Cleanup
if([IO.Path]::GetExtension($MediaPath) -eq ".iso"){
Dismount-DiskImage $MediaPath -ErrorAction SilentlyContinue
}
try{
Dismount-WindowsImage -Path $tempDir -Discard -Verbose:$False| Out-Null
Remove-Item -Path $tempDir -ErrorAction SilentlyContinue
}
catch{
$Host.UI.WriteErrorLine("Error occured in cleanup" + $_.Exception)
}
}
}
@altrive
Copy link
Author

altrive commented Mar 14, 2013

Usage Sampe:

this script download scripts from Gist. You need to check content is valid before using

$url= "https://gist.github.com/altrive/5124149/raw/37f9e72b8404b43c5628694cdd4eda34c03bd187/Copy-WindowsImageSxS.ps1/Copy-WindowsImageSxS.ps1"
(New-Object Net.WebClient).DownloadString($url) | Invoke-Expression

$params=@{
    MediaPath= "\\172.16.0.1\Shared\Images\9200.16384.WIN8_RTM.120725-1247_X64FRE_SERVER_EVAL_JA-JP-HRM_SSS_X64FREE_JA-JP_DV5.iso"
    WimIndex = 4
    Destination = "\\172.16.0.1\Shared\Images\WinSxs\WinSvr2012_Datacenter"
}
Copy-WindowsImageSxS @params -Verbose

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment