776a5f7744
- Convert everything to spaces (fuck you VS Code) - Some initial work to stop relying on Get-LabTempDir - Trying to delete as much code as possible - Define constants all at the top of the file - Improve Get-WebUrl - Improve and simplify architecture handling - Move some more functions to native Powershell from shellouts - Add some functions for dealing w/ Windows Updates
589 lines
26 KiB
PowerShell
589 lines
26 KiB
PowerShell
<#
|
||
jesus fucking christ
|
||
fucking Packer
|
||
TODO:
|
||
- make every function 100% reliant on itself only.
|
||
- get rid of calls to Get-LabTempDir
|
||
- decided whether I'm using $URLs or not lol
|
||
#>
|
||
|
||
|
||
### Global Constants that I use elsewhere
|
||
|
||
$ArchitectureId = @{
|
||
amd64 = "amd64"
|
||
i386 = "i386"
|
||
}
|
||
$WindowsVersionId = @{
|
||
w63 = "w63" # TODO: rename to w81 probably
|
||
w10 = "w10"
|
||
w10ltsb = "w10ltsb"
|
||
server2012r2 = "server2012r2"
|
||
}
|
||
$OfficeVersionId = @{
|
||
o2013 = "o2013"
|
||
}
|
||
$IsoUrls = @{
|
||
$WindowsVersionId.w63 = @{
|
||
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X86FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X86FREE_EN-US_DV9.ISO"
|
||
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X64FREE_EN-US_DV9.ISO"
|
||
}
|
||
$WindowsVersionId.w10 = @{
|
||
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/C/3/9/C399EEA8-135D-4207-92C9-6AAB3259F6EF/10240.16384.150709-1700.TH1_CLIENTENTERPRISEEVAL_OEMRET_X86FRE_EN-US.ISO"
|
||
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/C/3/9/C399EEA8-135D-4207-92C9-6AAB3259F6EF/10240.16384.150709-1700.TH1_CLIENTENTERPRISEEVAL_OEMRET_X64FRE_EN-US.ISO"
|
||
}
|
||
$WindowsVersionId.w10ltsb = @{
|
||
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/6/2/4/624ECF83-38A6-4D64-8758-FABC099503DC/10240.16384.150709-1700.TH1_CLIENTENTERPRISE_S_EVAL_X86FRE_EN-US.ISO"
|
||
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/6/2/4/624ECF83-38A6-4D64-8758-FABC099503DC/10240.16384.150709-1700.TH1_CLIENTENTERPRISE_S_EVAL_X64FRE_EN-US.ISO"
|
||
}
|
||
$WindowsVersionId.server2012r2 = @{
|
||
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/6/2/A/62A76ABB-9990-4EFC-A4FE-C7D698DAEB96/9600.17050.WINBLUE_REFRESH.140317-1640_X64FRE_SERVER_EVAL_EN-US-IR3_SSS_X64FREE_EN-US_DV9.ISO"
|
||
}
|
||
$OfficeVersionId.o2013 = @{
|
||
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/2/9/C/29CC45EF-4CDA-4710-9FB3-1489786570A1/OfficeProfessionalPlus_x86_en-us.img"
|
||
$ArchitectureId.amd64 = "http://care.dlservice.microsoft.com/dl/download/2/9/C/29CC45EF-4CDA-4710-9FB3-1489786570A1/OfficeProfessionalPlus_x64_en-us.img"
|
||
}
|
||
}
|
||
$WSUSCatalogUrl = "http://download.windowsupdate.com/microsoftupdate/v6/wsusscan/wsusscn2.cab"
|
||
$WSUSOfflineRepoBaseUrl = "https://svn.wsusoffline.net/svn/wsusoffline/trunk"
|
||
$szUrl = "http://7-zip.org/a/$szFilename"
|
||
$URLs = @{
|
||
ISOs = @{
|
||
$WindowsVersionId.w63 = @{
|
||
$ArchitectureId.i386 = "http://care.dlservice.microsoft.com/dl/download/B/9/9/B999286E-0A47-406D-8B3D-5B5AD7373A4A/9600.17050.WINBLUE_REFRESH.140317-1640_X86FRE_ENTERPRISE_EVAL_EN-US-IR3_CENA_X86FREE_EN-US_DV9.ISO"
|
||
}
|
||
}
|
||
WindowsUpdateCatalog = "http://download.windowsupdate.com/microsoftupdate/v6/wsusscan/wsusscn2.cab"
|
||
WSUSOfflineRepoBase = "https://svn.wsusoffline.net/svn/wsusoffline/trunk"
|
||
SevenZipDownload = @{
|
||
$ArchitectureId.i386 = "http://7-zip.org/a/7z920.msi"
|
||
$ArchitectureId.amd64 = "http://7-zip.org/a/7z920-x64.msi"
|
||
}
|
||
UltraDefragDownload = @{
|
||
$ArchitectureId.i386 = "http://downloads.sourceforge.net/project/ultradefrag/stable-release/6.1.0/ultradefrag-portable-6.1.0.bin.i386.zip"
|
||
$ArchitectureId.amd64 = "http://downloads.sourceforge.net/project/ultradefrag/stable-release/6.1.0/ultradefrag-portable-6.1.0.bin.amd64.zip"
|
||
}
|
||
SdeleteDownload = "http://download.sysinternals.com/files/SDelete.zip"
|
||
}
|
||
|
||
### Private support functions I use behind the scenes
|
||
|
||
function Get-WebUrl {
|
||
[cmdletbinding(DefaultParameterSetName="outDir")] param(
|
||
[parameter(mandatory=$true)] [string] $url,
|
||
[parameter(mandatory=$true,ParameterSetName="outDir")] [string] $outDir,
|
||
[parameter(mandatory=$true,ParameterSetName="outFile")] [string] $outFile
|
||
)
|
||
if ($PScmdlet.ParameterSetName -match "outDir") {
|
||
$filename = [System.IO.Path]::GetFileName($url)
|
||
$outFile = "$outDir\$filename"
|
||
}
|
||
$outFile = [IO.Path]::GetFullPath($outFile)
|
||
(New-Object System.Net.WebClient).DownloadFile($url, $outFile)
|
||
return (get-item $outFile)
|
||
}
|
||
|
||
function Invoke-ExpressionAndCheck {
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] [string] $command,
|
||
[int] $sleepSeconds
|
||
)
|
||
$global:LASTEXITCODE = 0
|
||
write-verbose "Invoking expression '$command'"
|
||
invoke-expression -command $command
|
||
write-verbose "Expression '$command' had a last exit code of '$LastExitCode'"
|
||
if ($global:LASTEXITCODE -ne 0) {
|
||
throw "LASTEXITCODE: ${global:LASTEXITCODE} for command: '${command}'"
|
||
}
|
||
if ($sleepSeconds) { start-sleep $sleepSeconds }
|
||
}
|
||
|
||
# TODO: Copy-ItemAndExclude
|
||
# function Copy-ItemAndExclude {
|
||
# [cmdletbinding()] param(
|
||
# [parameter(mandatory=$true)] [string] $path,
|
||
# [parameter(mandatory=$true)] [string] $destination,
|
||
# [parameter(mandatory=$true)] [string[]] $exclude,
|
||
# [switch] $force
|
||
# )
|
||
# $path = resolve-path $path | select -expand path
|
||
# $sourceItems = Get-ChildItem -Path $path -Recurse -Exclude $exclude
|
||
# write-verbose "Found $($sourceItems.count) items to copy from '$path'"
|
||
# #$sourceItems | copy-item -force:$force -destination {Join-Path $destination $_.FullName.Substring($path.length)}
|
||
# $sourceItems | copy-item -force:$force -destination {
|
||
# if ($_.GetType() -eq [System.IO.FileInfo]) {
|
||
# Join-Path $destination $_.FullName.Substring($path.length)
|
||
# }
|
||
# else {
|
||
# Join-Path $destination $_.Parent.FullName.Substring($path.length)
|
||
# }
|
||
# }
|
||
# }
|
||
|
||
function Apply-XmlTransform {
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] [string] $xmlFile,
|
||
[parameter(mandatory=$true)] [string] $xsltFile,
|
||
[parameter(mandatory=$true)] [string] $outFile
|
||
)
|
||
$xmlFile = resolve-path $xmlFile | select -expand path
|
||
$xsltFile = resolve-path $xsltFile | select -expand path
|
||
|
||
if (test-path $outFile) { throw "outFile exists at '$outFile'" }
|
||
$outParent = split-path -parent $outFile | resolve-path | select -expand Path
|
||
$outName = split-path -leaf $outFile
|
||
$outFile = "$outParent\$outName"
|
||
|
||
$xslt = New-Object System.Xml.Xsl.XslCompiledTransform
|
||
$xslt.Load($xsltFile)
|
||
$xslt.Transform($xmlFile, $outFile)
|
||
return (get-item $outFile)
|
||
}
|
||
|
||
<#
|
||
.description
|
||
Get the path of the Windows ADK or AIK or whatever the fuck they're calling it from a format string
|
||
- {0} is always the WAIK directory
|
||
- e.g. "C:\Program Files (x86)\Windows Kits\8.1\"
|
||
- e.g. "X:\Program Files\Windows Kits\8.0"
|
||
- {1} is always the host architecture (x86 or amd64)
|
||
- i THINK this is right, but I don't understand WHY. why do you need an amd64 version of oscdimg.exe?
|
||
- however, there are arm executables lying around, and i definitely can't execute those. wtf?
|
||
|
||
So we expect a string like "{0}\bin\{1}\wsutil.exe"
|
||
#>
|
||
function Get-AdkPath {
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] [string] $pathFormatString
|
||
)
|
||
|
||
$adkPath = ""
|
||
$possibleAdkPaths = @("${env:ProgramFiles(x86)}\Windows Kits\8.1","${env:ProgramFiles}\Windows Kits\8.1")
|
||
$possibleAdkPaths |% { if (test-path $_) { $adkPath = $_ } }
|
||
if (-not $adkPath) { throw "Could not find the Windows Automated Installation Kit" }
|
||
write-verbose "Found the WAIK at '$adkPath'"
|
||
|
||
$arch = Get-OSArchitecture
|
||
switch ($arch) {
|
||
$ArchitectureId.i386 {
|
||
$formatted = $pathFormatString -f $adkPath,$waikArch
|
||
if (test-path $formatted) { return $formatted }
|
||
}
|
||
$ArchitectureId.amd64 {
|
||
foreach ($waikArch in @("amd64","x64")) {
|
||
$formatted = $pathFormatString -f $adkPath,$waikArch
|
||
if (test-path $formatted) { return $formatted }
|
||
}
|
||
}
|
||
default {
|
||
throw "Could not determine architecture of '$arch'"
|
||
}
|
||
}
|
||
throw "Could not resolve format string '$pathFormatString' to an existing path"
|
||
}
|
||
|
||
<#
|
||
.notes
|
||
For use with WSUS Offline Updater
|
||
#>
|
||
function Get-WOShortCode { # TODO fixme I think I don't need this anymore because I'm not using WSUS Offline anymore
|
||
param(
|
||
[parameter(mandatory=$true)] [string] $OSName,
|
||
[parameter(mandatory=$true)] [string] $OSArchitecture
|
||
)
|
||
|
||
# I'm adding to this list slowly, only as I encounter the actual names from install.wim
|
||
# on the trial CDs when I actually try to install them
|
||
$shortCodeTable = @{
|
||
"8.1" = "w63"
|
||
}
|
||
|
||
$shortCodeTable.keys |% { if ($OSName -match $_) { $shortCode = $shortCodeTable[$_] } }
|
||
if (-not $shortCode) { throw "Could not determine shortcode for an OS named '$OSName'" }
|
||
|
||
if ($OSArchitecture -match $ArchitectureId.i386) { $shortCode += "" }
|
||
elseif ($OSArchitecture -match $ArchitectureId.amd64) { $shortCode += "-x64" }
|
||
else { throw "Could not determine shortcode for an OS of architecture '$OSArchitecture'" }
|
||
|
||
write-verbose "Found shortcode '$shortcode' for OS named '$OSName' of architecture '$OSArchitecture'"
|
||
return $shortCode
|
||
}
|
||
|
||
|
||
### Publicly exported functions called directly from slipstreaming scripts
|
||
|
||
<#
|
||
.notes
|
||
This is intended for use in the postinstall phase, on the target machine
|
||
We expect calling scripts to get a lab temp dir with this function, but we do NOT permit functions in the module to call it
|
||
TODO: does that even make sense to do??
|
||
Only functions that were intended to run in that phase should have the concept of a "LabTempDir".
|
||
NOTE: this will return the same directory every time it's called until the module is reimported
|
||
#>
|
||
function Get-LabTempDir {
|
||
if ("${script:WinTrialLabTemp}") {} # noop
|
||
elseif ("${env:WinTrialLabTemp}") {
|
||
$script:WinTrialLabTemp = $env:WinTrialLabTemp
|
||
}
|
||
else {
|
||
$dateStamp = get-date -UFormat "%Y-%m-%d-%H-%M-%S"
|
||
$script:WinTrialLabTemp = "${env:Temp}\WinTrialLab-$dateStamp"
|
||
}
|
||
$script:WinTrialLabTemp = [System.IO.Path]::GetFullPath($script:WinTrialLabTemp)
|
||
write-verbose "Using WinTrialLabTemp directory at '${script:WinTrialLabTemp}'"
|
||
if (-not (test-path $script:WinTrialLabTemp)) {
|
||
write-verbose "Temporary directory does not exist, creating it..."
|
||
mkdir -force $script:WinTrialLabTemp | out-null
|
||
}
|
||
return $script:WinTrialLabTemp
|
||
}
|
||
|
||
<#
|
||
.description
|
||
Return the OS Architecture of the current system, as determined by WMI
|
||
Will return either "i386" or "amd64"
|
||
TODO: this isn't a great method but I'm tired of trying to find the totally correct one. This one isn't ideal because OSArchitecture can be localized.
|
||
I've seen some advice that you should call into the registry
|
||
- reg Query "HKLM\Hardware\Description\System\CentralProcessor\0" | find /i "x86" > NUL && set OSARCHITECTURE=32BIT || set OSARCHITECTURE=64BIT
|
||
- http://stackoverflow.com/a/24590583/868206
|
||
- https://support.microsoft.com/en-us/kb/556009
|
||
... however, this lets you know about the HARDWARE, not the OPERATING SYSTEM - we care about the latter
|
||
#>
|
||
function Get-OSArchitecture {
|
||
$OSArch = Get-WmiObject -class win32_operatingsystem -property osarchitecture | select -expand OSArchitecture
|
||
if ($OSArch -match "64") { return $ArchitectureId.amd64 }
|
||
elseif ($OSArch -match "32") { return $ArchitectureId.i386 }
|
||
else { throw "Could not determine OS Architecture from string '$OSArch'" }
|
||
}
|
||
|
||
function Test-AdminPrivileges {
|
||
[cmdletbinding()] param(
|
||
[switch] $ThrowIfNotElevated
|
||
)
|
||
$me = [Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()
|
||
$elevated = $me.IsInRole([Security.Principal.WindowsBuiltInRole] "Administrator")
|
||
if ($ThrowIfNotElevated -and (! $elevated)) { throw "Administrative privileges are required" }
|
||
return $elevated
|
||
}
|
||
|
||
function Install-SevenZip {
|
||
$OSArch = Get-OSArchitecture
|
||
$szDlPath = Get-WebUrl -url $URLs.SevenZipDownload.$OSArch -outDir $env:temp
|
||
try {
|
||
write-verbose "Downloaded '$szUrl' to '$szDlPath', now running msiexec..."
|
||
$msiCall = 'msiexec /qn /i "{0}"' -format $szDlPath
|
||
# Windows suxxx so msiexec sometimes returns right away? or something idk. fuck
|
||
Invoke-ExpressionAndCheck -command $msiCall -sleepSeconds 30
|
||
}
|
||
finally {
|
||
rm -force $szDlPath
|
||
}
|
||
}
|
||
set-alias sevenzip "${env:ProgramFiles}\7-Zip\7z.exe"
|
||
|
||
function Install-VBoxAdditions {
|
||
[cmdletbinding()]
|
||
param(
|
||
[parameter(mandatory=$true)] [string] $isoPath
|
||
)
|
||
$isoPath = resolve-path $isoPath | select -expand Path
|
||
$vbgaPath = "${env:Temp}\InstallVbox"
|
||
try {
|
||
mkdir -force $vbgaPath
|
||
|
||
write-verbose "Extracting iso at '$isoPath' to directory at '$vbgaPath'..."
|
||
Invoke-ExpressionAndCheck -command ('sevenzip x "{0}" -o"{1}"' -f $isoPath, $vbgaPath)
|
||
|
||
write-verbose "Installing the Oracle certificate..."
|
||
$oracleCert = resolve-path "$vbgaPath\cert\oracle-vbox.cer" | select -expand path
|
||
# NOTE: Checking for exit code, but this command will fail with an error if the cert is already installed
|
||
Invoke-ExpressionAndCheck -command ('"{0}" add-trusted-publisher "{1}" --root "{1}"' -f "$vbgaPath\cert\VBoxCertUtil.exe",$oracleCert)
|
||
|
||
write-verbose "Installing the virtualbox additions"
|
||
Invoke-ExpressionAndCheck -command ('"{0}" /with_wddm /S' -f "$vbgaPath\VBoxWindowsAdditions.exe") # returns IMMEDIATELY, goddamn fuckers
|
||
while (get-process -Name VBoxWindowsAdditions*) { write-verbose 'Waiting for VBox install to finish...'; sleep 1; }
|
||
}
|
||
finally {
|
||
rm -recurse -force $vbgaPath
|
||
}
|
||
}
|
||
|
||
function Disable-AutoAdminLogon {
|
||
write-verbose "Function: $($MyInvocation.MyCommand)..."
|
||
set-itemproperty -Path "HKLM:\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Winlogon" -Name AutoAdminLogon -Value 0
|
||
}
|
||
|
||
function Enable-RDP { # TODO fixme
|
||
netsh advfirewall firewall add rule name="Open Port 3389" dir=in action=allow protocol=TCP localport=3389
|
||
reg add "HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server" /v fDenyTSConnections /t REG_DWORD /d 0 /f
|
||
}
|
||
|
||
function Install-CompiledDotNetAssemblies {
|
||
# http://support.microsoft.com/kb/2570538
|
||
# http://robrelyea.wordpress.com/2007/07/13/may-be-helpful-ngen-exe-executequeueditems/
|
||
|
||
$ngen = "${env:WinDir}\microsoft.net\framework\v4.0.30319\ngen.exe"
|
||
Invoke-ExpressionAndCheck -command "$ngen update /force /queue"
|
||
Invoke-ExpressionAndCheck -command "$ngen executequeueditems"
|
||
|
||
if ((Get-OSArchitecture) -match $ArchitectureId.amd64) {
|
||
$ngen64 = "${env:WinDir}\microsoft.net\framework64\v4.0.30319\ngen.exe"
|
||
Invoke-ExpressionAndCheck -command "$ngen64 update /force /queue"
|
||
Invoke-ExpressionAndCheck -command "$ngen64 executequeueditems"
|
||
}
|
||
}
|
||
|
||
function Compress-WindowsInstall {
|
||
$OSArch = Get-OSArchitecture
|
||
try {
|
||
$udfZipPath = Get-WebUrl -url $URLs.UltraDefragDownload.$OSArch -outDir $env:temp
|
||
$udfExPath = "${env:temp}\ultradefrag-portable-6.1.0.$udfArch"
|
||
# This archive contains a folder - extract it directly to the temp dir
|
||
Invoke-ExpressionAndCheck -command ('sevenzip x "{0}" "-o{1}"' -f $udfZipPath,$env:temp)
|
||
|
||
$sdZipPath = Get-WebUrl -url $URLs.SdeleteDownload -outDir $env:temp
|
||
$sdExPath = "${env:temp}\SDelete"
|
||
# This archive does NOT contain a folder - extract it to a subfolder (will create if necessary)
|
||
Invoke-ExpressionAndCheck -command ('sevenzip x "{0}" "-o{1}"' -f $sdZipPath,$sdExPath)
|
||
|
||
stop-service wuauserv
|
||
rm -recurse -force ${env:WinDir}\SoftwareDistribution\Download
|
||
start-service wuauserv
|
||
|
||
Invoke-ExpressionAndCheck -command ('{0} --optimize --repeat "{1}"' -f $udfExPath\udefrag.exe,"$env:SystemDrive")
|
||
|
||
Set-ItemProperty -path HKCU\Software\Sysinternals\SDelete -name EulaAccepted -value 1 }
|
||
Invoke-ExpressionAndCheck -command ('{0} -q -z "{1}"' -f $sdExPath,$env:SystemDrive)
|
||
}
|
||
finally {
|
||
rm -recurse -force $udfZipPath,$udfExPath,$sdZipPath,$sdExPath -ErrorAction Continue
|
||
}
|
||
}
|
||
|
||
function Disable-WindowsUpdates {
|
||
Test-AdminPrivileges -ThrowIfNotElevated
|
||
|
||
$Updates = (New-Object -ComObject "Microsoft.Update.AutoUpdate").Settings
|
||
if ($Updates.ReadOnly) {
|
||
throw "Cannot update Windows Update settings due to GPO restrictions."
|
||
}
|
||
|
||
$Updates.NotificationLevel = 1 # 1 = Disabled lol
|
||
$Updates.Save()
|
||
$Updates.Refresh()
|
||
}
|
||
|
||
function Enable-MicrosoftUpdate {
|
||
[cmdletbinding()] param()
|
||
write-verbose "Enabling Microsoft Update..."
|
||
stop-service wuauserv
|
||
$auKey = "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update"
|
||
Set-ItemProperty -path $auKey -name EnableFeaturedSoftware -value 1
|
||
Set-ItemProperty -path $auKey -name IncludeRecommendedUpdates -value 1
|
||
|
||
$ServiceManager = New-Object -ComObject "Microsoft.Update.ServiceManager"
|
||
$ServiceManager.AddService2("7971f918-a847-4430-9279-4a52d1efe18d",7,"")
|
||
|
||
start-service wuauserv
|
||
}
|
||
|
||
function Install-Chocolatey {
|
||
[cmdleetbinding()] param()
|
||
|
||
$chocoExePath = "${env:ProgramData}\Chocolatey\bin"
|
||
if ($($env:Path).ToLower().Contains($($chocoExePath).ToLower())) {
|
||
write-verbose "Chocolatey already in path, exiting..."
|
||
return
|
||
}
|
||
|
||
$systemPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::Machine)
|
||
$systemPath += ";$chocoExePath"
|
||
[Environment]::SetEnvironmentVariable("PATH", $systemPath, [System.EnvironmentVariableTarget]::Machine)
|
||
|
||
$env:Path = $systemPath
|
||
$userPath = [Environment]::GetEnvironmentVariable('Path', [System.EnvironmentVariableTarget]::User)
|
||
if ($userPath) { $env:Path += ";$userPath" }
|
||
|
||
iex ((new-object net.webclient).DownloadString('https://chocolatey.org/install.ps1'))
|
||
}
|
||
|
||
function Set-UserOptions {
|
||
[cmdletbinding()] param(
|
||
[switch] $ShowHiddenFiles,
|
||
[switch] $ShowSystemFiles,
|
||
[switch] $ShowFileExtensions,
|
||
[switch] $ShowStatusBar,
|
||
[switch] $DisableSharingWizard,
|
||
[switch] $EnablePSOnWinX,
|
||
[switch] $EnableQuickEdit
|
||
)
|
||
$explorerAdvancedKey = 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced'
|
||
if ($ShowHiddenFiles) { Set-ItemProperty -path $explorerAdvancedKey -name Hidden -value 1 }
|
||
if ($ShowSystemFiles) { Set-ItemProperty -path $explorerAdvancedKey -name ShowSuperHidden -value 1 }
|
||
if ($ShowFileExtensions) { Set-ItemProperty -path $explorerAdvancedKey -name HideFileExt -value 0 }
|
||
if ($ShowStatusBar) { Set-ItemProperty -path $explorerAdvancedKey -name ShowStatusBar -value 1 }
|
||
if ($DisableSharingWizard) { Set-ItemProperty -path $explorerAdvancedKey -name SharingWizardOn -value 0 }
|
||
if ($EnablePSOnWinX) { Set-ItemProperty -path $explorerAdvancedKey -name DontUsePowerShellOnWinX -value 0 }
|
||
|
||
$consoleKey = "HKCU:\Console"
|
||
if ($EnableQuickEdit) { Set-ItemProperty -path $consoleKey -name QuickEdit -value 1 }
|
||
}
|
||
|
||
function Disable-HibernationFile {
|
||
[cmdletbinding()] param()
|
||
write-verbose "Removing Hibernation file..."
|
||
$powerKey = 'HKLM:\SYSTEM\CurrentControlSet\Control\Power'
|
||
Set-ItemProperty -path $powerKey -name HibernateFileSizePercent -value 0 # hiberfil is zero bytes
|
||
Set-ItemProperty -path $powerKey -name HibernateEnabled -value 0 # disable hibernation altogether
|
||
}
|
||
|
||
function Enable-WinRM { # TODO fixme, would prefer this to be in Powershell if possible. also it's totally insecure
|
||
[cmdletbinding()] param()
|
||
write-verbose "Enabling WinRM..."
|
||
|
||
cmd /c winrm quickconfig -q
|
||
cmd /c winrm quickconfig -transport:http
|
||
cmd /c winrm set winrm/config @{MaxTimeoutms="1800000"}
|
||
cmd /c winrm set winrm/config/winrs @{MaxMemoryPerShellMB="1800"}
|
||
cmd /c winrm set winrm/config/service @{AllowUnencrypted="true"}
|
||
cmd /c winrm set winrm/config/service/auth @{Basic="true"}
|
||
cmd /c winrm set winrm/config/client/auth @{Basic="true"}
|
||
cmd /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"}
|
||
cmd /c netsh advfirewall firewall set rule group="remote administration" new enable=yes
|
||
cmd /c netsh firewall add portopening TCP 5985 "Port 5985"
|
||
cmd /c net stop winrm
|
||
cmd /c sc config winrm start= auto
|
||
cmd /c net start winrm
|
||
|
||
<#
|
||
# cmd /c winrm quickconfig -q
|
||
# cmd /c winrm quickconfig -transport:http
|
||
Enable-PSRemoting –force -SkipNetworkProfileCheck
|
||
|
||
set-item wsman:\localhost\MaxTimeoutms -value 1800000 -force
|
||
set-item wsman:\localhost\Shell\MaxMemoryPerShellMB -value 1800 -force
|
||
set-item wsman:\localhost\Service\AllowUnencrypted -value $true -force
|
||
set-item wsman:\localhost\Service\Auth\Basic -value $true -force
|
||
set-item wsman:\localhost\Client\Auth\Basic -value $true -force
|
||
|
||
# cmd /c winrm set winrm/config/listener?Address=*+Transport=HTTP @{Port="5985"}
|
||
$httpListener = $null
|
||
foreach ($listener in (ls WSMan:\localhost\Listener)) {
|
||
foreach ($key in $listener.keys) {
|
||
$subKey = $key.split("=")[0]
|
||
$subVal = $key.split("=")[1]
|
||
if (($subKey -match "Transport") -and ($subVal = "HTTP")) {
|
||
$httpListener = $listener
|
||
break
|
||
}
|
||
}
|
||
if ($httpListener) { break }
|
||
}
|
||
set-item $httpListener -value 5894
|
||
|
||
Set-Item wsman:\localhost\client\auth\CredSSP -value true -force
|
||
Enable-WSManCredSSP -force -role server -force
|
||
#set-item wsman:localhost\client\trustedhosts -value * -force
|
||
#set-item wsman:localhost\client\trustedhosts -value 1.1.2.242
|
||
set-item wsman:\localhost\listener\listener*\port -value 81 -force
|
||
|
||
stop-service winrm
|
||
set-service -StartupType "automatic"
|
||
start-service winrm
|
||
|
||
winrm get winrm/config
|
||
winrm enumerate winrm/config/listener
|
||
#>
|
||
}
|
||
|
||
function Set-PasswordExpiry { # TODO fixme use pure Powershell
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] [string] $accountName,
|
||
[parameter(mandatory=$true)] [bool] $expirePassword
|
||
)
|
||
$pe = "TRUE"
|
||
if (-not $expirePassword) { $pe = "FALSE" }
|
||
cmd.exe /c wmic useraccount where "name='$accountName'" set "PasswordExpires=$pe"
|
||
}
|
||
|
||
function New-WindowsInstallMedia { # TODO fixme not sure I wanna handle temp dirs this way??
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] [string] $sourceIsoPath,
|
||
[parameter(mandatory=$true)] [string] $installMediaTemp, # WILL BE DELETED
|
||
[parameter(mandatory=$true)] [string] $installWimPath, # your new install.wim file
|
||
[parameter(mandatory=$true)] [string] $outputIsoPath
|
||
)
|
||
$oscdImgPath = Get-AdkPath "{0}\Assessment and Deployment Kit\Deployment Tools\{1}\Oscdimg\oscdimg.exe"
|
||
$installWimPath = resolve-path $installWimPath | select -expand path
|
||
$installMediaTemp = mkdir -force $installMediaTemp | select -expand fullname
|
||
|
||
$outputIsoParentPath = split-path $outputIsoPath -parent
|
||
$outputIsoFilename = split-path $outputIsoPath -leaf
|
||
$outputIsoParentPath = mkdir -force $outputIsoParentPath | select -expand fullname
|
||
|
||
if (test-path $installMediaTemp) { rm -recurse -force $installMediaTemp }
|
||
mkdir -force $installMediaTemp | out-null
|
||
|
||
$diskVol = get-diskimage -imagepath $sourceIsoPath | get-volume
|
||
if (-not $diskVol) {
|
||
mount-diskimage -imagepath $sourceIsoPath
|
||
$diskVol = get-diskimage -imagepath $sourceIsoPath | get-volume
|
||
}
|
||
$driveLetter = $diskVol | select -expand DriveLetter
|
||
$existingInstallMediaDir = "${driveLetter}:"
|
||
|
||
# TODO: the first copy here copies the original install.wim, and the second copies the new one over it
|
||
# this is really fucking dumb right? but then, THIS is way fucking dumber:
|
||
# http://stackoverflow.com/questions/731752/exclude-list-in-powershell-copy-item-does-not-appear-to-be-working
|
||
# PS none of those solutions are generic enough to get included so fuck it
|
||
copy-item -recurse -path "$existingInstallMediaDir\*" -destination "$installMediaTemp" -verbose:$verbose
|
||
remove-item -force -path "$installMediaTemp\sources\install.wim"
|
||
copy-item -path $installWimPath -destination "$installMediaTemp\sources\install.wim" -force -verbose:$verbose
|
||
|
||
$etfsBoot = resolve-path "$existingInstallMediaDir\boot\etfsboot.com" | select -expand Path
|
||
$oscdimgCall = '& "{0}" -m -n -b"{1}" "{2}" "{3}"' -f @($oscdImgPath, $etfsBoot, $installMediaTemp, $outputIsoPath)
|
||
write-verbose "Calling OSCDIMG: '$oscdimgCall"
|
||
Invoke-ExpressionAndCheck $oscdimgCall -verbose:$verbose
|
||
|
||
dismount-diskimage -imagepath $sourceIsoPath
|
||
}
|
||
|
||
function Get-WindowsUpdateUrls { # TODO: is this how we wanna do temps tho?
|
||
[cmdletbinding()] param(
|
||
[parameter(mandatory=$true)] $windowsVersion,
|
||
[parameter(mandatory=$true)] $osArchitecture,
|
||
[parameter(mandatory=$true)] $packageXml,
|
||
[parameter(mandatory=$true)] $outFile,
|
||
[switch] $debugSaveXslt
|
||
)
|
||
$xsltPath = [IO.Path]::GetTempFileName()
|
||
write-verbose "Downloading XSLT to '$xsltPath'"
|
||
|
||
if ($osArchitecture -match $ArchitectureId.i386) { $arch = "x86" }
|
||
elseif ($osArchitecture -match $ArchitectureId.amd64) { $arch = "x64" }
|
||
else { throw "Dunno bout architecture '$osArchitecture'" }
|
||
|
||
$xsltUrl = "$WSUSOfflineRepoBaseUrl/xslt/ExtractDownloadLinks-$windowsVersion-$arch-glb.xsl"
|
||
Get-WebFile -url $xsltUrl -outFile $xsltPath
|
||
|
||
Apply-XmlTransform -xmlFile $packageXml -xsltFile $xsltPath -outFile $outFile
|
||
if (-not $debugSaveXslt) { rm -force $xsltPath }
|
||
|
||
return $outFile
|
||
}
|
||
|
||
|
||
# Exports: #TODO
|
||
$emmParams = @{
|
||
Alias = @("sevenzip")
|
||
Variable = @("ArchitectureId")
|
||
Function = "*"
|
||
# Function = @(
|
||
# "Get-OSArchitecture"
|
||
# "Get-LabTempDir"
|
||
# "Install-SevenZip"
|
||
# "Install-VBoxAdditions"
|
||
# )
|
||
}
|
||
export-modulemember @emmParams
|