From 6818922ba8de6b60b81f952491791e52e718ea54 Mon Sep 17 00:00:00 2001 From: Alan Mason <1923621+2Shirt@users.noreply.github.com> Date: Fri, 24 Nov 2017 20:59:32 -0800 Subject: [PATCH] 2016-03: Retroactive Updates * Started work on building 32-bit and 64-bit images --- System32/startnet.cmd | 11 - WK_32/CPU-Z/cpuz.ini | 20 + {WK => WK_32}/ConEmu/ConEmu.xml | 0 {WK => WK_32}/Explorer++/config.xml | 4 +- {WK => WK_32}/HWMonitor/hwmonitorw.ini | 0 {WK => WK_32}/Notepad2/Notepad2.ini | 42 +- {WK => WK_32}/Scripts/WK.ps1 | 21 +- {WK => WK_32}/Scripts/imaging.ps1 | 36 +- {WK => WK_32}/Scripts/init.ps1 | 0 {WK => WK_32}/Scripts/servers.ps1 | 0 WK_64/CPU-Z/cpuz.ini | 20 + WK_64/ConEmu/ConEmu.xml | 643 +++++++++++++++++++++++++ WK_64/Explorer++/config.xml | 113 +++++ WK_64/HWMonitor/hwmonitorw.ini | 8 + WK_64/Notepad2/Notepad2.ini | 106 ++++ WK_64/Scripts/WK.ps1 | 116 +++++ WK_64/Scripts/imaging.ps1 | 467 ++++++++++++++++++ WK_64/Scripts/init.ps1 | 158 ++++++ WK_64/Scripts/servers.ps1 | 85 ++++ 19 files changed, 1785 insertions(+), 65 deletions(-) delete mode 100644 System32/startnet.cmd create mode 100644 WK_32/CPU-Z/cpuz.ini rename {WK => WK_32}/ConEmu/ConEmu.xml (100%) rename {WK => WK_32}/Explorer++/config.xml (97%) rename {WK => WK_32}/HWMonitor/hwmonitorw.ini (100%) rename {WK => WK_32}/Notepad2/Notepad2.ini (64%) rename {WK => WK_32}/Scripts/WK.ps1 (82%) rename {WK => WK_32}/Scripts/imaging.ps1 (93%) rename {WK => WK_32}/Scripts/init.ps1 (100%) rename {WK => WK_32}/Scripts/servers.ps1 (100%) create mode 100644 WK_64/CPU-Z/cpuz.ini create mode 100644 WK_64/ConEmu/ConEmu.xml create mode 100644 WK_64/Explorer++/config.xml create mode 100644 WK_64/HWMonitor/hwmonitorw.ini create mode 100644 WK_64/Notepad2/Notepad2.ini create mode 100644 WK_64/Scripts/WK.ps1 create mode 100644 WK_64/Scripts/imaging.ps1 create mode 100644 WK_64/Scripts/init.ps1 create mode 100644 WK_64/Scripts/servers.ps1 diff --git a/System32/startnet.cmd b/System32/startnet.cmd deleted file mode 100644 index 45186f05..00000000 --- a/System32/startnet.cmd +++ /dev/null @@ -1,11 +0,0 @@ -@echo off - -color 0b -echo Initializing... -wpeinit -wpeutil updatebootinfo - -pushd %systemdrive%\WK -set "PATH=%PATH%;%systemdrive%\WK" - -powershell -executionpolicy bypass -file %systemdrive%\WK\Scripts\WK.ps1 diff --git a/WK_32/CPU-Z/cpuz.ini b/WK_32/CPU-Z/cpuz.ini new file mode 100644 index 00000000..fa6114f0 --- /dev/null +++ b/WK_32/CPU-Z/cpuz.ini @@ -0,0 +1,20 @@ +[CPU-Z] +VERSION=1.7.5.0 +TextFontName= +TextFontSize=14 +TextFontColor=000080 +LabelFontName= +LabelFontSize=14 +ACPI=1 +PCI=1 +MaxPCIBus=256 +DMI=1 +Sensor=1 +SMBus=1 +Display=1 +UseDisplayAPI=1 +BusClock=1 +Chipset=1 +SPD=1 +XOC=0 +CheckUpdates=0 diff --git a/WK/ConEmu/ConEmu.xml b/WK_32/ConEmu/ConEmu.xml similarity index 100% rename from WK/ConEmu/ConEmu.xml rename to WK_32/ConEmu/ConEmu.xml diff --git a/WK/Explorer++/config.xml b/WK_32/Explorer++/config.xml similarity index 97% rename from WK/Explorer++/config.xml rename to WK_32/Explorer++/config.xml index 342f0de4..add6848f 100644 --- a/WK/Explorer++/config.xml +++ b/WK_32/Explorer++/config.xml @@ -71,9 +71,9 @@ - + - + diff --git a/WK/HWMonitor/hwmonitorw.ini b/WK_32/HWMonitor/hwmonitorw.ini similarity index 100% rename from WK/HWMonitor/hwmonitorw.ini rename to WK_32/HWMonitor/hwmonitorw.ini diff --git a/WK/Notepad2/Notepad2.ini b/WK_32/Notepad2/Notepad2.ini similarity index 64% rename from WK/Notepad2/Notepad2.ini rename to WK_32/Notepad2/Notepad2.ini index 4522220d..b5c75f87 100644 --- a/WK/Notepad2/Notepad2.ini +++ b/WK_32/Notepad2/Notepad2.ini @@ -1,14 +1,15 @@ -[Settings] +[Notepad2] +[Settings] SaveSettings=1 -SaveRecentFiles=1 -SaveFindReplace=1 +SaveRecentFiles=0 +SaveFindReplace=0 CloseFind=0 CloseReplace=0 NoFindWrap=0 -OpenWithDir=%SystemDrive%\ -Favorites=%SystemDrive%\ -PathNameFormat=1 -WordWrap=0 +OpenWithDir=%SystemDrive%\WK\Tools\.bin\Notepad2 +Favorites=%SystemDrive%\WK\Tools\.bin\Notepad2 +PathNameFormat=2 +WordWrap=1 WordWrapMode=0 WordWrapIndent=0 WordWrapSymbols=22 @@ -21,7 +22,7 @@ AutoCompleteWords=0 ShowIndentGuides=0 TabsAsSpaces=1 TabIndents=1 -BackspaceUnindents=0 +BackspaceUnindents=1 TabWidth=4 IndentWidth=0 MarkLongLines=1 @@ -77,6 +78,9 @@ FindReplaceDlgPosY=0 SingleFileInstance=1 ShellAppUserModelID=Notepad2 ShellUseSystemMRU=1 +[Recent Files] +[Recent Find] +[Recent Replace] [Custom Colors] 01=#000000 02=#0A246A @@ -100,25 +104,3 @@ DefaultScheme=0 AutoSelect=1 SelectDlgSizeX=304 SelectDlgSizeY=324 -[Default Text] -2nd Default Style=font:Lucida Console; size:10; fore:#C0C0C0; back:#000000 -2nd Margins and Line Numbers=font:Tahoma; size:-3; fore:#808080; back:#000000 -2nd Matching Braces=bold; fore:#00FF00 -2nd Matching Braces Error=bold; fore:#FF0000 -2nd Control Characters (Font)=size:-1 -2nd Indentation Guide (Color)=fore:#808080 -2nd Selected Text (Colors)=fore:#008000; back:#404040; alpha:50; eolfilled -2nd Whitespace (Colors, Size 0-5)=fore:#FF0000 -2nd Current Line Background (Color)=back:#808080; alpha:50 -2nd Caret (Color, Size 1-3)=fore:#C0C0C0 -2nd Long Line Marker (Colors)=fore:#404040 -2nd Extra Line Spacing (Size)= -[Recent Files] -01= -02= -[Recent Find] -01= -02= -[Recent Replace] -01= -02= diff --git a/WK/Scripts/WK.ps1 b/WK_32/Scripts/WK.ps1 similarity index 82% rename from WK/Scripts/WK.ps1 rename to WK_32/Scripts/WK.ps1 index f39f397c..bf346b17 100644 --- a/WK/Scripts/WK.ps1 +++ b/WK_32/Scripts/WK.ps1 @@ -26,13 +26,14 @@ function wk-exit { function menu-tools { # Avail tools $tools = @( - @{Name="Blue Screen View"; Folder="BlueScreenView"; File="BlueScreenView64.exe"}, - @{Name="Explorer++"; Folder="Explorer++"; File="Explorer++64.exe"}, - @{Name="Fast Copy"; Folder="FastCopy"; File="FastCopy64.exe"; Args=@('/cmd=noexist_only', '/utf8', '/skip_empty_dir', '/linkdest', '/exclude="desktop.ini;Thumbs.db"')}, - @{Name="HW Monitor"; Folder="HWMonitor"; File="HWMonitor64.exe"}, - @{Name="NT Password Editor"; Folder="NT Password Editor"; File="ntpwedit64.exe"}, - @{Name="Notepad2"; Folder="Notepad2"; File="Notepad2-Mod64.exe"}, + @{Name="Blue Screen View"; Folder="BlueScreenView"; File="BlueScreenView.exe"}, + @{Name="Explorer++"; Folder="Explorer++"; File="Explorer++.exe"}, + @{Name="Fast Copy"; Folder="FastCopy"; File="FastCopy.exe"; Args=@('/cmd=noexist_only', '/utf8', '/skip_empty_dir', '/linkdest', '/exclude="desktop.ini;Thumbs.db"')}, + @{Name="HW Monitor"; Folder="HWMonitor"; File="HWMonitor.exe"}, + @{Name="NT Password Editor"; Folder="NT Password Editor"; File="ntpwedit.exe"}, + @{Name="Notepad2"; Folder="Notepad2"; File="Notepad2-Mod.exe"}, @{Name="Prime95"; Folder="Prime95"; File="prime95.exe"}, + @{Name="ProduKey"; Folder="ProduKey"; File="ProduKey.exe"}, @{Name="PhotoRec (GUI)"; Folder="TestDisk"; File="qphotorec_win.exe"}, @{Name="PhotoRec (CLI)"; Folder="TestDisk"; File="photorec_win.exe"}, @{Name="TestDisk (CLI)"; Folder="TestDisk"; File="testdisk_win.exe"} @@ -101,6 +102,14 @@ function menu-main { } } +# Mount all partitions +foreach ($_d in @(Get-Disk)) { + foreach ($_p in @(Get-Partition -DiskNumber $_d.DiskNumber)) { + # Assign letter + Add-PartitionAccessPath -DiskNumber $_d.DiskNumber -PartitionNumber $_p.PartitionNumber -AssignDriveLetter 2>&1 | Out-Null + } +} + # Main Loop do { menu-main diff --git a/WK/Scripts/imaging.ps1 b/WK_32/Scripts/imaging.ps1 similarity index 93% rename from WK/Scripts/imaging.ps1 rename to WK_32/Scripts/imaging.ps1 index a1033dc5..38b48b4c 100644 --- a/WK/Scripts/imaging.ps1 +++ b/WK_32/Scripts/imaging.ps1 @@ -13,14 +13,16 @@ function apply-image { $split_image = $false $split_image_pattern = "" - # Check for local source + # Check for source image + ## This checks all drive letters for the source image. + ## It starts with local sources and then tries the server(s) (usually Y: and Z:) $volumes = @(Get-Volume | Where-Object {$_.Size -ne 0 -and $_.DriveLetter -imatch '^[C-Z]$'}) foreach ($v in $volumes) { $letter = $v.DriveLetter + ":" if (Test-Path "$letter\sources\$image.wim") { $path = "$letter\sources\$image.wim" } elseif (Test-Path "$letter\sources\$image.esd") { - $path = "$letter\sources\$image.wim" + $path = "$letter\sources\$image.esd" } elseif (Test-Path "$letter\sources\$image.swm") { $path = "$letter\sources\$image.swm" $split_image = $true @@ -28,7 +30,7 @@ function apply-image { } } - # Check for remote source (if necessary) + # Check for FQDN remote source (if necessary) if ($path -imatch '^$') { # Temporarily set path to network source $path = "\\$source_server\Windows\$image" @@ -36,7 +38,7 @@ function apply-image { if (Test-Path "$path.wim") { $path = "$path.wim" } elseif (Test-Path "$path.esd") { - $path = "$path.swm" + $path = "$path.esd" } elseif (Test-Path "$path.swm") { $path = "$path.swm" $split_image = $true @@ -177,6 +179,10 @@ function select-disk { function menu-imaging { wk-write "Drive Imaging" wk-write "" + + # Pre-emptively mount Server(s) + ## Helps ensure a successfull backup and/or setup + mount-servers ## WARNING wk-warn "WARNING: This section is experimental" @@ -256,9 +262,6 @@ function menu-imaging { } wk-write "" - # Mount server(s) - mount-servers - # Select Server $server = (select-server) if (!($server)) { @@ -310,12 +313,12 @@ function menu-imaging { mkdir "$_imagepath" | out-null } $_dism_args = @( - '/Capture-Image', - '/ImageFile:$_imagefile', - '/CaptureDir:$_capturedir', - '/Name:$_name', - '/Compress:fast', - '/Quiet') + "/Capture-Image", + "/ImageFile:$_imagefile", + "/CaptureDir:$_capturedir", + "/Name:$_name", + "/Compress:fast", + "/Quiet") Start-Process "$windir\System32\Dism.exe" -ArgumentList $_dism_args -NoNewWindow -Wait | out-null ## The following command fails to capture OS partitions consitantly. Until this is fixed I will use DISM directly (as above). @@ -341,12 +344,13 @@ function menu-imaging { } } } - - # Unmount server(s) - unmount-servers pause "Press Enter to return to main menu... " } function menu-setup { + # Pre-emptively mount Server(s) + ## Helps ensure a successfull backup and/or setup + mount-servers + # Select Disk $dest_disk = (select-disk "To which drive are we installing Windows?" -skip_usb=$true) diff --git a/WK/Scripts/init.ps1 b/WK_32/Scripts/init.ps1 similarity index 100% rename from WK/Scripts/init.ps1 rename to WK_32/Scripts/init.ps1 diff --git a/WK/Scripts/servers.ps1 b/WK_32/Scripts/servers.ps1 similarity index 100% rename from WK/Scripts/servers.ps1 rename to WK_32/Scripts/servers.ps1 diff --git a/WK_64/CPU-Z/cpuz.ini b/WK_64/CPU-Z/cpuz.ini new file mode 100644 index 00000000..fa6114f0 --- /dev/null +++ b/WK_64/CPU-Z/cpuz.ini @@ -0,0 +1,20 @@ +[CPU-Z] +VERSION=1.7.5.0 +TextFontName= +TextFontSize=14 +TextFontColor=000080 +LabelFontName= +LabelFontSize=14 +ACPI=1 +PCI=1 +MaxPCIBus=256 +DMI=1 +Sensor=1 +SMBus=1 +Display=1 +UseDisplayAPI=1 +BusClock=1 +Chipset=1 +SPD=1 +XOC=0 +CheckUpdates=0 diff --git a/WK_64/ConEmu/ConEmu.xml b/WK_64/ConEmu/ConEmu.xml new file mode 100644 index 00000000..26a3611c --- /dev/null +++ b/WK_64/ConEmu/ConEmu.xml @@ -0,0 +1,643 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WK_64/Explorer++/config.xml b/WK_64/Explorer++/config.xml new file mode 100644 index 00000000..add6848f --- /dev/null +++ b/WK_64/Explorer++/config.xml @@ -0,0 +1,113 @@ + + + + + yes + no + yes + yes + no + yes + no + no + + + + + 90 + yes + no + no + no + no + no + no + 0 + yes + 9 + no + 0 + yes + no + ::{20D04FE0-3AEA-1069-A2D8-08002B30309D} + no + 500 + yes + yes + 1 + yes + no + no + no + yes + yes + yes + yes + no + yes + no + yes + yes + yes + no + yes + yes + no + yes + yes + yes + 1 + yes + 1 + yes + no + no + + no + 208 + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/WK_64/HWMonitor/hwmonitorw.ini b/WK_64/HWMonitor/hwmonitorw.ini new file mode 100644 index 00000000..e3978b4e --- /dev/null +++ b/WK_64/HWMonitor/hwmonitorw.ini @@ -0,0 +1,8 @@ +[HWMonitor] +VERSION=1.2.8.0 +USE_ACPI=1 +USE_SMBUS=1 +USE_SMART=1 +USE_DISPLAY=1 +CPU_0_TJMAX=100.0 +UPDATES=0 diff --git a/WK_64/Notepad2/Notepad2.ini b/WK_64/Notepad2/Notepad2.ini new file mode 100644 index 00000000..b5c75f87 --- /dev/null +++ b/WK_64/Notepad2/Notepad2.ini @@ -0,0 +1,106 @@ +[Notepad2] +[Settings] +SaveSettings=1 +SaveRecentFiles=0 +SaveFindReplace=0 +CloseFind=0 +CloseReplace=0 +NoFindWrap=0 +OpenWithDir=%SystemDrive%\WK\Tools\.bin\Notepad2 +Favorites=%SystemDrive%\WK\Tools\.bin\Notepad2 +PathNameFormat=2 +WordWrap=1 +WordWrapMode=0 +WordWrapIndent=0 +WordWrapSymbols=22 +ShowWordWrapSymbols=0 +MatchBraces=1 +AutoCloseTags=0 +HighlightCurrentLine=1 +AutoIndent=1 +AutoCompleteWords=0 +ShowIndentGuides=0 +TabsAsSpaces=1 +TabIndents=1 +BackspaceUnindents=1 +TabWidth=4 +IndentWidth=0 +MarkLongLines=1 +LongLinesLimit=80 +LongLineMode=1 +ShowSelectionMargin=0 +ShowLineNumbers=1 +ShowCodeFolding=1 +MarkOccurrences=2 +MarkOccurrencesMatchCase=0 +MarkOccurrencesMatchWholeWords=0 +ViewWhiteSpace=0 +ViewEOLs=0 +DefaultEncoding=3 +SkipUnicodeDetection=0 +LoadASCIIasUTF8=0 +LoadNFOasOEM=1 +NoEncodingTags=0 +DefaultEOLMode=0 +FixLineEndings=0 +FixTrailingBlanks=0 +PrintHeader=1 +PrintFooter=0 +PrintColorMode=3 +PrintZoom=10 +PrintMarginLeft=1000 +PrintMarginTop=1000 +PrintMarginRight=1000 +PrintMarginBottom=1000 +SaveBeforeRunningTools=1 +FileWatchingMode=1 +ResetFileWatching=0 +EscFunction=2 +AlwaysOnTop=0 +MinimizeToTray=0 +TransparentMode=0 +ToolbarButtons=1 2 4 0 5 6 0 7 8 9 0 10 11 0 12 0 24 0 13 14 0 15 0 17 +ShowToolbar=1 +ShowStatusbar=1 +EncodingDlgSizeX=256 +EncodingDlgSizeY=262 +RecodeDlgSizeX=256 +RecodeDlgSizeY=262 +FileMRUDlgSizeX=412 +FileMRUDlgSizeY=376 +OpenWithDlgSizeX=384 +OpenWithDlgSizeY=386 +FavoritesDlgSizeX=334 +FavoritesDlgSizeY=316 +FindReplaceDlgPosX=0 +FindReplaceDlgPosY=0 +[Settings2] +SingleFileInstance=1 +ShellAppUserModelID=Notepad2 +ShellUseSystemMRU=1 +[Recent Files] +[Recent Find] +[Recent Replace] +[Custom Colors] +01=#000000 +02=#0A246A +03=#3A6EA5 +04=#003CE6 +05=#006633 +06=#608020 +07=#648000 +08=#A46000 +09=#FFFFFF +10=#FFFFE2 +11=#FFF1A8 +12=#FFC000 +13=#FF4000 +14=#C80000 +15=#B000B0 +16=#B28B40 +[Styles] +Use2ndDefaultStyle=0 +DefaultScheme=0 +AutoSelect=1 +SelectDlgSizeX=304 +SelectDlgSizeY=324 diff --git a/WK_64/Scripts/WK.ps1 b/WK_64/Scripts/WK.ps1 new file mode 100644 index 00000000..bf346b17 --- /dev/null +++ b/WK_64/Scripts/WK.ps1 @@ -0,0 +1,116 @@ +# WK-Checklist + +## Init ## +$wd = $(Split-Path $MyInvocation.MyCommand.Path) +pushd "$wd" +. .\init.ps1 +. .\servers.ps1 +. .\imaging.ps1 +clear +$host.UI.RawUI.WindowTitle = "WK PE Tool" +$logpath = "$WKPath\Info\$date" +md "$logpath" 2>&1 | Out-Null +$log = "$logpath\winpe.log" + +# Functions +function wk-exit { + param([string]$action) + switch ($action) { + 'Q' {PowerShell -ExecutionPolicy Bypass; break} + 'R' {wpeutil reboot; break} + 'S' {wpeutil shutdown; break} + default {throw} + } + exit 0 +} +function menu-tools { + # Avail tools + $tools = @( + @{Name="Blue Screen View"; Folder="BlueScreenView"; File="BlueScreenView.exe"}, + @{Name="Explorer++"; Folder="Explorer++"; File="Explorer++.exe"}, + @{Name="Fast Copy"; Folder="FastCopy"; File="FastCopy.exe"; Args=@('/cmd=noexist_only', '/utf8', '/skip_empty_dir', '/linkdest', '/exclude="desktop.ini;Thumbs.db"')}, + @{Name="HW Monitor"; Folder="HWMonitor"; File="HWMonitor.exe"}, + @{Name="NT Password Editor"; Folder="NT Password Editor"; File="ntpwedit.exe"}, + @{Name="Notepad2"; Folder="Notepad2"; File="Notepad2-Mod.exe"}, + @{Name="Prime95"; Folder="Prime95"; File="prime95.exe"}, + @{Name="ProduKey"; Folder="ProduKey"; File="ProduKey.exe"}, + @{Name="PhotoRec (GUI)"; Folder="TestDisk"; File="qphotorec_win.exe"}, + @{Name="PhotoRec (CLI)"; Folder="TestDisk"; File="photorec_win.exe"}, + @{Name="TestDisk (CLI)"; Folder="TestDisk"; File="testdisk_win.exe"} + ) + + # Build menu + $selection = $null + $actions = @(@{Name="Main Menu"; Letter="M"}) + + # Run Loop + $_done = $false + do { + $selection = (menu-select "Tools Menu" $tools $actions) + + if ($selection -imatch '^M$') { + # User selected to return to the menu + return $false + } elseif ($selection -inotmatch '^\d+$') { + # This shouldn't happen? + throw + } else { + $selection -= 1 + $path = "{0}\{1}" -f $WKPath, $tools[$selection].Folder + if ($tools[$selection].ContainsKey("Args")) { + Start-Process $tools[$selection].File -ArgumentList $tools[$selection].Args -WorkingDirectory $path + } else { + Start-Process $tools[$selection].File -WorkingDirectory $path + } + } + } until ($_done) +} +function menu-main { + # Build menu + $selection = $null + $menus = @( + @{Name="Drive Imaging"; Menu="menu-imaging"} + @{Name="Windows Setup"; Menu="menu-setup"} + @{Name="Misc Tools"; Menu="menu-tools"} + ) + $actions = @( + @{Name="Command Prompt"; Letter="C"} + @{Name="PowerShell"; Letter="P"} + @{Name="Reboot"; Letter="R"} + @{Name="Shutdown"; Letter="S"} + ) + + # Show Menu + $selection = (menu-select "Main Menu" $menus $actions -SecretExit $true) + + if ($selection -imatch '^C$') { + Start-Process "$windir\System32\cmd.exe" -argumentlist @("-new_console:n") -WorkingDirectory "$WKPath" + return + } elseif ($selection -imatch '^P$') { + Start-Process "$windir\System32\WindowsPowerShell\v1.0\powershell.exe" -argumentlist @("-ExecutionPolicy", "Bypass", "-new_console:n") -WorkingDirectory "$WKPath" + return + } elseif ($selection -imatch '^[QRS]$') { + wk-exit $selection + return + } elseif ($selection -inotmatch '^\d+$') { + # This shouldn't happen? + throw + } else { + # Launch sub-menu + $selection -= 1 + & $menus[$selection].Menu + } +} + +# Mount all partitions +foreach ($_d in @(Get-Disk)) { + foreach ($_p in @(Get-Partition -DiskNumber $_d.DiskNumber)) { + # Assign letter + Add-PartitionAccessPath -DiskNumber $_d.DiskNumber -PartitionNumber $_p.PartitionNumber -AssignDriveLetter 2>&1 | Out-Null + } +} + +# Main Loop +do { + menu-main +} while ($true) diff --git a/WK_64/Scripts/imaging.ps1 b/WK_64/Scripts/imaging.ps1 new file mode 100644 index 00000000..38b48b4c --- /dev/null +++ b/WK_64/Scripts/imaging.ps1 @@ -0,0 +1,467 @@ +# WK imaging functions + +## Init ## +$wd = $(Split-Path $MyInvocation.MyCommand.Path) +pushd "$wd" +. .\init.ps1 + +# Functions +function apply-image { + # Apply a Windows image to W:\ + Param([string]$image, [string]$name) + $path = "" + $split_image = $false + $split_image_pattern = "" + + # Check for source image + ## This checks all drive letters for the source image. + ## It starts with local sources and then tries the server(s) (usually Y: and Z:) + $volumes = @(Get-Volume | Where-Object {$_.Size -ne 0 -and $_.DriveLetter -imatch '^[C-Z]$'}) + foreach ($v in $volumes) { + $letter = $v.DriveLetter + ":" + if (Test-Path "$letter\sources\$image.wim") { + $path = "$letter\sources\$image.wim" + } elseif (Test-Path "$letter\sources\$image.esd") { + $path = "$letter\sources\$image.esd" + } elseif (Test-Path "$letter\sources\$image.swm") { + $path = "$letter\sources\$image.swm" + $split_image = $true + $split_image_pattern = "$letter\sources\$image*.swm" + } + } + + # Check for FQDN remote source (if necessary) + if ($path -imatch '^$') { + # Temporarily set path to network source + $path = "\\$source_server\Windows\$image" + wk-warn "Searching for network source" + if (Test-Path "$path.wim") { + $path = "$path.wim" + } elseif (Test-Path "$path.esd") { + $path = "$path.esd" + } elseif (Test-Path "$path.swm") { + $path = "$path.swm" + $split_image = $true + $split_image_pattern = "$path*.swm" + } else { + # Revert to empty path if nothing found. + $path = "" + } + } + + # Expand Image + if ($path -imatch 'Win\d+\.(esd|wim)$') { + wk-write " Applying image..." + Expand-WindowsImage -ImagePath "$path" -Name "$name" -ApplyPath 'W:\' | out-null + } elseif ($path -imatch 'Win\d+\.swm$') { + wk-write " Applying split-image..." + Expand-WindowsImage -ImagePath "$path" -Name "$name" -ApplyPath 'W:\' -SplitImageFilePattern "$split_image_pattern" | out-null + } else { + wk-error "Image not found." + throw + } +} +function format-gpt { + Param($dest_disk) + wk-write "Drive will use a GPT (UEFI) layout." + + # Double-check we have the right drive + ## I don't trust the order will be the same for diskpart & PS Storage Cmdlets + $_sel_uid = $dest_disk.Guid + if ($dest_disk.PartitionStyle -imatch "MBR") { + # MBR disks don't have GUIDs and use the signature in hex instead + $_sel_uid = "{0:x}" -f $dest_disk.Signature + } + $diskpart_script = "select disk {0}`r`n" -f $dest_disk.DiskNumber + $diskpart_script += "uniqueid disk" + Out-File -encoding 'UTF8' -filepath "$wd\diskpart.script" -inputobject $diskpart_script + Start-Process "diskpart" -argumentlist @("/s", "$wd\diskpart.script") -wait -nonewwindow -PassThru -RedirectStandardOutput "$wd\drive_uid" | Out-Null + if (!(Get-Content "$wd\drive_uid" | Where-Object {$_ -imatch $_sel_uid})) { + # GUIDs do not match + wk-error "Diskpart failed to select the same disk for formatting, aborting setup." + wk-warn "This system requires manual formatting & setup" + wk-write "" + throw "Failed to format disk" + } else { + wk-write ("Selecting Disk {0} ({1})" -f $dest_disk.DiskNumber, $_sel_uid) + } + + # Generate Diskpart script and execute + ## NOTE 1: PS Storage Cmdlets can't be used; See Keith Garner's response here: + ## https://social.technet.microsoft.com/Forums/en-US/9d78da31-557f-4408-89e0-a1603f7ebe0d + ## + ## NOTE 2: This overwrites existing diskpart.script file without confirmation. + $diskpart_script = "select disk {0}`r`n" -f $dest_disk.DiskNumber + $diskpart_script += "clean`r`n" + $diskpart_script += "convert gpt`r`n" + + # 1. Windows RE tools partition (Windows 8+) + if ($dest_windows_version.Name -imatch '^Windows (8|10)') { + $diskpart_script += "create partition primary size=300`r`n" + $diskpart_script += "format quick fs=ntfs label='Windows RE tools'`r`n" + $diskpart_script += "assign letter='T'`r`n" + $diskpart_script += "set id='de94bba4-06d1-4d40-a16a-bfd50179d6ac'`r`n" + $diskpart_script += "gpt attributes=0x8000000000000001`r`n" + } + + # 2. System partition + $diskpart_script += "create partition efi size=260`r`n" + ## NOTE: Allows for Advanced Format 4Kn drives + $diskpart_script += "format quick fs=fat32 label='System'`r`n" + $diskpart_script += "assign letter='S'`r`n" + + # 3. Microsoft Reserved (MSR) partition + $diskpart_script += "create partition msr size=128`r`n" + + # 4. Windows partition + $diskpart_script += "create partition primary`r`n" + $diskpart_script += "format quick fs=ntfs label='Windows'`r`n" + $diskpart_script += "assign letter='W'`r`n" + + # Run script + Out-File -encoding 'UTF8' -filepath "$wd\diskpart.script" -inputobject $diskpart_script + Start-Process "diskpart" -argumentlist @("/s", "$wd\diskpart.script") -wait -nonewwindow | out-null +} +function format-mbr { + Param($dest_disk) + wk-write "Drive will use a MBR (legacy) layout." + + if ($dest_disk.PartitionStyle -inotmatch '^RAW$') { + # Only clean if necessary + clear-Disk $dest_disk.DiskNumber -RemoveData -RemoveOEM -Confirm:$false | out-null + } + Initialize-Disk $dest_disk.DiskNumber -PartitionStyle 'MBR' | out-null + New-Partition -DiskNumber $dest_disk.DiskNumber -Size 100Mb -DriveLetter 'S' -IsActive:$true | out-null + New-Partition -DiskNumber $dest_disk.DiskNumber -UseMaximumSize -DriveLetter 'W' -IsActive:$false | out-null + Format-Volume -DriveLetter 'S' -FileSystem 'NTFS' -NewFileSystemLabel 'System Reserved' | out-null + Format-Volume -DriveLetter 'W' -FileSystem 'NTFS' -NewFileSystemLabel 'Windows' | out-null +} +function select-disk { + param([string]$title, [bool]$skip_usb=$false) + $_skipped_parts = 0 + + # Get Disk(s) + if ($skip_usb) { + $disks = @(Get-Disk | Where-Object {$_.Size -ne 0 -and $_.BusType -inotmatch 'USB'} | Sort-Object -Property "Number") + } else { + $disks = @(Get-Disk | Where-Object {$_.Size -ne 0} | Sort-Object -Property "Number") + } + + # Check if any drives were detected + if ($disks.count -eq 0) { + wk-error "No suitable drives were detected." + return $false + } + + # Get selection + $selection = $null + $main_set = @() + if ($disks.count -eq 1) { + # Only one disk is available + $selection = $disks[0] + } else { + # Multiple options. Build and use menu + foreach ($_ in $disks) { + $_entry = "{0}`t[{1}] ({2}) {3}" -f (human-size $_.Size 0), $_.PartitionStyle, $_.BusType, $_.FriendlyName + $main_set += @{Name=$_entry} + } + $actions = @(@{Name="Main Menu"; Letter="M"}) + $selection = (menu-select $title $main_set $actions) + } + + if ($selection -imatch '^\d+$') { + $selection -= 1 + return $disks[$selection] + } else { + return $selection + } +} +function menu-imaging { + wk-write "Drive Imaging" + wk-write "" + + # Pre-emptively mount Server(s) + ## Helps ensure a successfull backup and/or setup + mount-servers + + ## WARNING + wk-warn "WARNING: This section is experimental" + pause + ## WARNING + + # Service Order + $menu_service_order += "Please enter the service order`r`n" + do { + clear + $service_order = read-host -prompt $menu_service_order + } until ($service_order -imatch '^\d[\w\-]+$') + + # Select Disk + $disk = (select-disk "For which drive are we creating backup image(s)?") + + if (!($disk)) { + # No drives detected or user aborted + wk-warn "Drive Imaging aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } elseif ($disk -imatch '^M$') { + # User selected to return to the menu + return $false + } elseif ($disk.DiskNumber -imatch '^\d+$') { + # Valid disk selected + clear + wk-write ("Disk:`t{0}`t[{1}] ({2}) {3}" -f (human-size $disk.Size 0), $disk.PartitionStyle, $disk.BusType, $disk.FriendlyName) + wk-write "Partition(s):" + + # Print partition info + $partitions = Get-Partition -DiskNumber $disk.DiskNumber + $_skipped_parts = 0 + foreach ($_p in $partitions) { + # Assign letter + Add-PartitionAccessPath -DiskNumber $disk.DiskNumber -PartitionNumber $_p.PartitionNumber -AssignDriveLetter 2>&1 | Out-Null + + # Update partition info + $_p = Get-Partition -DiskNumber $disk.DiskNumber -PartitionNumber $_p.PartitionNumber + $_v = Get-Volume -Partition $_p + + # Set size label + $_size = (human-size $_p.size 0) + $_used = "" + if ($_v) { + $_used = "({0} used)" -f (human-size ($_v.Size - $_v.SizeRemaining) 0) + } + + # Print partition info + if ($_p.AccessPaths) { + # Has drive letter + $_path = $_p.AccessPaths | Where-Object {$_ -imatch '^\w:\\$'} + $_label = " {0}" -f $_p.Type + if ($_v -and $_v.FileSystemLabel -ne "") { + $_label = '"{0}"' -f $_v.FileSystemLabel + } + $_msg = " {0:N0}:`t{1} ({2,6}) {3} {4}" -f $_p.PartitionNumber, $_path, $_size, $_label, $_used + wk-write "$_msg" + } else { + # No drive letter + $_msg = " *{0:N0}:`t ({1}) {2}" -f $_p.PartitionNumber, $_size, $_p.Type + wk-error "$_msg" + $_skipped_parts += 1 + } + } + if ($_skipped_parts -gt 0) { + wk-warn " *`tUnable to backup these partition(s)" + } + wk-write "" + if (!(ask " Backup these partition(s)?")) { + wk-warn "Drive Imaging aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } + } + wk-write "" + + # Select Server + $server = (select-server) + if (!($server)) { + # No servers detected + wk-warn "Drive Imaging aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } elseif ($server -imatch '^M$') { + # User selected to return to the menu + return + } + wk-write "" + wk-write ("Saving partition backups to: {0}" -f $server.Description) + wk-write "" + + # Backup partitions + $partitions = Get-Partition -DiskNumber $disk.DiskNumber + foreach ($_p in $partitions) { + $_v = Get-Volume -Partition $_p + + $_name = "{0}" -f $_p.PartitionNumber + if ($_v -and $_v.FileSystemLabel -ne "") { + $_name += "_{0}" -f $_v.FileSystemLabel + } else { + $_name += "_{0}" -f $_p.Type + } + # Sanitize the name + $_name = $_name -replace '\s', '_' + + $_imagepath = "{0}{1}" -f $server.Root, $service_order + $_imagefile = "{0}{1}\{2}.wim" -f $server.Root, $service_order, $_name + + if ($_p.AccessPaths -ne $null) { + # Avoid unwanted clobbering + if (Test-Path "$_imagefile") { + if (!(ask ("Overwrite backup image: {0}" -f $_imagefile))) { + wk-warn "Drive Imaging aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } + } + $_capturedir = $_p.AccessPaths | Where-Object {$_ -imatch '^\w:\\$'} + + # Take image + wk-write (" Imaging partition {0} --> `"{1}`"" -f $_p.PartitionNumber, $_imagefile) + if (!(Test-Path "$_imagepath")) { + mkdir "$_imagepath" | out-null + } + $_dism_args = @( + "/Capture-Image", + "/ImageFile:$_imagefile", + "/CaptureDir:$_capturedir", + "/Name:$_name", + "/Compress:fast", + "/Quiet") + Start-Process "$windir\System32\Dism.exe" -ArgumentList $_dism_args -NoNewWindow -Wait | out-null + + ## The following command fails to capture OS partitions consitantly. Until this is fixed I will use DISM directly (as above). + #New-WindowsImage -ImagePath "$_imagefile" -CapturePath "$_capturedir" -Name "$_name" -CompressionType "fast" | out-null + + # Verify image + ## Code borrowed from: https://stackoverflow/a/10262275 + $pinfo = New-Object System.Diagnostics.ProcessStartInfo + $pinfo.FileName = "$WKPath\7-Zip\7z.exe" + $pinfo.RedirectStandardError = $true + $pinfo.RedirectStandardOutput = $true + $pinfo.UseShellExecute = $false + $pinfo.Arguments = 't "{0}"' -f $_imagefile + $p = New-Object System.Diagnostics.Process + $p.StartInfo = $pinfo + $p.Start() | Out-Null + write-host " Verifying . . . " -NoNewline + $p.WaitForExit() + if ($p.ExitCode -eq 0) { + write-host "Complete." -foreground "green" + } else { + write-host "Failed." -foreground "red" + } + } + } + pause "Press Enter to return to main menu... " +} +function menu-setup { + # Pre-emptively mount Server(s) + ## Helps ensure a successfull backup and/or setup + mount-servers + + # Select Disk + $dest_disk = (select-disk "To which drive are we installing Windows?" -skip_usb=$true) + + if (!($dest_disk)) { + # No drives detected or user aborted + wk-warn "Windows Setup aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } elseif ($dest_disk -imatch '^M$') { + # User selected to return to the menu + return $false + } elseif ($dest_disk.DiskNumber -inotmatch '^\d+$') { + # This shouldn't happen? + throw + } else { + wk-warn "All data will be deleted from the following drive:" + wk-warn ("`t{0}`t({1}) {2}`r`n" -f (human-size $dest_disk.Size 0), $dest_disk.PartitionStyle, $dest_disk.FriendlyName) + if (!(ask "Proceed and install Windows?")) { + wk-warn "Windows Setup aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } + } + + # Set available Windows versions + $windows_versions = @( + @{Name="Windows 7 Home Basic"; ImageFile="Win7"; ImageName="Windows 7 HOMEBASIC"} + @{Name="Windows 7 Home Premium"; ImageFile="Win7"; ImageName="Windows 7 HOMEPREMIUM"} + @{Name="Windows 7 Professional"; ImageFile="Win7"; ImageName="Windows 7 PROFESSIONAL"} + @{Name="Windows 7 Ultimate"; ImageFile="Win7"; ImageName="Windows 7 ULTIMATE"} + + @{Name="Windows 8.1"; ImageFile="Win8"; ImageName="Windows 8.1"; CRLF=$true} + @{Name="Windows 8.1 Pro"; ImageFile="Win8"; ImageName="Windows 8.1 Pro"} + + # The ISOs from the MediaCreationTool are apparently Technical Previews + @{Name="Windows 10 Home"; ImageFile="Win10"; ImageName="Windows 10 Technical Preview"; CRLF=$true} + @{Name="Windows 10 Pro"; ImageFile="Win10"; ImageName="Windows 10 Pro Technical Preview"} + ) + + # Build menu and get selection + $dest_windows_version = $null + $selection = $null + $actions = @(@{Name="Main Menu"; Letter="M"}) + $selection = (menu-select "Which version of Windows are we installing?" $windows_versions $actions) + + if ($selection -imatch '^M$') { + # User selected to return to the menu + return $false + } elseif ($selection -inotmatch '^\d+$') { + # This shouldn't happen? + throw + } else { + $selection -= 1 + $dest_windows_version = $windows_versions[$selection] + } + + # Double check before deleting data + wk-warn "SAFTEY CHECK:" + wk-write (" Installing:`t{0}" -f $dest_windows_version.Name) + wk-error (" And ERASING:`tDisk: {0}`t({1}) {2}`r`n" -f (human-size $dest_disk.Size 0), $dest_disk.PartitionStyle, $dest_disk.FriendlyName) + if (!(ask "Is this correct?")) { + wk-warn "Windows Setup aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } + + ## WARNING + wk-warn "WARNING: This section is experimental" + ## WARNING + + ## Here be dragons + try { + # Select UEFI or BIOS partition layout + if ($UEFI) { + # System booted via UEFI so assume new layout should be GPT + if (ask "Setup drive using GPT (UEFI) layout?") { + format-gpt $dest_disk + } else { + format-mbr $dest_disk + } + } else{ + if (ask "Setup drive using MBR (legacy) layout?") { + format-mbr $dest_disk + } else { + format-gpt $dest_disk + } + } + + # Apply image + apply-image $dest_windows_version.ImageFile $dest_windows_version.ImageName + + # Create boot files (copies files for both Legacy and UEFI) + wk-write " Copying boot files..." + bcdboot W:\Windows /s S: /f ALL 2>&1 | out-null + if ($dest_windows_version.Name -imatch '^Windows (8|10)') { + W:\Windows\System32\reagentc /setreimage /path T:\Recovery\WindowsRE /target W:\Windows 2>&1 | out-null + } + + # Done + wk-write "Windows Setup complete." + wk-write "" + pause "Press Enter to return to main menu... " + } catch { + # Error(s) + wk-error "$Error" + wk-error "Windows Setup aborted." + wk-write "" + pause "Press Enter to return to main menu... " -warning=$true + return $false + } +} diff --git a/WK_64/Scripts/init.ps1 b/WK_64/Scripts/init.ps1 new file mode 100644 index 00000000..b198fdd8 --- /dev/null +++ b/WK_64/Scripts/init.ps1 @@ -0,0 +1,158 @@ +# WK-Init +# +# Some common settings and functions + +$host.UI.RawUI.BackgroundColor = "black" +$host.UI.RawUI.ForegroundColor = "cyan" +#$appdata = (gci env:appdata).value +#$localappdata = (gci env:localappdata).value +#$username = (gci env:username).value +#$userprofile = (gci env:userprofile).value +$systemdrive = (gci env:systemdrive).value +$windir = (gci env:windir).value +#$programfiles = (gci env:programfiles).value +#$programfiles86 = $programfiles +#if (test-path env:"programfiles(x86)") { +# $programfiles86 = (gci env:"programfiles(x86)").value +#} +$WKPath = "$systemdrive\WK" +$date = get-date -uformat "%Y-%m-%d" +#$logpath = "$WKPath\Info\$date" + +# Check if booted via UEFI +$UEFI = $false +if ((Get-ItemProperty -path "HKLM:\System\CurrentControlSet\Control").PEFirmwareType -eq 2) { + $UEFI = $true +} + +function ask { + param([string]$text = "Kotaero", [string]$log = "WK.log") + $answered = $false + $text += " [Y/N]" + while (!$answered) { + $answer = read-host $text + if ($answer -imatch '^(y|yes)$') { + $answer = $true + $answered = $true + } elseif ($answer -imatch '^(n|no)$') { + $answer = $false + $answered = $true + } + } + $text += ": $answer" + out-file -filepath $log -inputobject $text -append + return $answer +} +function wk-error { + param([string]$text = "ERROR", [string]$log = "WK.log") + write-host ($text) -foreground "red" + out-file -filepath $log -inputobject $text -append +} +function wk-warn { + param([string]$text = "WARNING", [string]$log = "WK.log") + write-host ($text) -foreground "yellow" + out-file -filepath $log -inputobject $text -append +} +function wk-write { + param([string]$text = "", [string]$log = "WK.log") + write-host ($text) + out-file -filepath $log -inputobject $text -append +} +function human-size { + param($bytes, [int]$decimals = 2) + if ($bytes -gt 1Tb) { + $size = "{0:N$decimals} Tb" -f ($bytes / 1Tb) + } elseif ($bytes -gt 1Gb) { + $size = "{0:N$decimals} Gb" -f ($bytes / 1Gb) + } elseif ($bytes -gt 1Mb) { + $size = "{0:N$decimals} Mb" -f ($bytes / 1Mb) + } elseif ($bytes -gt 1Kb) { + $size = "{0:N$decimals} Kb" -f ($bytes / 1Kb) + } else { + $size = "{0:N$decimals} b" -f $bytes + } + return $size +} +function menu-select { + ## $MainEntries should be an "AoH" object (with at least the key "Name" for each item) + ## NOTE: if the CRLF=$true; then a spacer is added before that entry. + ## Example: + ## $MainEntries = @( + ## @{Name="Windows 10 Home"; ImageFile="Win10"; ImageName="Windows 10 Home"} + ## @{Name="Windows 10 Pro"; ImageFile="Win10"; ImageName="Windows 10 Pro"} + ##) + + ## $ActionEntries should be an "AoH" object (with at least the keys "Name" and "Letter" for each item) + ## NOTE: if the CRLF=$true; then a spacer is added before that entry. + ## Example: + ## $ActionEntries = @( + ## @{Name="Reboot"; Letter="R"} + ## @{Name="Shutdown"; Letter="S"} + ##) + + param( + [string]$Title = "## Untitled Menu ##", + $MainEntries = @(), + $ActionEntries = @(), + [string]$Prompt = "Please make a selection", + [bool]$SecretExit = $false + ) + + # Bail early if no items given + if ($MainEntries.length -eq 0 -and $ActionEntries.length -eq 0) { + throw "MenuError: No items given." + } + + # Build menu + $menu_splash = "{0}`r`n`r`n" -f $title + $valid_answers = @() + if ($SecretExit) { + $valid_answers += "Q" + } + + # Add main items to splash + if ($MainEntries.length -gt 0) { + for ($i=0; $i -lt $MainEntries.length; $i++) { + if ($MainEntries[$i].CRLF) { + # Add spacer + $menu_splash += "`r`n" + } + $valid_answers += ($i + 1) + $menu_splash += "{0,2:N0}: {1}`r`n" -f ($i + 1), $MainEntries[$i].Name + } + $menu_splash += "`r`n" + } + + # Add action items to splash + if ($ActionEntries.length -gt 0) { + foreach ($_item in $ActionEntries) { + if ($_item.CRLF) { + # Add spacer + $menu_splash += "`r`n" + } + $menu_splash += " {0}: {1}`r`n" -f $_item.Letter.ToUpper(), $_item.Name + $valid_answers += $_item.Letter.ToLower(), $_item.Letter.ToUpper() + } + $menu_splash += "`r`n" + } + + # Add prompt to splash + $menu_splash += "{0}`r`n" -f $prompt + + # Select Windows version + do { + clear + $answer = read-host -prompt $menu_splash + } until ($valid_answers -contains $answer) + + return $answer.ToUpper() +} +function pause { + param([string]$message = "Press Enter to continue... ", [bool]$warning = $False) + if ($warning) { + write-host ($message) -foreground "yellow" + } else { + write-host ($message) + } + $x = read-host +} diff --git a/WK_64/Scripts/servers.ps1 b/WK_64/Scripts/servers.ps1 new file mode 100644 index 00000000..2d47e19f --- /dev/null +++ b/WK_64/Scripts/servers.ps1 @@ -0,0 +1,85 @@ +# WK server functions + +## Init ## +$wd = $(Split-Path $MyInvocation.MyCommand.Path) +pushd "$wd" +. .\init.ps1 + +# Variables +$source_server = "10.0.0.10" +$backup_servers = @( + @{ "ip"="10.0.0.10"; + "letter"="Z"; + "name"="ServerOne"; + "path"="Backups"}, + @{ "ip"="10.0.0.11"; + "name"="ServerTwo"; + "letter"="Y"; + "path"="Backups"} + ) +$backup_user = "backup" +$backup_pass = "Abracadabra" + +# Functions +function select-server { + # Check for available servers + $avail_servers = @(Get-PSDrive | Where-Object {$_.DisplayRoot -imatch '\\\\'}) + if ($avail_servers.count -eq 0) { + wk-error "No suitable backup servers were detected." + return $false + } + + # Build menu and get selection + $selection = $null + $main_set = @() + foreach ($server in $avail_servers) { + $_entry = "{0} ({1} free)" -f $server.Description, (human-size $server.Free) + $main_set += @{Name=$_entry} + } + $actions = @(@{Name="Main Menu"; Letter="M"}) + $selection = (menu-select "Where are we saving the backup image(s)?" $main_set $actions) + + if ($selection -imatch '^\d+$') { + $selection -= 1 + return $avail_servers[$selection] + } + return $selection +} +function mount-servers { + # Mount servers + wk-write "Connecting to backup server(s)" + foreach ($_server in $backup_servers) { + if (test-connection $_server.ip -count 3 -quiet) { + try { + $_path = "\\{0}\{1}" -f $_server.ip, $_server.path + $_drive = "{0}:" -f $_server.letter + net use $_drive "$_path" /user:$backup_user $backup_pass | Out-Null + wk-write ("`t{0} server: mounted" -f $_server.name) + + # Add friendly description + $_regex = "^{0}$" -f $_server.letter + (Get-PSDrive | Where-Object {$_.Name -imatch $_regex}).Description = $_server.name + } catch { + wk-warn ("`t{0} server: failed" -f $_server.name) + } + } else { + wk-warn ("`t{0} server: timed-out" -f $_server.name) + } + } +} +function unmount-servers { + # Unmount servers + wk-write "Disconnecting from backup server(s)" + $mounted_servers = @(Get-PSDrive | Where-Object {$_.DisplayRoot -imatch '\\\\'}) + foreach ($_server in $mounted_servers) { + try { + $_drive = "{0}:" -f $_server.Name + net use $_drive /delete | Out-Null + #wk-warn ("`t{0} server: unmounted" -f $_server.name) + wk-warn "`tServer: unmounted" + } catch { + #wk-warn ("`t{0} server: failed" -f $_server.name) + wk-warn "`tServer: failed" + } + } +}