diff --git a/.gitignore b/.gitignore index fff215c..62c9609 100644 --- a/.gitignore +++ b/.gitignore @@ -4,3 +4,5 @@ config*.json .env.* *.key *.pem +*.log +*.csv diff --git a/CoreMigration-RemoveDuplicateComputer/readme.md b/CoreMigration-RemoveDuplicateComputer/readme.md new file mode 100644 index 0000000..13f90b9 --- /dev/null +++ b/CoreMigration-RemoveDuplicateComputer/readme.md @@ -0,0 +1,21 @@ +# removeduplicate.ps1 — Remove Duplicate Devices + +Delete duplicate computer objects left on an **old Core** after migrating to a **new Core**. +The script connects to both Cores via the legacy SOAP endpoint (`MBSDKService/MsgSDK.asmx`), compares by `DeviceName`, and deletes the matching device from the old Core (skips names starting with `newcore`, and ignores `GUID = "Unassigned"`). + +## Requirements +- An account with rights to list devices and delete computers. +- Windows PowerShell 5.1. + +## Configure +Edit the two endpoints in the script: +```powershell +$ldWSold = New-WebServiceProxy -Uri http://oldcore.example.com/MBSDKService/MsgSDK.asmx -Credential $mycreds +$ldWSNew = New-WebServiceProxy -Uri https://newcore.example.com/MBSDKService/MsgSDK.asmx -Credential $mycreds +``` + +## Run +Edit the two endpoints in the script: +```powershell +powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\removeduplicate.ps1 +``` diff --git a/CoreMigration-RemoveDuplicateComputer/removeduplicate.ps1 b/CoreMigration-RemoveDuplicateComputer/removeduplicate.ps1 new file mode 100644 index 0000000..59face4 --- /dev/null +++ b/CoreMigration-RemoveDuplicateComputer/removeduplicate.ps1 @@ -0,0 +1,23 @@ +# http://localhost/MBSDKService/MsgSDK.asmx?WSDL/GetMachineData + +$mycreds = Get-Credential -Credential "Domain\account" + +$ldWSold = New-WebServiceProxy -uri http://oldcore.example.com/MBSDKService/MsgSDK.asmx -Credential $mycreds +$ListOlds = $ldWSold.ListMachines("").Devices + +$ldWSNew = New-WebServiceProxy -uri https://newcore.example.com/MBSDKService/MsgSDK.asmx -Credential $mycreds +$ListNews = $ldWSNew.ListMachines("").Devices + +#GUID DeviceName DomainName LastLogin +foreach ($ListOld in $ListOlds) { + foreach ($ListNew in $ListNews) { + If ($ListNew.DeviceName -notlike "newcore*") { + If ($ListOld.DeviceName -eq $ListNew.DeviceName) { + If ($ListOld.GUID -ne "Unassigned") { + write-host $ListOld.DeviceName "=>" $ListOld.GUID + $ldWSold.DeleteComputerByGUID($ListOld.GUID) + } + } + } + } +} \ No newline at end of file diff --git a/Tools/CopyDrivers/CopyDrivers.au3 b/Tools/CopyDrivers/CopyDrivers.au3 new file mode 100644 index 0000000..7db937c --- /dev/null +++ b/Tools/CopyDrivers/CopyDrivers.au3 @@ -0,0 +1,718 @@ +#cs ---------------------------------------------------------------------------- + + AutoIt Version: 3.2.12.1 + Author: Jan Buelens, Landesk Software (idea stolen from Sergio Ribeiro) + + Script Function: + CopyDrivers. This script copies machine dependent drivers to a provisioning / OSD client machine. + A mapping table (CopyDrivers.ini) is used to map the WMI machine model to a driver source folder. + + A GUI is included to build CopyDrivers.ini + + Version: 1.5.1 + +#ce ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +Dim $iniFilename = "" +Dim $Manufacturer = "" +Dim $Model = "" +Dim $Version = "" +Dim $subfolder = "" +Dim $SourceFolder = "" +Dim $TargetFolder = "" +Dim $sysprep = "C:\sysprep\sysprep.inf" + +Dim $bVerbose = False +Dim $bRunOnce = True +Dim $bCmdLines = True + +; =========================================================================================== +; Validate command line parameters and verify that copydrivers.ini exists +; =========================================================================================== + +If $CmdLine[0] = 0 Then DoGui() ; no command line parameters - do gui + +If $CmdLine[0] > 0 And ($CmdLine[1] = "/?" Or $CmdLine[1] = "-?" Or $CmdLine[1] = "help") Then + Usage() +EndIf + +For $n = 1 to $CmdLine[0] + if $CmdLine[$n] = "/s" Or $CmdLine[$n] = "-s" Then + if $n >= $CmdLine[0] Then Usage() + $SourceFolder = $CmdLine[$n + 1] + $n = $n + 1 + ElseIf $CmdLine[$n] = "/d" Or $CmdLine[$n] = "-d" Then + if $n >= $CmdLine[0] Then Usage() + $TargetFolder = $CmdLine[$n + 1] + $n = $n + 1 + ElseIf $CmdLine[$n] = "/c" Or $CmdLine[$n] = "-c" Then + ; if no other command line parameters are required, use /c to copy drivers rather than launch GUI + ElseIf $CmdLine[$n] = "/v" Or $CmdLine[$n] = "-v" Then + $bVerbose = True; + ;If there is a reason for not doing the cmdlines and GuiRunOnce stuff, uncomment these lines + ; ElseIf $CmdLine[$n] = "/cmdlines" Or $CmdLine[$n] = "-cmdlines" Then + ; $bCmdLines = False + ; ElseIf $CmdLine[$n] = "/RunOnce" Or $CmdLine[$n] = "-RunOnce" Then + ; $bRunOnce = False + Else + Usage() + EndIf +Next + +$iniFilename = @ScriptDir & "\copydrivers.ini" ; @ScriptDir is folder in which this script (or compiled program) resides +If not FileExists($iniFilename) Then ErrorExit("File not found: " & $iniFilename, 2) + +; If no source and target folders were defined on the command line, take them from the [Config] section of copydrivers.ini + +If $SourceFolder = "" Then $SourceFolder = IniRead($iniFilename, "Config", "DriversSource", "") +If $TargetFolder = "" Then $TargetFolder = IniRead($iniFilename, "Config", "DriversTarget", "") +If $SourceFolder = "" Then ErrorExit("No Drivers Source Folder defined", 3) +If $TargetFolder = "" Then ErrorExit("No Drivers Target Folder defined", 4) + +; MsgBox(0, "CopyDrivers", "source: " & $SourceFolder & @CRLF & "target: " & $TargetFolder); + +; =========================================================================================== +; Read Manufacturer, Model and Version from WMI. We only use Model. +; =========================================================================================== + +ReadWmi($Manufacturer, $Model, $Version) + +; =========================================================================================== +; Find a match for WMI Model in [Models] section of copydrivers.ini +; =========================================================================================== + +;IniReadSection returns a 2 dimensional array of keywords and values; $ini[n][0] is key # n, $ini[n][1] is value # n; $ini[0][0] is the number of elements +$ini = IniReadSection($iniFilename, "Models") +if @error OR $ini[0][0] = 0 Then ErrorExit("There is no [Models] section in " & $iniFilename, 5) + +; Take WMI Model and find match in ini file +For $n = 1 to $ini[0][0] + if $ini[$n][0] = $Model Then + $subfolder = $ini[$n][1] + ExitLoop + EndIf +Next + +if $subfolder = "" Then ErrorExit("No match found for Model """ & $Model & """ in " &$iniFilename, 6) + +If $bVerbose Then MsgBox(0, "CopyDrivers","Manufacturer: " & $Manufacturer & @CRLF & "Model: " & $Model & @CRLF & "Version: " & $Version & @CRLF & "subfolder: " & $subfolder) + +; =========================================================================================== +; Copy the driver files +; =========================================================================================== + +$src = $SourceFolder & "\" & $subfolder +If Not IsFolder($src) Then ErrorExit("Source folder not found: " & $src, 7) +DirCreate($TargetFolder) +If Not IsFolder($TargetFolder) Then ErrorExit("Unable to create target folder: " & $TargetFolder, 8) +If Not DirCopy($src, $TargetFolder, 1) Then ErrorExit("Unable to copy folder: " & $TargetFolder, 9) ; 1 on DirCopy means overwrite existing files + +; =========================================================================================== +; Handle RunOnce and CmdLines +; =========================================================================================== + +if $bRunOnce Then DoRunOnce() +if $bCmdLines Then DoCmdLines() + +; =========================================================================================== +; Done +; =========================================================================================== + +; =========================================================================================== +Func DoCmdLines() +; Run at deployment time if the $bCmdLines is true. If there is a cmdlines.txt file in the drivers folder that we just copied, set up +; sysprep.inf such that it will be processed at mini-setup time. If sysprep.inf already refers to a cmdlines.txt file, merge it. The cmdlines.txt file must be +; in the format as described in the sysprep documentation. Example: +; +; [cmdlines] +; "c:\drivers\setup\driver1\setup.exe" +; +; This program also has a GUI that allows cmdlines.txt to be edited in a convenient way, without the user being aware of the format or the location of the file. +; =========================================================================================== + +Dim $MyBase = $TargetFolder +Dim $MyCmdLines = $MyBase & "\cmdlines.txt" +Dim $oemFolder = "" +Dim $OemCmdLines = "" + +if not FileExists($MyCmdLines) Then Return + +if not FileExists($sysprep) Then ErrorExit("File not found: " & $sysprep, 2) +$InstallFilesPath = Iniread($sysprep, "unattended", "InstallFilesPath", "") +if $InstallFilesPath = "" Then + ; no InstallFilesPath in sysprep.inf - create one + $InstallFilesPath = $MyBase + IniWrite($sysprep, "unattended", "InstallFilesPath", $InstallFilesPath) +EndIf + +$oemFolder = $InstallFilesPath & "\$oem$" +$OemCmdLines = $oemFolder & "\cmdlines.txt" + +if not FileExists($OemCmdLines) Then + ; no $oem$\cmdlines.txt exist - just copy ours + $success = FileCopy($MyCmdLines, $OemCmdLines, 8) ; 8 = create folders + if $success = 0 Then ErrorExit("Copy " & $MyCmdLines & " to " & $OemCmdLines & " failed", 3) + Exit 0 +EndIf + +; A $oem$\cmdlines.txt already exists - append ours +$file1 = FileOpen($MyCmdLines, 0) ; 0 = read +if $file1 = -1 Then ErrorExit("Error opening " & $MyCmdLines, 5) +$file2 = FileOpen($OemCmdLines, 1) ; 1 = append +if $file2 = -1 Then ErrorExit("Error opening " & $OemCmdLines, 4) +While 1 + $line = FileReadLine($file1) + If @error Then ExitLoop + If StringStripWS($line,8) <> "[commands]" Then ; StringStripWS($line,8) strips all white space + FileWriteLine($file2, $line) + EndIf +Wend +FileClose($file1) +FileClose($file2) + +EndFunc + + +; =========================================================================================== +Func DoRunOnce() +; Run at deployment time if the $bRunonce is true. If there is a file called GuiRunOnce.ini in the drivers +; folder that we just copied, merge its GuiRunOnce section with the sysprep.inf GuiRunOnce section. The GuiRunOnce.ini file must be +; in the format as described in the sysprep documentation. Example: +; +; [GuiRunOnce] +; Command0="c:\drivers\driver1\setup.exe" +; Command1="c:\drivers\driver2\setup.exe" +; +; This program also has a GUI that allows GuiRunOnce.ini to be edited in a convenient way, without the user to be aware of the format or the location of the file. +; =========================================================================================== + + +Dim $MyRunOnce = $TargetFolder & "\GuiRunOnce.ini" + +if not FileExists($MyRunOnce) Then Return + +if not FileExists($sysprep) Then ErrorExit("File not found: " & $sysprep, 2) +Dim $section1[1][1] +$section1[0][0] = 0 +$section1 = IniReadSection($sysprep, "GuiRunOnce") +if @error Then + Dim $section1[1][1] + $section1[0][0] = 0 +EndIf +$section2 = IniReadSection($MyRunOnce, "GuiRunOnce") +if @error Then Return +if $section2[0][0] = 0 Then Return + +$count = $section1[0][0] +For $i = 1 To $section2[0][0] + $count = $count + 1 + ReDim $section1[$count + 1][2] + $section1[$count][0] = $section2[$i][0] + $section1[$count][1] = $section2[$i][1] +Next +$section1[0][0] = $count +For $i = 1 To $section1[0][0] + $section1[$count][0] = "Command" & ($i - 1) +Next + +IniWriteSection($sysprep, "GuiRunOnce", $section1) + + +EndFunc + +; =========================================================================================== +; Set the 3 WMI attributes mentioned. We only use the Model, but feel free to organise things differently +Func ReadWmi(ByRef $Manufacturer, ByRef $Model, ByRef $Version) +; =========================================================================================== + +$objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") +If $objWMIService = 0 Then ErrorExit("Failed to connect to WMI", 10) + +$colRows = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem") +For $row In $colRows + $Manufacturer = StringStripWS($Row.Manufacturer, 3) + $Model = StringStripWS($Row.Model, 3) +Next + +$colRows = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystemProduct") +For $row In $colRows + $Version = StringStripWS($Row.Version, 3) +Next + +Return True + +EndFunc + + + +; =========================================================================================== +Func Usage() +; =========================================================================================== + + Msgbox ("0", "CopyDrivers V1.5.1", _ + "This program copies machine specific drivers from a source folder on a" _ + & @CRLF & "server to a destination folder on the local machine." & @CRLF _ + & @CRLF & "Usage: CopyDrivers [/s ] [/d ] [/cmdlines] [/RunOnce] [/c] [/v]" _ + & @CRLF & "where is the base path for machine specfic driver folders" _ + & @CRLF & " is the target folder on the local machine." _ + & @CRLF & " /v: verbose" _ + & @CRLF & " /c: copy" & @CRLF _ + & @CRLF & "CopyDrivers requires a list that associates machine types with driver folders." _ + & @CRLF & "This list is to be supplied in the [Models] section of copydrivers.ini, which" _ + & @CRLF & "associates WMI model names with specific subfolders of ." & @CRLF _ + & @CRLF & "When invoked without command line switches, CopyDrivers opens a GUI that allows" _ + & @CRLF & "copydrivers.ini to be edited. Use /c to do the copying rather than show the GUI." _ + ) + + Exit 1 + +EndFunc + + +; =========================================================================================== +; The remainder of the file is just GUI stuff. It does nothing that you can't do by simply editing the CopyDrivers.ini file +; =========================================================================================== + + +; =========================================================================================== +; Main GUI function called when program is invoked with no command line parameters +Func DoGui() +; =========================================================================================== +$iniFilename = @ScriptDir & "\copydrivers.ini" ; @ScriptDir is folder in which this script (or compiled program) resides +$SourceFolder = IniRead($iniFilename, "Config", "DriversSource", "") +$TargetFolder = IniRead($iniFilename, "Config", "DriversTarget", "") + +#Region ### START Koda GUI section ### Form=z:\install\autoit\koda_1.7.0.1\forms\myform1.kxf +$Form_Main = GUICreate("CopyDrivers", 452, 322) +$BtnOK = GUICtrlCreateButton("OK", 16, 280, 97, 25, 0) +$EditSource = GUICtrlCreateInput("", 13, 32, 305, 21) +GUICtrlSetState(-1, $GUI_DISABLE) +$BtnConfig = GUICtrlCreateButton("Edit", 335, 32, 57, 21, 0) +$ListView1 = GUICtrlCreateListView("WMI Model|Subfolder", 13, 120, 305, 145) +GUICtrlSendMsg(-1, 0x101E, 0, 150) +GUICtrlSendMsg(-1, 0x101E, 1, 150) +; GUICtrlSetTip(-1, "abc") +$BtnAdd = GUICtrlCreateButton("Add", 335, 126, 57, 21, 0) +$BtnEdit = GUICtrlCreateButton("Edit", 335, 157, 57, 21, 0) +$BtnDelete = GUICtrlCreateButton("Delete", 335, 190, 57, 21, 0) +GUICtrlCreateLabel("Drivers source folder", 16, 14, 101, 17) +$BtnCancel = GUICtrlCreateButton("Cancel", 133, 281, 97, 25, 0) +$EditTarget = GUICtrlCreateInput("", 13, 79, 305, 21) +GUICtrlSetState(-1, $GUI_DISABLE) +GUICtrlCreateLabel("Drivers target folder", 16, 61, 96, 17) +GUISetState(@SW_SHOW) +#EndRegion ### END Koda GUI section ### + +GUICtrlSetData($EditSource, $SourceFolder) +GUICtrlSetData($EditTarget, $TargetFolder) + +;IniReadSection returns a 2 dimensional array of keywords and values; $ini[n][0] is key # n, $ini[n][1] is value # n; $ini[0][0] is the number of elements +$items = 0 +$count = 0 +$ini = IniReadSection($iniFilename, "Models") +if not @error Then + $items = $ini[0][0] +EndIf + +$count1 = $items +if ($items = 0) Then $count1 = 1 + +Dim $item [$count1] [4] ; we'll store the model in item[n][0], the folder in item[n][1], the listview controlid in item[n][2] and the state (0 = deleted, 1 = active) in item[n][3] +if $items = 0 Then + ; if the section was empty or non-existing, we create one dummy item to avoid run-time errors + $item[0][0] = "" + $item[0][1] = "" + $item[0][2] = 0 + $item[0][3] = 0 +EndIf + +For $n = 1 to $items + $item[$n-1][0] = $ini[$n][0] + $item[$n-1][1] = $ini[$n][1] + $item[$n-1][2] = GUICtrlCreateListViewItem($ini[$n][0] & "|" & $ini[$n][1], $ListView1) + $item[$n-1][3] = 1 + $count = $count + 1 +Next + +While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Exit + Case $BtnOK + IniWrite($iniFilename, "Config", "DriversSource", $SourceFolder) + IniWrite($iniFilename, "Config", "DriversTarget", $TargetFolder) + Dim $ini[$count][2] + $i = 0 + for $n = 0 to UBound($item) - 1 + if $item[$n][3] = 1 Then + $ini[$i][0] = $item[$n][0] + $ini[$i][1] = $item[$n][1] + $i = $i + 1 + EndIf + Next + IniWriteSection($iniFilename, "Models", $ini, 0) + Exit + Case $BtnCancel + Exit + Case $BtnConfig + $newSource = $SourceFolder + $newTarget = $TargetFolder + if EditConfig($newSource, $newTarget) Then + $SourceFolder = $newSource + $TargetFolder = $newTarget + GUICtrlSetData($EditSource, $SourceFolder) + GUICtrlSetData($EditTarget, $TargetFolder) + EndIf + Case $BtnDelete + $id = GUICtrlRead($ListView1) + for $n = 0 to UBound($item) - 1 + if $item[$n][2] = $id And $item[$n][3] = 1 Then + GUICtrlDelete($id) + $item[$n][3] = 0 + $count = $count - 1 + EndIf + Next + Case $BtnAdd + Dim $newModel = "" + Dim $newFolder = "" + If AddModel($newModel, $newFolder, 0) Then + $n = UBound($item); + ReDim $item[$n+1][4] + $item[$n][0] = $newModel + $item[$n][1] = $newFolder + $item[$n][2] = GUICtrlCreateListViewItem($newModel & "|" & $newFolder, $ListView1) + $item[$n][3] = 1 + $count = $count + 1 + EndIf + Case $BtnEdit + $id = GUICtrlRead($ListView1) + for $n = 0 to UBound($item) - 1 + if $item[$n][2] = $id And $item[$n][3] = 1 Then + ExitLoop + EndIf + Next + if $n >= UBound($item) Then ContinueLoop + Dim $newModel = $item[$n][0] + Dim $newFolder = $item[$n][1] + If AddModel($newModel, $newFolder, 1) Then + $item[$n][0] = $newModel + $item[$n][1] = $newFolder + GUICtrlSetData($id, $newModel & "|" & $newFolder) + EndIf + + EndSwitch +WEnd + + +EndFunc + +; =========================================================================================== +; GUI function called when the Add or Edit button is pressed. +Func AddModel(ByRef $model, ByRef $folder, $flag) ; flag = 0: Add flag = 1: Edit +; =========================================================================================== + +$title = "Add Model" +if $flag = 1 Then $title = "Edit Model" + +#Region ### START Koda GUI section ### Form=Z:\install\AutoIt\koda_1.7.0.1\Forms\Form_AddItem.kxf +$Form_AddModel = GUICreate($title, 429, 413) +GUICtrlCreateGroup("", 8, 1, 297, 137) +$InputModel = GUICtrlCreateInput("", 16, 40, 209, 21) +$InputFolder = GUICtrlCreateInput("", 16, 97, 209, 21, BitOR($ES_AUTOHSCROLL,$ES_READONLY) ) +GUICtrlCreateLabel("Model", 16, 16, 33, 17) +GUICtrlCreateLabel("Subfolder", 17, 73, 49, 17) +$Btn_WMI = GUICtrlCreateButton("WMI", 236, 40, 57, 21, 0) +$BtnBrowse = GUICtrlCreateButton("..", 236, 97, 57, 21, 0) +$CmdLines = GUICtrlCreateEdit("", 16, 192, 385, 81, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_WANTRETURN,$WS_HSCROLL,$WS_VSCROLL,$WS_BORDER), $ES_MULTILINE) +$ButtonOK = GUICtrlCreateButton("&OK", 321, 11, 75, 25, 0) +$ButtonCancel = GUICtrlCreateButton("&Cancel", 322, 43, 75, 25, 0) +$RunOnce = GUICtrlCreateEdit("", 16, 304, 385, 81, BitOR($ES_AUTOVSCROLL,$ES_AUTOHSCROLL,$ES_WANTRETURN,$WS_HSCROLL,$WS_VSCROLL,$WS_BORDER), $ES_MULTILINE) +GUICtrlCreateGroup("Command lines for drivers that require a setup program", 8, 152, 409, 249) +GUICtrlCreateLabel("Before reboot (cmdlines.txt)", 16, 174, 132, 17) +GUICtrlCreateLabel("After reboot (GuiRunonce section of sysprep.inf)", 16, 287, 230, 17) +GUISetState(@SW_SHOW) +#EndRegion ### END Koda GUI section ### + +GUICtrlSetData($InputModel, $model) +GUICtrlSetData($InputFolder, $folder) + +; If the model specific folder exists, read the cmdlines.txt and GuiRunOnce.txt files from it and display their contents in the $cmdlines and $RunOnce edit boxes. +; If the model specific folder does not exist, disable the edit boxes + +$RunOnceText = "" +$CmdLinesText = "" + +$ModelFolder = $SourceFolder & "\" & $folder +if $SourceFolder = "" or $folder = "" Then $ModelFolder = "---dummy---" +if IsFolder($ModelFolder) Then + $CmdLinesText = ReadCmdLines($ModelFolder) + GUICtrlSetData($CmdLines, $CmdLinesText) + $RunOnceText = ReadRunOnce($ModelFolder) + GUICtrlSetData($RunOnce, $RunOnceText) +Else + GUICtrlSetState($CmdLines, $GUI_DISABLE) + GUICtrlSetState($RunOnce, $GUI_DISABLE) +EndIf + +While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Return False + Case $ButtonCancel + GUIDelete($Form_AddModel) + Return False + Case $BtnBrowse + $flag = 1 + if IsWinPE() Then $flag = 0 + $old = $SourceFolder + "\" + GUICtrlRead($InputFolder) + $new = FileSelectFolder("Select Folder", $SourceFolder, $flag, $ModelFolder) ; $flag = 1 : Show Create Folder Button (does not work in WinPE) + if $new <> "" Then + $new = StringMid($new, StringLen($SourceFolder) + 2) + GUICtrlSetData($InputFolder, $new) + EndIf + $ModelFolder = $SourceFolder & "\" & $new + if $SourceFolder = "" or $new = "" Then $ModelFolder = "---dummy---" + if IsFolder($ModelFolder) Then + ; User selected a new model specific folder - and the folder exists. Read the cmdlines.txt and GuiRunOnce.txt files from it and display their contents in the + ; $cmdlines and $RunOnce edit boxes. + GUICtrlSetState($CmdLines, $GUI_ENABLE) + GUICtrlSetState($RunOnce, $GUI_ENABLE) + $CmdLinesText = ReadCmdLines($ModelFolder) + $RunOnceText = ReadRunOnce($ModelFolder) + Else + ; User selected a new model specific folder - and the folder does not exist. Disable the $cmdlines and $RunOnce edit boxes. + GUICtrlSetState($CmdLines, $GUI_DISABLE) + GUICtrlSetState($RunOnce, $GUI_DISABLE) + $CmdLinesText = "" + $RunOnceText = "" + EndIf + GUICtrlSetData($CmdLines, $CmdLinesText) + GUICtrlSetData($RunOnce, $RunOnceText) + Case $Btn_WMI + ReadWmi($Manufacturer, $Model, $Version) + GUICtrlSetData($InputModel, $Model) + Case $ButtonOK + $model = StringStripWS(GUICtrlRead($InputModel),3) + $folder = StringStripWS(GUICtrlRead($InputFolder),3) + If $model = "" Then + MsgBox(0, "CopyDrivers", "A model is required") + ElseIf $folder = "" Then + MsgBox(0, "CopyDrivers", "A folder is required") + Else + $newCmdLinesText = GUICtrlRead($CmdLines) + $newRunOnceText = GUICtrlRead($RunOnce) + GUIDelete($Form_AddModel) + if IsFolder($ModelFolder) Then + if $newCmdLinesText <> $CmdLinesText Then SaveCmdLines($ModelFolder, $newCmdLinesText) + if $newRunOnceText <> $RunOnceText Then SaveRunOnce ($ModelFolder, $newRunOnceText) + EndIf + return True + EndIf + EndSwitch +WEnd + +EndFunc + +; =========================================================================================== +; GUI function to edit the SOurce Folder and target folder settings +Func EditConfig(ByRef $source, ByRef $target) +; =========================================================================================== + +#Region ### START Koda GUI section ### Form=Z:\install\AutoIt\koda_1.7.0.1\Forms\Form_Config.kxf +$Form_Config = GUICreate("Edit Config", 316, 197) +; GUISetIcon("D:\003.ico") +GUICtrlCreateGroup("", 8, 1, 297, 153) +$EditSource = GUICtrlCreateInput("", 16, 38, 217, 21) +$EditTarget = GUICtrlCreateInput("", 16, 110, 217, 21) +GUICtrlCreateLabel("Drivers Source Folder (Specify UNC path)", 16, 16, 200, 17) +GUICtrlCreateLabel("DriversTarget Folder", 16, 87, 100, 17) +$BtnBrowse = GUICtrlCreateButton("..", 244, 38, 57, 21, 0) +GUICtrlCreateGroup("", -99, -99, 1, 1) +$BtnOK = GUICtrlCreateButton("&OK", 65, 163, 75, 25, 0) +$BtnCancel = GUICtrlCreateButton("&Cancel", 162, 163, 75, 25, 0) +GUISetState(@SW_SHOW) +#EndRegion ### END Koda GUI section ### + +GUICtrlSetData($EditSource, $source) +GUICtrlSetData($EditTarget, $target) + +While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Return False + Case $BtnCancel + GUIDelete($Form_Config) + Return False + Case $BtnOK + $source = StringStripWS(GUICtrlRead($EditSource),3) + $target = StringStripWS(GUICtrlRead($EditTarget),3) + if $source = "" Then + MsgBox(0, "CopyDrivers", "A source folder is required") + Else + GUIDelete($Form_Config) + Return True + EndIf + Case $BtnBrowse + $new = FileSelectFolder("Select Source Folder", "", 0, $source) + $new = StringStripWS($new,3) + GUICtrlSetData($EditSource, $new) + if $new <> "" Then $source = $new + EndSwitch +WEnd + +EndFunc + +; =========================================================================================== +; Used by GUI to read cmdlines.txt from specified folder. The data is returned in a format ready to be fed into a GUI edit box +; (lines separated by CR-LF). The header line ([Commands]) is not included in the data. +Func ReadCmdLines($folder) +; =========================================================================================== + $retstring = "" + $filename = $folder & "\cmdlines.txt" + $lineno = 0 + $file = FileOpen($filename, 0) ; 0 = read + if $file = -1 Then return "" + + While 1 + $line = FileReadLine($file) + If @error Then ExitLoop + If StringStripWS($line,8) = "[commands]" Then ContinueLoop ; StringStripWS($line,8) strips all white space + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + if $line = "" Then ContinueLoop + if StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + if $line = "" Then ContinueLoop + if $lineno > 0 Then $retstring = $retstring & @CRLF + $lineno = $lineno + 1 + $retstring = $retstring & $line + Wend + + FileClose($file) + return $retstring + +EndFunc + +; =========================================================================================== +; Used by GUI to read GuiRunOnce.ini from specified folder. The data is returned in a format ready to be fed into a GUI edit box +; (lines separated by CR-LF). The header line ([GuiRunOnce]) is not included in the data, nor are the CommandN= prefixes. +Func ReadRunOnce($folder) +; =========================================================================================== + $retstring = "" + $filename = $folder & "\GuiRunOnce.ini" + $lineno = 0 + $lines = IniReadSection($filename, "GuiRunOnce") + if @error Then return "" + + for $i = 1 to $lines[0][0] + $line = $lines[$i][1] + if $line = "" Then ContinueLoop + if StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + if $line = "" Then ContinueLoop + if $lineno > 0 Then $retstring = $retstring & @CRLF + $lineno = $lineno + 1 + $retstring = $retstring & $line + Next + + return $retstring + +EndFunc + +; =========================================================================================== +; Used by GUI to save cmdlines.txt in specified folder. The input data ($text) is the raw data as read from the GUI edit control. The header line ([Commands]) is not expected to +; be included in the input data. +Func SaveCmdLines($folder, $text) +; =========================================================================================== + $filename = $folder & "\cmdlines.txt" + if not IsFolder($folder) Then DirCReate($folder) + $file = FileOpen($filename, 2) ; 2 = create + $text = StringReplace($text, @LF, "") + $lineno = 0 + $lines = StringSplit($text, @CR) + for $i = 1 to $lines[0] + $line = StringReplace($lines[$i], @LF, "") + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + if $line = "" Then ContinueLoop + if StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = '"' & $line & '"' + if $lineno = 0 Then FileWriteLine($file, "[Commands]") + $lineno = $lineno + 1 + FileWriteLine($file, $line) + Next + FileClose($file) + if $lineno = 0 Then FileDelete($filename) + +EndFunc + +; =========================================================================================== +; Used by GUI to save GuiRunOnce.ini in specified folder. The input data ($text) is the raw data as read from the GUI edit control. The header line ([GuiRunOnce]) is not expected to +; be included in the input data, nor are the "CommandN=" prefixes. +Func SaveRunOnce($folder, $text) +; =========================================================================================== + $filename = $folder & "\GuiRunOnce.ini" + if not IsFolder($folder) Then DirCReate($folder) + $file = FileOpen($filename, 2) ; 2 = create + $text = StringReplace($text, @LF, "") + $lineno = 0 + $lines = StringSplit($text, @CR) + for $i = 1 to $lines[0] + $line = StringReplace($lines[$i], @LF, "") + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + if $line = "" Then ContinueLoop + if StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = 'Command' & $lineno & '="' & $line & '"' + if $lineno = 0 Then FileWriteLine($file, "[GuiRunOnce]") + $lineno = $lineno + 1 + FileWriteLine($file, $line) + Next + FileClose($file) + if $lineno = 0 Then FileDelete($filename) + +EndFunc + + +; =========================================================================================== +; Return true if $s is a folder +Func IsFolder($s) +; =========================================================================================== + If Not FileExists($s) Or Not StringInStr(FileGetAttrib($s), "D") Then Return False + Return True +EndFunc + +; =========================================================================================== +; Return true uf running under WinPE +Func IsWinPE() +; =========================================================================================== + If EnvGet("SystemDrive") = "X:" Then Return True + Return False +EndFunc + + +; =========================================================================================== +Func ErrorExit($msg, $exitcode) +; =========================================================================================== + + MsgBox(0x40010, "CopyDrivers", $msg, 10) ; 10 is timeout, i.e. the msgbox closes after 10 seconds + Exit $exitcode + +EndFunc diff --git a/Tools/CopyDrivers_x64/CopyDrivers_x64.exe b/Tools/CopyDrivers_x64/CopyDrivers_x64.exe new file mode 100644 index 0000000..09cfd78 Binary files /dev/null and b/Tools/CopyDrivers_x64/CopyDrivers_x64.exe differ diff --git a/Tools/DBrepair/EPM_DBRepair_2021.1.zip b/Tools/DBrepair/EPM_DBRepair_2021.1.zip new file mode 100644 index 0000000..65571ec Binary files /dev/null and b/Tools/DBrepair/EPM_DBRepair_2021.1.zip differ diff --git a/Tools/DBrepair/UsingSnapshotInDbrepair_Rev1.pdf b/Tools/DBrepair/UsingSnapshotInDbrepair_Rev1.pdf new file mode 100644 index 0000000..ce492e0 Binary files /dev/null and b/Tools/DBrepair/UsingSnapshotInDbrepair_Rev1.pdf differ diff --git a/Tools/Landesk_Autoit/CopyDrivers.au3 b/Tools/Landesk_Autoit/CopyDrivers.au3 new file mode 100644 index 0000000..10924bd --- /dev/null +++ b/Tools/Landesk_Autoit/CopyDrivers.au3 @@ -0,0 +1,1140 @@ +#Region AutoIt3Wrapper directives section +#AutoIt3Wrapper_Res_Fileversion=1.6 +#EndRegion AutoIt3Wrapper directives section + +#cs ---------------------------------------------------------------------------- + + AutoIt Version: 3.2.12.1 + Author: Jan Buelens, Landesk Software (idea stolen from Sergio Ribeiro) + + Script Function: + CopyDrivers. This script copies machine dependent drivers to a provisioning / OSD client machine. + A mapping table (CopyDrivers.ini) is used to map the WMI machine model to a driver source folder. + + A GUI is included to build CopyDrivers.ini + + Change History: + V1.5.1 05 Dec 2008. This is the version that came out with the HII V9 document + V1.6 07 July 2009. + * Some people are copying dozens over even hundreds of MB. Progress info is therefore desirable. Picked up a copy function with progress bar + * logging + * Wildcard matching. Example: + + [Models] + *=common + Precision Workstation T3400=T3400 + 2007FVG=ThinkPad T60 + HP Compaq dc5100 SFF*=DC5100 + + Now suppose a target machine has a WMI model name = "HP Compaq dc5100 SFF(PZ579UA)". The first line (*) matches all models, therefore the subfolders called "common" will be copied. + The last line also matches, therefore subfolder DC5100 will also be copied. + + +#ce ---------------------------------------------------------------------------- + +#include +#include +#include +#include + +$progname = "CopyDrivers V1.6" +Dim $logfilename = "" ; log file (from /log command line parameter) +Dim $log = -1 + +Dim $iniFilename = "" +Dim $Manufacturer = "" +Dim $Model = "" +Dim $Version = "" +Dim $subfolder = "" +Dim $SourceFolder = "" +Dim $TargetFolder = "" +Dim $sysprep = "C:\sysprep\sysprep.inf" + +Dim $bVerbose = False +Dim $bRunOnce = True +Dim $bCmdLines = True + +; =========================================================================================== +; Validate command line parameters and verify that copydrivers.ini exists +; =========================================================================================== + +If $CmdLine[0] = 0 Then DoGui() ; no command line parameters - do gui + +If $CmdLine[0] > 0 And ($CmdLine[1] = "/?" Or $CmdLine[1] = "-?" Or $CmdLine[1] = "help") Then + Usage() +EndIf + +For $n = 1 To $CmdLine[0] + $s = "" + If $CmdLine[$n] = "/s" Or $CmdLine[$n] = "-s" Then + ; "legacy" syntax: /s + If $n >= $CmdLine[0] Then Usage() + $SourceFolder = $CmdLine[$n + 1] + $n = $n + 1 + ElseIf ValParam($CmdLine[$n], "s", $s) Then + ; "new" syntax: /s= + $SourceFolder = $s + ElseIf $CmdLine[$n] = "/d" Or $CmdLine[$n] = "-d" Then + ; "legacy" syntax: /d + If $n >= $CmdLine[0] Then Usage() + $TargetFolder = $CmdLine[$n + 1] + $n = $n + 1 + ElseIf ValParam($CmdLine[$n], "d", $s) Then + ; "new" syntax: /d + $TargetFolder = $s + ElseIf ValParam($CmdLine[$n], "log", $s) Then + $logfilename = $s + ElseIf $CmdLine[$n] = "/c" Or $CmdLine[$n] = "-c" Then + ; if no other command line parameters are required, use /c to copy drivers rather than launch GUI + ElseIf $CmdLine[$n] = "/v" Or $CmdLine[$n] = "-v" Then + $bVerbose = True; + ;If there is a reason for not doing the cmdlines and GuiRunOnce stuff, uncomment these lines + ; ElseIf $CmdLine[$n] = "/cmdlines" Or $CmdLine[$n] = "-cmdlines" Then + ; $bCmdLines = False + ; ElseIf $CmdLine[$n] = "/RunOnce" Or $CmdLine[$n] = "-RunOnce" Then + ; $bRunOnce = False + Else + Usage() + EndIf +Next + +LogOpen($logfilename) + +$iniFilename = PathConcat(@ScriptDir, "copydrivers.ini") ; @ScriptDir is folder in which this script (or compiled program) resides +LogIniSection($iniFilename, "Config") +If Not FileExists($iniFilename) Then ErrorExit("File not found: " & $iniFilename, 2) + +; If no source and target folders were defined on the command line, take them from the [Config] section of copydrivers.ini + +If $SourceFolder = "" Then $SourceFolder = IniRead($iniFilename, "Config", "DriversSource", "") +If $TargetFolder = "" Then $TargetFolder = IniRead($iniFilename, "Config", "DriversTarget", "") +If $SourceFolder = "" Then ErrorExit("No Drivers Source Folder defined", 3) +If $TargetFolder = "" Then ErrorExit("No Drivers Target Folder defined", 4) + +LogMessage("source: " & $SourceFolder & ", target: " & $TargetFolder) + +; =========================================================================================== +; Read Manufacturer, Model and Version from WMI. We only use Model. +; =========================================================================================== + +ReadWmi($Manufacturer, $Model, $Version) +LogMessage("WMI info: Manufacturer=" & $Manufacturer & ", Model=" & $Model & ", Version=" & $Version) +If $bVerbose Then MsgBox(0, $progname, "Manufacturer: " & $Manufacturer & @CRLF & "Model: " & $Model & @CRLF & "Version: " & $Version) + +; =========================================================================================== +; Copy the driver files. Do a wildcard match of the WMI model with each line in [Models] section of copydrivers.ini +; and copy all subfolders that match +; =========================================================================================== + +DirCreate($TargetFolder) +If Not IsFolder($TargetFolder) Then ErrorExit("Unable to create target folder: " & $TargetFolder, 8) + +;IniReadSection returns a 2 dimensional array of keywords and values; $ini[n][0] is key # n, $ini[n][1] is value # n; $ini[0][0] is the number of elements + +LogIniSection($iniFilename, "Models") +$ini = IniReadSection($iniFilename, "Models") +If @error Or $ini[0][0] = 0 Then ErrorExit("There is no [Models] section in " & $iniFilename, 5) + + +For $n = 1 To $ini[0][0] + ; if $Model = $ini[$n][0] Then ; if you want a plain compare rather than wildcard match, uncomment this line and comment out next line + If WildcardMatch($Model, $ini[$n][0]) Then + $subfolder = $ini[$n][1] + $src = PathConcat($SourceFolder, $subfolder) + LogMessage("Match on line " & $n & ": " & $ini[$n][0]) + LogMessage(GetTime() & " Start copy from " & $src & " to " & $TargetFolder) + If Not IsFolder($src) Then ErrorExit("Source folder not found: " & $src, 7) + ; Previous versions used the built-in DirCopy() function. Replaced with _CopyDirWithProgress(). If the new function causes trouble, use DirCopy again + ; If Not DirCopy($src, $TargetFolder, 1) Then ErrorExit("Unable to copy folder: " & $TargetFolder, 9) ; 1 on DirCopy means overwrite existing files + $stat = _CopyDirWithProgress($src, $TargetFolder) + LogMessage(GetTime() & " End copy from " & $src & " to " & $TargetFolder) + If $stat Then ErrorExit("Error copying driver files", 9) + EndIf +Next +If $subfolder = "" Then ErrorExit("No match found for Model """ & $Model & """ in " & $iniFilename, 6) + + +; =========================================================================================== +; Handle RunOnce and CmdLines +; =========================================================================================== + +If $bRunOnce Then DoRunOnce() +If $bCmdLines Then DoCmdLines() + +; =========================================================================================== +; Done +; =========================================================================================== + +; =========================================================================================== +Func DoCmdLines() + ; Run at deployment time if the $bCmdLines is true. If there is a cmdlines.txt file in the drivers folder that we just copied, set up + ; sysprep.inf such that it will be processed at mini-setup time. If sysprep.inf already refers to a cmdlines.txt file, merge it. The cmdlines.txt file must be + ; in the format as described in the sysprep documentation. Example: + ; + ; [cmdlines] + ; "c:\drivers\setup\driver1\setup.exe" + ; + ; This program also has a GUI that allows cmdlines.txt to be edited in a convenient way, without the user being aware of the format or the location of the file. + ; =========================================================================================== + + Local $MyBase = $TargetFolder + Local $MyCmdLines = PathConcat($MyBase, "cmdlines.txt") + Local $OemCmdLines = "" + + If Not FileExists($MyCmdLines) Then + LogMessage("File not found: " & $MyCmdLines) + Return + EndIf + + LogMessage("File exists: " & $MyCmdLines) + + If Not FileExists($sysprep) Then ErrorExit("File not found: " & $sysprep, 2) + Local $InstallFilesPath = IniRead($sysprep, "unattended", "InstallFilesPath", "") + If $InstallFilesPath = "" Then + ; no InstallFilesPath in sysprep.inf - create one + $InstallFilesPath = $MyBase + IniWrite($sysprep, "unattended", "InstallFilesPath", $InstallFilesPath) + LogMessage("Added to sysprep.inf [unattended]: InstallFilesPath=" & $InstallFilesPath) + EndIf + + $OemCmdLines = PathConcat($InstallFilesPath, "$oem$\cmdlines.txt") + + LogFileContents($OemCmdLines, $OemCmdLines & " before merge:") + + If Not FileExists($OemCmdLines) Then + ; no $oem$\cmdlines.txt exist - just copy ours + Local $success = FileCopy($MyCmdLines, $OemCmdLines, 8) ; 8 = create folders + If $success = 0 Then ErrorExit("Copy " & $MyCmdLines & " to " & $OemCmdLines & " failed", 3) + Else + ; A $oem$\cmdlines.txt already exists - append ours + Local $file1 = FileOpen($MyCmdLines, 0) ; 0 = read + If $file1 = -1 Then ErrorExit("Error opening " & $MyCmdLines, 5) + Local $file2 = FileOpen($OemCmdLines, 1) ; 1 = append + If $file2 = -1 Then ErrorExit("Error opening " & $OemCmdLines, 4) + While 1 + $line = FileReadLine($file1) + If @error Then ExitLoop + If StringStripWS($line, 8) <> "[commands]" Then ; StringStripWS($line,8) strips all white space + FileWriteLine($file2, $line) + EndIf + WEnd + FileClose($file1) + FileClose($file2) + EndIf + + LogFileContents($OemCmdLines, $OemCmdLines & " after merge:") + +EndFunc ;==>DoCmdLines + + +; =========================================================================================== +Func DoRunOnce() +; Run at deployment time if the $bRunonce is true. If there is a file called GuiRunOnce.ini in the drivers +; folder that we just copied, merge its GuiRunOnce section with the sysprep.inf GuiRunOnce section. The GuiRunOnce.ini file must be +; in the format as described in the sysprep documentation. Example: +; +; [GuiRunOnce] +; Command0="c:\drivers\driver1\setup.exe" +; Command1="c:\drivers\driver2\setup.exe" +; +; This program also has a GUI that allows GuiRunOnce.ini to be edited in a convenient way, without the user to be aware of the format or the location of the file. +; =========================================================================================== + + + Local $MyRunOnce = PathConcat($TargetFolder, "GuiRunOnce.ini") + + If Not FileExists($MyRunOnce) Then + LogMessage("File not found: " & $MyRunOnce) + Return + EndIf + + LogMessage("File exists: " & $MyRunOnce) + + LogIniSection($sysprep, "GuiRunOnce", "sysprep.inf [GuiRunOnce] section before merge:") + + If Not FileExists($sysprep) Then ErrorExit("File not found: " & $sysprep, 2) + Local $section1[1][1] + $section1[0][0] = 0 + $section1 = IniReadSection($sysprep, "GuiRunOnce") + If @error Then + Dim $section1[1][1] + $section1[0][0] = 0 + EndIf + Local $section2 = IniReadSection($MyRunOnce, "GuiRunOnce") + If @error Or $section2[0][0] = 0 Then + LogMessage("No [GuiRunOnce] section in " & $MyRunOnce) + Return + EndIf + + Local $count, $i + $count = $section1[0][0] + For $i = 1 To $section2[0][0] + $count = $count + 1 + ReDim $section1[$count + 1][2] + $section1[$count][0] = $section2[$i][0] + $section1[$count][1] = $section2[$i][1] + Next + $section1[0][0] = $count + For $i = 1 To $section1[0][0] + $section1[$i][0] = "Command" & ($i - 1) + Next + + IniWriteSection($sysprep, "GuiRunOnce", $section1) + + LogIniSection($sysprep, "GuiRunOnce", "sysprep.inf [GuiRunOnce] section after merge:") + + +EndFunc ;==>DoRunOnce + +; =========================================================================================== +; Wilcard match. Autoit has native support for regular expression matching, but not for wildcard matching. This function massages the pattern so it can +; be used as a regular expression. Copied from http://www.autoitscript.com/forum/index.php?showtopic=78620. +Func WildcardMatch($str, $pattern) +; =========================================================================================== + Local $sChar, $sChars = '\.+[^]$(){}=!<>|:' + For $i = 1 To StringLen($sChars) + $sChar = StringMid($sChars, $i, 1) + $pattern = StringReplace($pattern, $sChar, '\' & $sChar) + Next + $pattern = StringReplace($pattern, '?', '.{1}') + $pattern = StringReplace($pattern, '*', '.*') + Return StringRegExp($str, $pattern) +EndFunc ;==>WildcardMatch + + +; =========================================================================================== +; Set the 3 WMI attributes mentioned. We only use the Model, but feel free to organise things differently +Func ReadWmi(ByRef $Manufacturer, ByRef $Model, ByRef $Version) +; =========================================================================================== + + $objWMIService = ObjGet("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") + If $objWMIService = 0 Then ErrorExit("Failed to connect to WMI", 10) + + $colRows = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystem") + For $row In $colRows + $Manufacturer = StringStripWS($row.Manufacturer, 3) + $Model = StringStripWS($row.Model, 3) + Next + + $colRows = $objWMIService.ExecQuery("SELECT * FROM Win32_ComputerSystemProduct") + For $row In $colRows + $Version = StringStripWS($row.Version, 3) + Next + + Return True + +EndFunc ;==>ReadWmi + +; =========================================================================================== +Func Usage() +; =========================================================================================== + + MsgBox("0", $progname, _ + "This program copies machine specific drivers from a source folder on a" _ + & @CRLF & "server to a destination folder on the local machine." & @CRLF _ + & @CRLF & "Optional command line parameters:" _ + & @CRLF & " /s= : base path for machine specfic driver folders" _ + & @CRLF & " (overrides DriversSource in copydrivers.ini)" _ + & @CRLF & " /d= : target folder on the local machine." _ + & @CRLF & " (overrides DriversTarget in copydrivers.ini)" _ + & @CRLF & " /log= : log file." _ + & @CRLF & " /v : verbose" _ + & @CRLF & " /c : copy" _ + & @CRLF & "" _ + & @CRLF & "CopyDrivers requires a list that associates machine types with driver folders." _ + & @CRLF & "This list is to be supplied in the [Models] section of copydrivers.ini, which" _ + & @CRLF & "associates WMI model names with specific subfolders of ." & @CRLF _ + & @CRLF & "When invoked without command line switches, CopyDrivers opens a GUI that allows" _ + & @CRLF & "copydrivers.ini to be edited. Use /c to do the copying rather than show the GUI." _ + ) + + Exit 1 + +EndFunc ;==>Usage + +; =========================================================================================== +Func GetTime() +; =========================================================================================== + Local $s = @HOUR & ":" & @MIN & ":" & @SEC + return $s +EndFunc + +; =========================================================================================== +Func LogOpen(ByRef $logfilename) +; =========================================================================================== + + Local $scriptName = StringTrimRight(@ScriptName, 4) + While 1 + If $logfilename <> "" Then + ; log filename specified on command line + $log = FileOpen($logfilename, 10) ; 10 = 2 (write, create) + 8 (create path) + ExitLoop + EndIf + + ; No /log command line parameter. If there is a copydrivers.ini file with a DriversTarget parameter (typically c:\drivers), create the log in there + Local $iniFilename = PathConcat(@ScriptDir, "copydrivers.ini") + Local $DriverPath = IniRead($iniFilename, "Config", "DriversTarget", "") + if $DriverPath <> "" Then + $DriverPath = StringStripWS($DriverPath, 3) + if StringRight($DriverPath, 1) <> "\" Then $DriverPath &= "\" + $logfilename = $DriverPath & $scriptName & ".log" + $log = FileOpen($logfilename, 10) ; 10 = 2 (write, create) + 8 (create path) + if $log <> -1 Then ExitLoop + EndIf + + ; No /log command parameter and no copydrivers.ini. If running from a local path, create log in folder of running program + If Not IsRemote(@ScriptFullPath) Then + $logfilename = StringTrimRight(@ScriptFullPath, 3) & "log" + $log = FileOpen($logfilename, 2) + if $log <> -1 Then ExitLoop + EndIf + + ; failed to create log + $log = -1 + $logfilename = "" + return + Wend + + LogCmdLine() +EndFunc + +; =========================================================================================== +Func LogMessage($msg) +; =========================================================================================== + FileWriteLine($log, $msg) +EndFunc + +; =========================================================================================== +Func LogCmdLine() +; =========================================================================================== + Local $n + LogMessage($progname & ", command line parameter(s): " & $CmdLine[0]) + For $n = 1 to $CmdLine[0] + LogMessage(" " & $CmdLine[$n]) + Next +EndFunc + +; =========================================================================================== +Func LogIniSection($inifilename, $inisection, $msg = Default) +; =========================================================================================== + Local $i + if $msg = Default Then + LogMessage($inifilename & ",section [" & $inisection & "]:") + Else + LogMessage($msg) + EndIf + Local $section = IniReadSection($inifilename, $inisection) + if @error Then + if not FileExists($inifilename) Then + LogMessage(" File does not exist: " & $inifilename) + Return + EndIf + LogMessage(" " & $inifilename & " includes no [" & $inisection & "] section") + Return + EndIf + For $i = 1 to $section[0][0] + LogMessage(" " & $section[$i][0] & " = " & $section[$i][1]) + Next +EndFunc + +; =========================================================================================== +Func LogFileContents($filename, $msg = Default) +; =========================================================================================== + if $msg = Default Then + LogMessage($filename & ":") + Else + LogMessage($msg) + EndIf + Local $f = FileOpen($filename, 0) + if @error Then + if not FileExists($filename) Then + LogMessage(" File does not exist: " & $filename) + Return + EndIf + LogMessage(" Error opening " & $filename) + Return + EndIf + While 1 + Local $line = FileReadLine($f) + if @error Then ExitLoop + LogMessage(" " & $line) + WEnd + FileClose($f) +EndFunc + +; =========================================================================================== +; Return true if $s is a network path. Must be full path. +Func IsRemote($s) +; =========================================================================================== + If StringLeft($s, 2) = "\\" Then Return True + Local $drive = StringLeft($s, 3) + if DriveGetType($drive) = "Network" Then Return True + Return False +EndFunc + +; =========================================================================================== +; Return true if $s is a folder +Func IsFolder($s) +; =========================================================================================== + If Not FileExists($s) Or Not StringInStr(FileGetAttrib($s), "D") Then Return False + Return True +EndFunc + +; =========================================================================================== +; Concatenate a filename ($s) with a base path +Func PathConcat($base, $s) +; =========================================================================================== + $base = StringStripWS($base,3) + $s = StringStripWS($s,3) + if StringRight($base,1) <> "\" Then $base &= "\" + if StringLeft($s,1) = "\" Then $s = StringTrimLeft($s,1) + Return $base & $s +EndFunc + +; =========================================================================================== +; Return true if running under WinPE +Func IsWinPE() +; =========================================================================================== + If EnvGet("SystemDrive") = "X:" Then Return True + Return False +EndFunc + +; =========================================================================================== +Func ErrorExit($msg, $exitcode) +; =========================================================================================== + LogMessage($msg) + FileClose($log) + MsgBox(0x40010, $progname, $msg, 10) ; 10 is timeout, i.e. the msgbox closes after 10 seconds + Exit $exitcode +EndFunc + +; =========================================================================================== +; parse command line parameter such as /keyw=something. Examples: +; ValParam("/path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("-path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("/path=c:\temp", "dir", $value) sets $value to "" and returns False +Func ValParam($param, $keyword, ByRef $value) +; =========================================================================================== + $value = "" + Local $p1 = "/" & $keyword & "=" + Local $p2 = "-" & $keyword & "=" + Local $len = StringLen($p1) + if StringLen($param) < ($len + 1) Then Return False + Local $t = StringLeft($param, $len) + if ($t <> $p1) And ($t <> $p2) Then Return False + $value = StringMid($param, $len + 1) ; 1 based + Return True + +EndFunc + +#cs ----------------------------------------------------------------------------------------- + + Here comes the GUI stuff. It does nothing that you can't do by simply editing the CopyDrivers.ini file + +#ce ----------------------------------------------------------------------------------------- + +; =========================================================================================== +; Main GUI function called when program is invoked with no command line parameters +Func DoGui() +; =========================================================================================== + $iniFilename = @ScriptDir & "\copydrivers.ini" ; @ScriptDir is folder in which this script (or compiled program) resides + $SourceFolder = IniRead($iniFilename, "Config", "DriversSource", "") + $TargetFolder = IniRead($iniFilename, "Config", "DriversTarget", "") + + #Region ### START Koda GUI section ### Form=z:\install\autoit\koda_1.7.0.1\forms\myform1.kxf + $Form_Main = GUICreate($progname, 452, 322) + $BtnOK = GUICtrlCreateButton("OK", 16, 280, 97, 25, 0) + $EditSource = GUICtrlCreateInput("", 13, 32, 305, 21) + GUICtrlSetState(-1, $GUI_DISABLE) + $BtnConfig = GUICtrlCreateButton("Edit", 335, 32, 57, 21, 0) + $ListView1 = GUICtrlCreateListView("WMI Model|Subfolder", 13, 120, 305, 145) + GUICtrlSendMsg(-1, 0x101E, 0, 150) + GUICtrlSendMsg(-1, 0x101E, 1, 150) + ; GUICtrlSetTip(-1, "abc") + $BtnAdd = GUICtrlCreateButton("Add", 335, 126, 57, 21, 0) + $BtnEdit = GUICtrlCreateButton("Edit", 335, 157, 57, 21, 0) + $BtnDelete = GUICtrlCreateButton("Delete", 335, 190, 57, 21, 0) + GUICtrlCreateLabel("Drivers source folder", 16, 14, 101, 17) + $BtnCancel = GUICtrlCreateButton("Cancel", 133, 281, 97, 25, 0) + $EditTarget = GUICtrlCreateInput("", 13, 79, 305, 21) + GUICtrlSetState(-1, $GUI_DISABLE) + GUICtrlCreateLabel("Drivers target folder", 16, 61, 96, 17) + GUISetState(@SW_SHOW) + #EndRegion ### END Koda GUI section ### + + GUICtrlSetData($EditSource, $SourceFolder) + GUICtrlSetData($EditTarget, $TargetFolder) + + ;IniReadSection returns a 2 dimensional array of keywords and values; $ini[n][0] is key # n, $ini[n][1] is value # n; $ini[0][0] is the number of elements + $items = 0 + $count = 0 + $ini = IniReadSection($iniFilename, "Models") + If Not @error Then + $items = $ini[0][0] + EndIf + + $count1 = $items + If ($items = 0) Then $count1 = 1 + + Dim $item[$count1][4] ; we'll store the model in item[n][0], the folder in item[n][1], the listview controlid in item[n][2] and the state (0 = deleted, 1 = active) in item[n][3] + If $items = 0 Then + ; if the section was empty or non-existing, we create one dummy item to avoid run-time errors + $item[0][0] = "" + $item[0][1] = "" + $item[0][2] = 0 + $item[0][3] = 0 + EndIf + + For $n = 1 To $items + $item[$n - 1][0] = $ini[$n][0] + $item[$n - 1][1] = $ini[$n][1] + $item[$n - 1][2] = GUICtrlCreateListViewItem($ini[$n][0] & "|" & $ini[$n][1], $ListView1) + $item[$n - 1][3] = 1 + $count = $count + 1 + Next + + While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Exit + Case $BtnOK + IniWrite($iniFilename, "Config", "DriversSource", $SourceFolder) + IniWrite($iniFilename, "Config", "DriversTarget", $TargetFolder) + Dim $ini[$count][2] + $i = 0 + For $n = 0 To UBound($item) - 1 + If $item[$n][3] = 1 Then + $ini[$i][0] = $item[$n][0] + $ini[$i][1] = $item[$n][1] + $i = $i + 1 + EndIf + Next + IniWriteSection($iniFilename, "Models", $ini, 0) + Exit + Case $BtnCancel + Exit + Case $BtnConfig + $newSource = $SourceFolder + $newTarget = $TargetFolder + If EditConfig($newSource, $newTarget) Then + $SourceFolder = $newSource + $TargetFolder = $newTarget + GUICtrlSetData($EditSource, $SourceFolder) + GUICtrlSetData($EditTarget, $TargetFolder) + EndIf + Case $BtnDelete + $id = GUICtrlRead($ListView1) + For $n = 0 To UBound($item) - 1 + If $item[$n][2] = $id And $item[$n][3] = 1 Then + GUICtrlDelete($id) + $item[$n][3] = 0 + $count = $count - 1 + EndIf + Next + Case $BtnAdd + Dim $newModel = "" + Dim $newFolder = "" + If AddModel($newModel, $newFolder, 0) Then + $n = UBound($item); + ReDim $item[$n + 1][4] + $item[$n][0] = $newModel + $item[$n][1] = $newFolder + $item[$n][2] = GUICtrlCreateListViewItem($newModel & "|" & $newFolder, $ListView1) + $item[$n][3] = 1 + $count = $count + 1 + EndIf + Case $BtnEdit + $id = GUICtrlRead($ListView1) + For $n = 0 To UBound($item) - 1 + If $item[$n][2] = $id And $item[$n][3] = 1 Then + ExitLoop + EndIf + Next + If $n >= UBound($item) Then ContinueLoop + Dim $newModel = $item[$n][0] + Dim $newFolder = $item[$n][1] + If AddModel($newModel, $newFolder, 1) Then + $item[$n][0] = $newModel + $item[$n][1] = $newFolder + GUICtrlSetData($id, $newModel & "|" & $newFolder) + EndIf + + EndSwitch + WEnd + + +EndFunc ;==>DoGui + +; =========================================================================================== +; GUI function called when the Add or Edit button is pressed. +Func AddModel(ByRef $Model, ByRef $folder, $flag) ; flag = 0: Add flag = 1: Edit +; =========================================================================================== + + $title = "Add Model" + If $flag = 1 Then $title = "Edit Model" + + #Region ### START Koda GUI section ### Form=Z:\install\AutoIt\koda_1.7.0.1\Forms\Form_AddItem.kxf + $Form_AddModel = GUICreate($title, 429, 413) + GUICtrlCreateGroup("", 8, 1, 297, 137) + $InputModel = GUICtrlCreateInput("", 16, 40, 209, 21) + $InputFolder = GUICtrlCreateInput("", 16, 97, 209, 21, BitOR($ES_AUTOHSCROLL, $ES_READONLY)) + GUICtrlCreateLabel("Model", 16, 16, 33, 17) + GUICtrlCreateLabel("Subfolder", 17, 73, 49, 17) + $Btn_WMI = GUICtrlCreateButton("WMI", 236, 40, 57, 21, 0) + $BtnBrowse = GUICtrlCreateButton("..", 236, 97, 57, 21, 0) + $CmdLines = GUICtrlCreateEdit("", 16, 192, 385, 81, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_HSCROLL, $WS_VSCROLL, $WS_BORDER), $ES_MULTILINE) + $ButtonOK = GUICtrlCreateButton("&OK", 321, 11, 75, 25, 0) + $ButtonCancel = GUICtrlCreateButton("&Cancel", 322, 43, 75, 25, 0) + $RunOnce = GUICtrlCreateEdit("", 16, 304, 385, 81, BitOR($ES_AUTOVSCROLL, $ES_AUTOHSCROLL, $ES_WANTRETURN, $WS_HSCROLL, $WS_VSCROLL, $WS_BORDER), $ES_MULTILINE) + GUICtrlCreateGroup("Command lines for drivers that require a setup program", 8, 152, 409, 249) + GUICtrlCreateLabel("Before reboot (cmdlines.txt)", 16, 174, 200, 17) + GUICtrlCreateLabel("After reboot (GuiRunonce section of sysprep.inf)", 16, 287, 300, 17) + GUISetState(@SW_SHOW) + #EndRegion ### END Koda GUI section ### + + GUICtrlSetData($InputModel, $Model) + GUICtrlSetData($InputFolder, $folder) + + ; If the model specific folder exists, read the cmdlines.txt and GuiRunOnce.txt files from it and display their contents in the $cmdlines and $RunOnce edit boxes. + ; If the model specific folder does not exist, disable the edit boxes + + $RunOnceText = "" + $CmdLinesText = "" + + $ModelFolder = $SourceFolder & "\" & $folder + If $SourceFolder = "" Or $folder = "" Then $ModelFolder = "---dummy---" + If IsFolder($ModelFolder) Then + $CmdLinesText = ReadCmdLines($ModelFolder) + GUICtrlSetData($CmdLines, $CmdLinesText) + $RunOnceText = ReadRunOnce($ModelFolder) + GUICtrlSetData($RunOnce, $RunOnceText) + Else + GUICtrlSetState($CmdLines, $GUI_DISABLE) + GUICtrlSetState($RunOnce, $GUI_DISABLE) + EndIf + + While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Return False + Case $ButtonCancel + GUIDelete($Form_AddModel) + Return False + Case $BtnBrowse + $flag = 1 + If IsWinPE() Then $flag = 0 + $old = $SourceFolder + "\" + GUICtrlRead($InputFolder) + $new = FileSelectFolder("Select Folder", $SourceFolder, $flag, $ModelFolder) ; $flag = 1 : Show Create Folder Button (does not work in WinPE) + If $new <> "" Then + $new = StringMid($new, StringLen($SourceFolder) + 2) + GUICtrlSetData($InputFolder, $new) + EndIf + $ModelFolder = $SourceFolder & "\" & $new + If $SourceFolder = "" Or $new = "" Then $ModelFolder = "---dummy---" + If IsFolder($ModelFolder) Then + ; User selected a new model specific folder - and the folder exists. Read the cmdlines.txt and GuiRunOnce.txt files from it and display their contents in the + ; $cmdlines and $RunOnce edit boxes. + GUICtrlSetState($CmdLines, $GUI_ENABLE) + GUICtrlSetState($RunOnce, $GUI_ENABLE) + $CmdLinesText = ReadCmdLines($ModelFolder) + $RunOnceText = ReadRunOnce($ModelFolder) + Else + ; User selected a new model specific folder - and the folder does not exist. Disable the $cmdlines and $RunOnce edit boxes. + GUICtrlSetState($CmdLines, $GUI_DISABLE) + GUICtrlSetState($RunOnce, $GUI_DISABLE) + $CmdLinesText = "" + $RunOnceText = "" + EndIf + GUICtrlSetData($CmdLines, $CmdLinesText) + GUICtrlSetData($RunOnce, $RunOnceText) + Case $Btn_WMI + ReadWmi($Manufacturer, $Model, $Version) + GUICtrlSetData($InputModel, $Model) + Case $ButtonOK + $Model = StringStripWS(GUICtrlRead($InputModel), 3) + $folder = StringStripWS(GUICtrlRead($InputFolder), 3) + If $Model = "" Then + MsgBox(0, $progname, "A model is required") + ElseIf $folder = "" Then + MsgBox(0, $progname, "A folder is required") + Else + $newCmdLinesText = GUICtrlRead($CmdLines) + $newRunOnceText = GUICtrlRead($RunOnce) + GUIDelete($Form_AddModel) + If IsFolder($ModelFolder) Then + If $newCmdLinesText <> $CmdLinesText Then SaveCmdLines($ModelFolder, $newCmdLinesText) + If $newRunOnceText <> $RunOnceText Then SaveRunOnce($ModelFolder, $newRunOnceText) + EndIf + Return True + EndIf + EndSwitch + WEnd + +EndFunc ;==>AddModel + +; =========================================================================================== +; GUI function to edit the Source Folder and target folder settings +Func EditConfig(ByRef $source, ByRef $target) +; =========================================================================================== + + #Region ### START Koda GUI section ### Form=Z:\install\AutoIt\koda_1.7.0.1\Forms\Form_Config.kxf + $Form_Config = GUICreate("Edit Config", 316, 197) + ; GUISetIcon("D:\003.ico") + GUICtrlCreateGroup("", 8, 1, 297, 153) + $EditSource = GUICtrlCreateInput("", 16, 38, 217, 21) + $EditTarget = GUICtrlCreateInput("", 16, 110, 217, 21) + GUICtrlCreateLabel("Drivers Source Folder (Specify UNC path)", 16, 16, 200, 17) + GUICtrlCreateLabel("DriversTarget Folder", 16, 87, 100, 17) + $BtnBrowse = GUICtrlCreateButton("..", 244, 38, 57, 21, 0) + GUICtrlCreateGroup("", -99, -99, 1, 1) + $BtnOK = GUICtrlCreateButton("&OK", 65, 163, 75, 25, 0) + $BtnCancel = GUICtrlCreateButton("&Cancel", 162, 163, 75, 25, 0) + GUISetState(@SW_SHOW) + #EndRegion ### END Koda GUI section ### + + GUICtrlSetData($EditSource, $source) + GUICtrlSetData($EditTarget, $target) + + While 1 + $nMsg = GUIGetMsg() + Switch $nMsg + Case $GUI_EVENT_CLOSE + Return False + Case $BtnCancel + GUIDelete($Form_Config) + Return False + Case $BtnOK + $source = StringStripWS(GUICtrlRead($EditSource), 3) + $target = StringStripWS(GUICtrlRead($EditTarget), 3) + If $source = "" Then + MsgBox(0, $progname, "A source folder is required") + Else + GUIDelete($Form_Config) + Return True + EndIf + Case $BtnBrowse + $new = FileSelectFolder("Select Source Folder", "", 0, $source) + $new = StringStripWS($new, 3) + GUICtrlSetData($EditSource, $new) + If $new <> "" Then $source = $new + EndSwitch + WEnd + +EndFunc ;==>EditConfig + +; =========================================================================================== +; Used by GUI to read cmdlines.txt from specified folder. The data is returned in a format ready to be fed into a GUI edit box +; (lines separated by CR-LF). The header line ([Commands]) is not included in the data. +Func ReadCmdLines($folder) +; =========================================================================================== + Local $retstring = "" + Local $filename = $folder & "\cmdlines.txt" + Local $lineno = 0 + Local $file = FileOpen($filename, 0) ; 0 = read + If $file = -1 Then Return "" + + Local $line + While 1 + $line = FileReadLine($file) + If @error Then ExitLoop + If StringStripWS($line, 8) = "[commands]" Then ContinueLoop ; StringStripWS($line,8) strips all white space + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + If $line = "" Then ContinueLoop + If StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + If $line = "" Then ContinueLoop + If $lineno > 0 Then $retstring = $retstring & @CRLF + $lineno = $lineno + 1 + $retstring = $retstring & $line + WEnd + + FileClose($file) + Return $retstring + +EndFunc ;==>ReadCmdLines + +; =========================================================================================== +; Used by GUI to read GuiRunOnce.ini from specified folder. The data is returned in a format ready to be fed into a GUI edit box +; (lines separated by CR-LF). The header line ([GuiRunOnce]) is not included in the data, nor are the CommandN= prefixes. +Func ReadRunOnce($folder) +; =========================================================================================== + Local $retstring = "" + Local $filename = $folder & "\GuiRunOnce.ini" + Local $lineno = 0 + Local $lines = IniReadSection($filename, "GuiRunOnce") + If @error Then Return "" + + Local $i, $line + For $i = 1 To $lines[0][0] + $line = $lines[$i][1] + If $line = "" Then ContinueLoop + If StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + If $line = "" Then ContinueLoop + If $lineno > 0 Then $retstring = $retstring & @CRLF + $lineno = $lineno + 1 + $retstring = $retstring & $line + Next + + Return $retstring + +EndFunc ;==>ReadRunOnce + +; =========================================================================================== +; Used by GUI to save cmdlines.txt in specified folder. The input data ($text) is the raw data as read from the GUI edit control. The header line ([Commands]) is not expected to +; be included in the input data. +Func SaveCmdLines($folder, $text) +; =========================================================================================== + If Not IsFolder($folder) Then DirCreate($folder) + Local $filename = $folder & "\cmdlines.txt" + Local $file = FileOpen($filename, 2) ; 2 = create + $text = StringReplace($text, @LF, "") + Local $lineno = 0 + Local $lines = StringSplit($text, @CR) + Local $i, $line + For $i = 1 To $lines[0] + $line = StringReplace($lines[$i], @LF, "") + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + If $line = "" Then ContinueLoop + If StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = '"' & $line & '"' + If $lineno = 0 Then FileWriteLine($file, "[Commands]") + $lineno = $lineno + 1 + FileWriteLine($file, $line) + Next + FileClose($file) + If $lineno = 0 Then FileDelete($filename) + +EndFunc ;==>SaveCmdLines + +; =========================================================================================== +; Used by GUI to save GuiRunOnce.ini in specified folder. The input data ($text) is the raw data as read from the GUI edit control. The header line ([GuiRunOnce]) is not expected to +; be included in the input data, nor are the "CommandN=" prefixes. +Func SaveRunOnce($folder, $text) +; =========================================================================================== + If Not IsFolder($folder) Then DirCreate($folder) + Local $filename = $folder & "\GuiRunOnce.ini" + Local $file = FileOpen($filename, 2) ; 2 = create + $text = StringReplace($text, @LF, "") + Local $lineno = 0 + Local $lines = StringSplit($text, @CR) + Local $i, $line + For $i = 1 To $lines[0] + $line = StringReplace($lines[$i], @LF, "") + $line = StringStripWS($line, 3) ; 3 = strip leading & trailing while space + If $line = "" Then ContinueLoop + If StringLeft($line, 1) = '"' And StringRight($line, 1) = '"' Then + $line = StringTrimLeft($line, 1) + $line = StringTrimRight($line, 1) + EndIf + $line = 'Command' & $lineno & '="' & $line & '"' + If $lineno = 0 Then FileWriteLine($file, "[GuiRunOnce]") + $lineno = $lineno + 1 + FileWriteLine($file, $line) + Next + FileClose($file) + If $lineno = 0 Then FileDelete($filename) + +EndFunc ;==>SaveRunOnce + +#cs ----------------------------------------------------------------------------------------- + End of GUI stuff. +#ce ----------------------------------------------------------------------------------------- + +#cs ----------------------------------------------------------------------------------------- + Copy with Progress Bar. Copied from from http://www.autoitscript.com/forum/index.php?showtopic=11313 +#ce ----------------------------------------------------------------------------------------- + +; =========================================================================================== +Func _CopyDirWithProgress($sOriginalDir, $sDestDir) +; =========================================================================================== + ;$sOriginalDir and $sDestDir are quite selfexplanatory... + ;This func returns: + ; -1 in case of critical error, bad original or destination dir + ; 0 if everything went all right + ; >0 is the number of file not copied and it makes a log file + ; if in the log appear as error message '0 file copied' it is a bug of some windows' copy command that does not redirect output... + + If StringRight($sOriginalDir, 1) <> '\' Then $sOriginalDir = $sOriginalDir & '\' + If StringRight($sDestDir, 1) <> '\' Then $sDestDir = $sDestDir & '\' + If $sOriginalDir = $sDestDir Then Return -1 + + ProgressOn('Copying Drivers...', 'Building list of files...' & @LF & @LF, '', -1, -1, 18) + Local $aFileList = _FileSearch($sOriginalDir) + If $aFileList[0] = 0 Then + ProgressOff() + SetError(1) + Return -1 + EndIf + + If FileExists($sDestDir) Then + If Not StringInStr(FileGetAttrib($sDestDir), 'd') Then + ProgressOff() + SetError(2) + Return -1 + EndIf + Else + DirCreate($sDestDir) + If Not FileExists($sDestDir) Then + ProgressOff() + SetError(2) + Return -1 + EndIf + EndIf + + Local $iDirSize, $iCopiedSize = 0, $fProgress = 0 + Local $c, $filename, $iOutPut = 0, $sLost = '', $sError + Local $Sl = StringLen($sOriginalDir) + + _Quick_Sort($aFileList, 1, $aFileList[0]) + + $iDirSize = Int(DirGetSize($sOriginalDir) / 1024) + + ProgressSet(Int($fProgress * 100), $aFileList[$c], 'Copying file:') + For $c = 1 To $aFileList[0] + $filename = StringTrimLeft($aFileList[$c], $Sl) + ProgressSet(Int($fProgress * 100), $aFileList[$c] & ' -> ' & $sDestDir & $filename & @LF & 'Total KB: ' & $iDirSize & @LF & 'Done KB: ' & $iCopiedSize, 'Coping file: ' & Round($fProgress * 100, 2) & ' % ' & $c & '/' & $aFileList[0]) + + If StringInStr(FileGetAttrib($aFileList[$c]), 'd') Then + DirCreate($sDestDir & $filename) + Else + If Not FileCopy($aFileList[$c], $sDestDir & $filename, 1) Then + If Not FileCopy($aFileList[$c], $sDestDir & $filename, 1) Then ;Tries a second time + If RunWait(@ComSpec & ' /c copy /y "' & $aFileList[$c] & '" "' & $sDestDir & $filename & '">' & @TempDir & '\o.tmp', '', @SW_HIDE) = 1 Then ; and a third time, but this time it takes the error message + $sError = FileReadLine(@TempDir & '\o.tmp', 1) + $iOutPut = $iOutPut + 1 + $sLost = $sLost & $aFileList[$c] & ' ' & $sError & @CRLF + EndIf + FileDelete(@TempDir & '\o.tmp') + EndIf + EndIf + + FileSetAttrib($sDestDir & $filename, "+A-RSH");<- Comment this line if you do not want attribs reset. + + $iCopiedSize = $iCopiedSize + Int(FileGetSize($aFileList[$c]) / 1024) + $fProgress = $iCopiedSize / $iDirSize + EndIf + Next + + ProgressOff() + + If $sLost <> '' Then;tries to write the log somewhere. + If FileWrite($sDestDir & 'notcopied.txt', $sLost) = 0 Then + If FileWrite($sOriginalDir & 'notcopied.txt', $sLost) = 0 Then + FileWrite(@WorkingDir & '\notcopied.txt', $sLost) + EndIf + EndIf + EndIf + + Return $iOutPut +EndFunc ;==>_CopyDirWithProgress + +; =========================================================================================== +Func _FileSearch($sIstr, $bSF = 1) +; =========================================================================================== + ; $bSF = 1 means looking in subfolders + ; $sSF = 0 means looking only in the current folder. + ; An array is returned with the full path of all files found. The pos [0] keeps the number of elements. + Local $sCriteria, $sBuffer, $iH, $iH2, $sCS, $sCF, $sCF2, $sCP, $sFP, $sOutPut = '', $aNull[1] + $sCP = StringLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) + If $sCP = '' Then $sCP = @WorkingDir & '\' + $sCriteria = StringTrimLeft($sIstr, StringInStr($sIstr, '\', 0, -1)) + If $sCriteria = '' Then $sCriteria = '*.*' + + ;To begin we seek in the starting path. + $sCS = FileFindFirstFile($sCP & $sCriteria) + If $sCS <> -1 Then + Do + $sCF = FileFindNextFile($sCS) + If @error Then + FileClose($sCS) + ExitLoop + EndIf + If $sCF = '.' Or $sCF = '..' Then ContinueLoop + $sOutPut = $sOutPut & $sCP & $sCF & @LF + Until 0 + EndIf + + ;And after, if needed, in the rest of the folders. + If $bSF = 1 Then + $sBuffer = @CR & $sCP & '*' & @LF;The buffer is set for keeping the given path plus a *. + Do + $sCS = StringTrimLeft(StringLeft($sBuffer, StringInStr($sBuffer, @LF, 0, 1) - 1), 1);current search. + $sCP = StringLeft($sCS, StringInStr($sCS, '\', 0, -1));Current search path. + $iH = FileFindFirstFile($sCS) + If $iH <> -1 Then + Do + $sCF = FileFindNextFile($iH) + If @error Then + FileClose($iH) + ExitLoop + EndIf + If $sCF = '.' Or $sCF = '..' Then ContinueLoop + If StringInStr(FileGetAttrib($sCP & $sCF), 'd') Then + $sBuffer = @CR & $sCP & $sCF & '\*' & @LF & $sBuffer;Every folder found is added in the begin of buffer + $sFP = $sCP & $sCF & '\'; for future searches + $iH2 = FileFindFirstFile($sFP & $sCriteria); and checked with the criteria. + If $iH2 <> -1 Then + Do + $sCF2 = FileFindNextFile($iH2) + If @error Then + FileClose($iH2) + ExitLoop + EndIf + If $sCF2 = '.' Or $sCF2 = '..' Then ContinueLoop + $sOutPut = $sOutPut & $sFP & $sCF2 & @LF;Found items are put in the Output. + Until 0 + EndIf + EndIf + Until 0 + EndIf + $sBuffer = StringReplace($sBuffer, @CR & $sCS & @LF, '') + Until $sBuffer = '' + EndIf + + If $sOutPut = '' Then + $aNull[0] = 0 + Return $aNull + Else + Return StringSplit(StringTrimRight($sOutPut, 1), @LF) + EndIf +EndFunc ;==>_FileSearch + +; =========================================================================================== +Func _Quick_Sort(ByRef $SortArray, $First, $Last);Larry's code +; =========================================================================================== + Local $Low, $High + Local $Temp, $List_Separator + + $Low = $First + $High = $Last + $List_Separator = StringLen($SortArray[($First + $Last) / 2]) + Do + While (StringLen($SortArray[$Low]) < $List_Separator) + $Low = $Low + 1 + WEnd + While (StringLen($SortArray[$High]) > $List_Separator) + $High = $High - 1 + WEnd + If ($Low <= $High) Then + $Temp = $SortArray[$Low] + $SortArray[$Low] = $SortArray[$High] + $SortArray[$High] = $Temp + $Low = $Low + 1 + $High = $High - 1 + EndIf + Until $Low > $High + If ($First < $High) Then _Quick_Sort($SortArray, $First, $High) + If ($Low < $Last) Then _Quick_Sort($SortArray, $Low, $Last) +EndFunc ;==>_Quick_Sort diff --git a/Tools/Landesk_Autoit/CopyDrivers.exe b/Tools/Landesk_Autoit/CopyDrivers.exe new file mode 100644 index 0000000..fe18753 Binary files /dev/null and b/Tools/Landesk_Autoit/CopyDrivers.exe differ diff --git a/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.chm b/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.chm new file mode 100644 index 0000000..791bb1e Binary files /dev/null and b/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.chm differ diff --git a/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.exe b/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.exe new file mode 100644 index 0000000..b62e60b Binary files /dev/null and b/Tools/Landesk_Autoit/HttpCopyV362/HttpCopy.exe differ diff --git a/Tools/Landesk_Autoit/HttpCopyV362/hcmkdiff.exe b/Tools/Landesk_Autoit/HttpCopyV362/hcmkdiff.exe new file mode 100644 index 0000000..8a67d79 Binary files /dev/null and b/Tools/Landesk_Autoit/HttpCopyV362/hcmkdiff.exe differ diff --git a/Tools/Landesk_Autoit/HttpCopyV362/libdf.dll b/Tools/Landesk_Autoit/HttpCopyV362/libdf.dll new file mode 100644 index 0000000..c1e3ab8 Binary files /dev/null and b/Tools/Landesk_Autoit/HttpCopyV362/libdf.dll differ diff --git a/Tools/Landesk_Autoit/HttpCopyV362/libdfp.dll b/Tools/Landesk_Autoit/HttpCopyV362/libdfp.dll new file mode 100644 index 0000000..c291976 Binary files /dev/null and b/Tools/Landesk_Autoit/HttpCopyV362/libdfp.dll differ diff --git a/Tools/Landesk_Autoit/InjectMsd.au3 b/Tools/Landesk_Autoit/InjectMsd.au3 new file mode 100644 index 0000000..1e0335f --- /dev/null +++ b/Tools/Landesk_Autoit/InjectMsd.au3 @@ -0,0 +1,385 @@ +#Region ;**** Directives created by AutoIt3Wrapper_GUI **** +#AutoIt3Wrapper_Res_Comment=This program injects a mass storage driver previously captured by CaptureMsd +#AutoIt3Wrapper_Res_Description=InjectMsd +#AutoIt3Wrapper_Res_Fileversion=1.1 +#AutoIt3Wrapper_Res_LegalCopyright=Copyright LANDesk Software +#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** +#cs ---------------------------------------------------------------------------- + + InjectMsd Version 1.0.1 08 Dec 2008 + AutoIt Version: 3.2.12.1 + Author: Jan Buelens, Landesk Software + + Script Function: + Inject a mass storage driver into a freshly restored image. Context: we are still running under WinPE. The target machine has just been restored + from an image. We are about to reboot the target into mini-setup. But before the target reboots, we need to inject the correct mass storage sriver into + it. + + This script expects a path as a command line parameter. Within that path, there should be following: + -1- A .inf and a .sys file, to be copied to c:\Windows\inf and c:\Windows\System32\drivers respectively + -2- A subfolder called "windows", to be copied recursively to c:\windows. This subfolder contains any additional files to be injected, e.g. DLLs. + There is a redundancy here (the .sys and .inf could just as well be in this subfolder), but item -1- above is still believed to be convenient. + -3- One or more .reg files. These were probably exported from a working machine using the same mass storage driver. Typically, two .reg files + will be needed. One to describe the "service" under HKLM\CurrentControlSet\Services. A second one to describe the driver's subkey under + HKLM\CurrentControlSet\Control\CriticalDeviceDatabase. + The script imports these .reg files into the target system's registry. + + The path passed as a command line parameter must have write access because -1- the program will make a temp copy of the .reg files it finds, -2- the + program will create a log file called injectmsd.log. + + + If something goes wrong, the script returns a non-zero exit code. There will also be a message box that goes away after 10 seconds. + + Change history: + V1.0.1 (08 Dec 08). In addition to HKLM\Software and HKLM\System, a .reg file can now also write to the target's HKEY_USERS\.Default. + v1.1 (07 July 09). The msd folder is no longer required as a command line parameter if a copydrivers.ini file (with a DriversTarget parameter in it) + is present in the folder from which this program is running. If copydrivers.ini has the "typical" DriversTarget path of c:\drivers, InjectMsd will + default to c:\drivers\msd. Non-existence of this folder will not be considered an error (exit code 0). If an msdfolder is specified on the command + line, however, it is required to exist. + The log file is in a different place than before (c:\drivers if that's what's in copydrivers.ini/DriversTarget). + + +#ce ---------------------------------------------------------------------------- + + +#Include + +$progname = "InjectMsd V1.1" +Dim $logfilename = "" ; log file (from /log command line parameter) +Dim $log = -1 + + +Dim $MsdFolder = "" + +; =========================================================================================== +; Validate command line parameters. There should be one command line parameter = base folder +; =========================================================================================== + +For $n = 1 to $CmdLine[0] + $s = "" + $c = StringLeft($CmdLine[$n],1) + if $n = 1 And $c <> "/" And $c <> "-" Then + $MsdFolder = $CmdLine[1] + ElseIf ValParam($CmdLine[$n], "log", $s) Then + $logfilename = $s + Else + Usage() + EndIf +Next + +LogOpen($logfilename) + +if $MsdFolder = "" Then + ; If no folder was specified on the command line, see if there is a copydrivers.ini with a DriversTarget parameter and default to msd subfolder off it. + ; Example: if DriversTarget has its typical value of c:\drivers, default to c:\drivers\msd. If that folder does not exist, don't complain - this may be + ; a normal case of a machine type that does not require an msd folder + $iniFilename = PathConcat(@ScriptDir, "copydrivers.ini") ; @ScriptDir is folder in which this script (or compiled program) resides + LogIniSection($iniFilename, "Config") + if FileExists($iniFilename) Then + $DriverPath = IniRead($iniFilename, "Config", "DriversTarget", "") ; normally c:\drivers + if $DriverPath <> "" Then + $MsdFolder = PathConcat($DriverPath, "msd") + if not IsFolder($MsdFolder) Then + LogMessage("Default msd folder (" & $MsdFolder & ") does not exist. No work to do - exiting") + Exit 0 + EndIf + EndIf + EndIf +EndIf + +if $MsdFolder = "" Then + ; No msd folder was specified on the command line and we couldn't take a default from copydrivers.ini. Complain. + Usage() +EndIf + +; If we defaulted the msdfolder based on DriversTarget in copydrivers.ini, we have already exited with a zero return code if the folder doesn't exist. +; But if an msdfolder was specified on the command line and it doesn't exist, we still complain. +if not IsFolder($MsdFolder) Then ErrorExit("Folder " & $MsdFolder & " does not exist.", 2) + + +; =========================================================================================== +; If there is a subfolder called windows, copy it to c:\Windows +; =========================================================================================== + +CopyWindows() ; Copy Windows subfolder if any to C:\Windows + +; =========================================================================================== +; Find .inf and .sys files and copy to C:\Windows\Inf and c:\windows\system32\drivers respectively. This +; is strictly speaking redundant since same can be achieved using CopyWindows. But is probably convenient. +; =========================================================================================== + +$search = FileFindFirstFile(PathConcat($MsdFolder, "*.inf")) +While 1 + $file = FileFindNextFile($search) + If @error Then ExitLoop + LogMessage("Copying " & $file & " to c:\windows\inf\") + FileCopy(PathConcat($MsdFolder, $file), "c:\windows\inf\", 1) ; 1 = overwrite + If @error Then LogMessage("Copy of " & $file & " failed") +WEnd +FileClose($search) ; Close the search handle + +$search = FileFindFirstFile(PathConcat($MsdFolder, "*.sys")) +While 1 + $file = FileFindNextFile($search) + If @error Then ExitLoop + LogMessage("Copying " & $file & " to c:\windows\system32\drivers\") + FileCopy(PathConcat($MsdFolder, $file), "c:\windows\system32\drivers\", 1) ; 1 = overwrite + If @error Then LogMessage("Copy of " & $file & " failed") +WEnd +FileClose($search) ; Close the search handle + +; =========================================================================================== +; Find .reg files. For each .reg file, call ProcessReg. +; =========================================================================================== + +$search = FileFindFirstFile(PathConcat($MsdFolder, "*.reg")) +While 1 + $file = FileFindNextFile($search) + If @error Then ExitLoop + LogMessage("Processing " & $file) + ProcessReg(PathConcat($MsdFolder, $file)) +WEnd +FileClose($search) ; Close the search handle + +; =========================================================================================== +; Done +; =========================================================================================== + + + +; =========================================================================================== +; If the folder that we got as a command line parameter has a subfolder called "windows", then xcopy it to C:\Windows +Func CopyWindows() +; =========================================================================================== + Local $SourceFolder = PathConcat($MsdFolder, "Windows") + Local $TargetFolder = "C:\Windows" + if Not IsFolder($SourceFolder) Then Return False + LogMessage("Copying " & $MsdFolder & "\Windows to c:\windows") + DirCreate($TargetFolder) + If Not IsFolder($TargetFolder) Then ErrorExit("Unable to create target folder: " & $TargetFolder, 6) + If Not DirCopy($SourceFolder, $TargetFolder, 1) Then ErrorExit("Unable to copy folder: " & $TargetFolder, 7) ; 1 means overwrite existing files + Return True +EndFunc + +; =========================================================================================== +; Import a .reg file into the target's registry. Make a temp copy of the .reg file (called .reg1), with modified registry key names. We need to modify +; the registry key names because e.g. HKLM\System refers to the WinPE registry. We change HKLM\System to HKLM\System1 and HKLM\Software to HKLM\Software1. +; We also need to change CurrentControlSet to ControlSet001 because CurrentControlSet is an alias that only exists in the running system, not in the target's +; System hive on disk. +; We then use the REG LOAD command to mount the target system's HKLM\System registry hive as HKLM\System1 and HKLM\Software as HKLM\Software1. After that, +; we can use the REG IMPORT command to import the modified .reg file into the target's registry. +Func ProcessReg($file) +; =========================================================================================== + $tempfile = $file & "1" + + LogMessage("Making temp copy of " & $file & ", the copy is called " & $tempfile) + FileCopy($file, $tempfile, 1) ; 1 = overwrite + if @error then ErrorExit("Unable to create " & $tempfile, 8) + if not FileExists($tempfile) then ErrorExit("Unable to create " & $tempfile, 9) + LogMessage("Editing " & $tempfile & ", replacing registry root key names") + $count1 = _ReplaceStringInFile($tempfile, "HKEY_LOCAL_MACHINE\System", "HKEY_LOCAL_MACHINE\System1") + $count2 = _ReplaceStringInFile($tempfile, "System1\CurrentControlSet", "System1\ControlSet001") + $count3 = _ReplaceStringInFile($tempfile, "HKEY_LOCAL_MACHINE\Software", "HKEY_LOCAL_MACHINE\Software1") + $count4 = _ReplaceStringInFile($tempfile, "HKEY_USERS\.DEFAULT", "HKEY_LOCAL_MACHINE\Default1") + + if $count1 > 0 Then + if not FileExists("c:\windows\system32\config\system") Then ErrorExit("File not found: c:\windows\system32\config\system", 10) + RunCommand("reg load HKLM\System1 c:\windows\system32\config\system") + if not HasSubKey("HKLM\System1") Then ErrorExit("Something went wrong loading target's HKLM\System", 11) + EndIf + if $count3 > 0 Then + if not FileExists("c:\windows\system32\config\software") Then ErrorExit("File not found: c:\windows\system32\config\software", 12) + RunCommand("reg load HKLM\Software1 c:\windows\system32\config\software") + if not HasSubKey("HKLM\Software1") Then ErrorExit("Something went wrong loading target's HKLM\Software", 13) + EndIf + if $count4 > 0 Then + if not FileExists("c:\windows\system32\config\default") Then ErrorExit("File not found: c:\windows\system32\config\default", 12) + RunCommand("reg load HKLM\Default1 c:\windows\system32\config\default") + if not HasSubKey("HKLM\Default1") Then ErrorExit("Something went wrong loading target's HKEY_USERS\.DEFAULT", 13) + EndIf + + RunCommand("reg import " & $tempfile) + + if $count1 > 0 Then RunCommand("reg unload HKLM\System1") + if $count3 > 0 Then RunCommand("reg unload HKLM\Software1") + if $count4 > 0 Then RunCommand("reg unload HKLM\Default1") + +EndFunc + +; =========================================================================================== +; Return true if $s has a registry subkey +Func HasSubKey($s) +; =========================================================================================== + SetError(0) + Dim $subkey = "" + $subkey = RegEnumKey($s, 1) + if @error Then Return False + If $subkey = "" Then Return False + Return True +EndFunc + +; =========================================================================================== +; Run specified command and include stdout and stderr output in our log file +Func RunCommand($cmd) +; =========================================================================================== + LogMessage("Running this command line: " & $cmd) + FileClose($log) + $command = "cmd /c " & $cmd & " >>" & $logfilename & " 2>&1" + RunWait($command) + $log = FileOpen($logfilename, 1) ; 1 = write, append mode +EndFunc + +; =========================================================================================== +Func Usage() +; =========================================================================================== + + Msgbox ("0", $progname, _ + "This program injects a Mass Storage Driver previously captured with the" _ + & @CRLF & "CaptureMsd program." & @CRLF _ + & @CRLF & "Usage: InjectMsd [msdfolder] [parameters]" & @CRLF _ + & @CRLF & "Msdfolder is the path where the driver files captured by CaptureMsd" _ + & @CRLF & "are stored (typically a .sys, .inf and .reg). The msdfolder parameter" _ + & @CRLF & "is optional if a copydrivers.ini file with appropriate parameters is" _ + & @CRLF & "present in the folder from which InjectMsd is running." & @CRLF _ + & @CRLF & "Parameters:" _ + & @CRLF & "/log= : log file" _ + ) + + Exit 1 + +EndFunc + +; =========================================================================================== +; Concatenate a filename ($s) with a base path +Func PathConcat($base, $s) +; =========================================================================================== + $base = StringStripWS($base,3) + $s = StringStripWS($s,3) + if StringRight($base,1) <> "\" Then $base &= "\" + if StringLeft($s,1) = "\" Then $s = StringTrimLeft($s,1) + Return $base & $s +EndFunc + +; =========================================================================================== +; Return true if $s is a folder +Func IsFolder($s) +; =========================================================================================== + If Not FileExists($s) Or Not StringInStr(FileGetAttrib($s), "D") Then Return False + Return True +EndFunc + +; =========================================================================================== +; Return true if $s is a network path. Must be full path. +Func IsRemote($s) +; =========================================================================================== + If StringLeft($s, 2) = "\\" Then Return True + Local $drive = StringLeft($s, 3) + if DriveGetType($drive) = "Network" Then Return True + Return False +EndFunc + +; =========================================================================================== +Func LogCmdLine() +; =========================================================================================== + Local $n + LogMessage($progname & ", command line parameter(s): " & $CmdLine[0]) + For $n = 1 to $CmdLine[0] + LogMessage(" " & $CmdLine[$n]) + Next +EndFunc + +; =========================================================================================== +Func LogMessage($msg) +; =========================================================================================== + FileWriteLine($log, $msg) +EndFunc + +; =========================================================================================== +Func LogIniSection($inifilename, $inisection, $msg = Default) +; =========================================================================================== + Local $i + if $msg = Default Then + LogMessage($inifilename & ",section [" & $inisection & "]:") + Else + LogMessage($msg) + EndIf + Local $section = IniReadSection($inifilename, $inisection) + if @error Then + if not FileExists($inifilename) Then + LogMessage(" File does not exist: " & $inifilename) + Return + EndIf + LogMessage(" " & $inifilename & " includes no [" & $inisection & "] section") + Return + EndIf + For $i = 1 to $section[0][0] + LogMessage(" " & $section[$i][0] & " = " & $section[$i][1]) + Next +EndFunc + +; =========================================================================================== +Func LogOpen(ByRef $logfilename) +; =========================================================================================== + + Local $scriptName = StringTrimRight(@ScriptName, 4) + While 1 + If $logfilename <> "" Then + ; log filename specified on command line + $log = FileOpen($logfilename, 10) ; 10 = 2 (write, create) + 8 (create path) + ExitLoop + EndIf + + ; No /log command line parameter. If there is a copydrivers.ini file with a DriversTarget parameter (typically c:\drivers), create the log in there + Local $iniFilename = PathConcat(@ScriptDir, "copydrivers.ini") + Local $DriverPath = IniRead($iniFilename, "Config", "DriversTarget", "") + if $DriverPath <> "" Then + $DriverPath = StringStripWS($DriverPath, 3) + if StringRight($DriverPath, 1) <> "\" Then $DriverPath &= "\" + $logfilename = $DriverPath & $scriptName & ".log" + $log = FileOpen($logfilename, 10) ; 10 = 2 (write, create) + 8 (create path) + if $log <> -1 Then ExitLoop + EndIf + + ; No /log command parameter and no copydrivers.ini. If running from a local path, create log in folder of running program + If Not IsRemote(@ScriptFullPath) Then + $logfilename = StringTrimRight(@ScriptFullPath, 3) & "log" + $log = FileOpen($logfilename, 2) + if $log <> -1 Then ExitLoop + EndIf + + ; failed to create log + $log = -1 + $logfilename = "" + return + Wend + + LogCmdLine() +EndFunc + +; =========================================================================================== +Func ErrorExit($msg, $exitcode) +; =========================================================================================== + LogMessage($msg) + FileClose($log) + MsgBox(0x40010, $progname, $msg, 10) ; 10 is timeout, i.e. the msgbox closes after 10 seconds + Exit $exitcode +EndFunc + +; =========================================================================================== +; parse command line parameter such as /keyw=something. Examples: +; ValParam("/path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("-path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("/path=c:\temp", "dir", $value) sets $value to "" and returns False +Func ValParam($param, $keyword, ByRef $value) +; =========================================================================================== + $value = "" + Local $p1 = "/" & $keyword & "=" + Local $p2 = "-" & $keyword & "=" + Local $len = StringLen($p1) + if StringLen($param) < ($len + 1) Then Return False + Local $t = StringLeft($param, $len) + if ($t <> $p1) And ($t <> $p2) Then Return False + $value = StringMid($param, $len + 1) ; 1 based + Return True + +EndFunc diff --git a/Tools/Landesk_Autoit/InjectMsd.exe b/Tools/Landesk_Autoit/InjectMsd.exe new file mode 100644 index 0000000..fc7e894 Binary files /dev/null and b/Tools/Landesk_Autoit/InjectMsd.exe differ diff --git a/Tools/Landesk_Autoit/Preferred.bat b/Tools/Landesk_Autoit/Preferred.bat new file mode 100644 index 0000000..283bcd8 --- /dev/null +++ b/Tools/Landesk_Autoit/Preferred.bat @@ -0,0 +1,3 @@ + +X:\ldclient\sdclient.exe /f /o /p=http://%coreIP%/landesk/files/prefmap.exe /dest=x:\ldclient\prefmap.exe /attemptpref +X:\ldclient\prefmap.exe /drv=I: /shr=%share% /usr=%usr% /pwd=%pwd% diff --git a/Tools/Landesk_Autoit/RunEnv.au3 b/Tools/Landesk_Autoit/RunEnv.au3 new file mode 100644 index 0000000..d17f2d9 --- /dev/null +++ b/Tools/Landesk_Autoit/RunEnv.au3 @@ -0,0 +1,88 @@ +#cs ---------------------------------------------------------------------------- + + AutoIt Version: 3.2.10.0 + Author: Jan Buelens, LANDesk Software + + Script Function: + This script may help in an OSD or Provisioning context to make environment variables useful. The author knows of no other way + whereby one provisioning action can use an environment variable set by another provisioning action. Even using setx to set a system + environment variable doesn't do the trick. + This script gets around the issue by reading the system environment variables from the registry before launching the specified + command line. The child process will see all the system environment variables. + +#ce ---------------------------------------------------------------------------- + +$progname = "RunEnv V1.0" + +If $CmdLine[0] = 0 Then Usage() +If $CmdLine[0] > 0 And ($CmdLine[1] = "/?" Or $CmdLine[1] = "-?" Or $CmdLine[1] = "help") Then + Usage() +EndIf + +$CommandLine = "" + +For $n = 1 to $CmdLine[0] + $str = $CmdLine[$n] + ; $str = StringReplace($str, '"', '""') + if StringInStr($str, " ") > 0 And StringLeft($str,1) <> '"' Then + $str = '"' & $str & '"' + EndIf + if $CommandLine <> "" Then + $CommandLine = $CommandLine & " " + EndIf + $CommandLine = $CommandLine & $str +Next + + +$base = "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" + for $n = 1 to 9999 + $valname = RegEnumVal($base, $n) + if @error Then ExitLoop + $val = RegRead($base, $valname) + $env = EnvGet($valname) + if $env = "" Then + ; This environment variable doesn't exist - set it. We only set variables that do not exist in the currrent environment. We don't override + ; variables that exist. This would violate the rule whereby user environmrent variables take priority over system environment variables. + EnvSet($valname, $val) + EndIf + +Next + +; Msgbox ("0", "RunEnv V1.0", "Command Line: ==" & $CommandLine & "==") + +AutoItSetOption ( "ExpandEnvStrings", 1) ; This tells AutoIt to expand Env Vars +$ExitCode = RunWait($CommandLine) +if @error Then ErrorExit("Failed to run command: " & $CommandLine, 2) + +; ErrorExit("Exit Code: " & $ExitCode, $ExitCode) + +Exit $ExitCode + +; =========================================================================================== +Func Usage() +; =========================================================================================== + + Msgbox ("0", $progname, _ + "This program runs the specified command line, after refreshing the system" _ + & @CRLF & "environment variables." & @CRLF _ + & @CRLF & "In a normal windows environment, when a new system environment variable is" _ + & @CRLF & "created (e.g. with setx), running processes will not see the new environment" _ + & @CRLF & "variable, but future processes launched by the windows shell will." & @CRLF _ + & @CRLF & "Under WinPE, the new environment variable seems to remain invisible even to" _ + & @CRLF & "future processes. If this is a problem, use RunEnv. A process launched by" _ + & @CRLF & "RunEnv will see all environment variables. To use RunEnv, just prefix the" _ + & @CRLF & "normal command line with RunEnv." _ + ) + + Exit 1 + +EndFunc + +; =========================================================================================== +Func ErrorExit($msg, $exitcode) +; =========================================================================================== + + MsgBox(0x40010, $progname, $msg, 10) ; 10 is timeout, i.e. the msgbox closes after 10 seconds + Exit $exitcode + +EndFunc diff --git a/Tools/Landesk_Autoit/RunEnv.exe b/Tools/Landesk_Autoit/RunEnv.exe new file mode 100644 index 0000000..fb760db Binary files /dev/null and b/Tools/Landesk_Autoit/RunEnv.exe differ diff --git a/Tools/Landesk_Autoit/prefmap.au3 b/Tools/Landesk_Autoit/prefmap.au3 new file mode 100644 index 0000000..7c23d6d --- /dev/null +++ b/Tools/Landesk_Autoit/prefmap.au3 @@ -0,0 +1,298 @@ +#Region ;**** Directives created by AutoIt3Wrapper_GUI **** +#AutoIt3Wrapper_Res_Comment=This program connects a drive letter to the preferred server for Windows or WinPE. +#AutoIt3Wrapper_Res_Fileversion=3.0.0.1 +#AutoIt3Wrapper_Res_LegalCopyright=LANdesk Software +#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI **** +#cs ---------------------------------------------------------------------------- + + AutoIt Version: 3.3.0.0 + Author: Jan Buelens, LANDesk Software + + Script Function: + Map a drive to the preferred server. + +Change History: + V1.0 01 July 2009. Original version. Based on earlier C++ program. + V2.0 020 Jan 2010. Chnaged for LDMS 9.0. PreferredServer.dat file lives in different place and has different format. + V3.0 06 June 2011. Made work in Windows XP (32-bit) and Windows 7 (32 and 64-bit). + +#ce ---------------------------------------------------------------------------- + +; Script Start - Add your code below here + +Const $progname = "prefmap V3.0" +Dim $share = "" +Dim $drvletter = "" +Dim $user = "" +Dim $pwd = "" +Dim $varname = "" +Dim $bVerbose = False +Dim $bSilent = False +$logfilename = "" ; log file (from /log command line parameter) +$log = -1 +Dim $PrefServerFile8 = "" +Dim $PrefServerFile9 = "" +Dim $CoreServer = "" +Dim $LDMSPath = "" + +If IsWinPE() Then + $PrefServerFile8 = "x:\LANDesk\ManagementSuite\sdmcache\preferredserver.dat" ; LDMS WinPE 8.x + $PrefServerFile9 = "x:\ldclient\preferredservers.dat" ; LDMS WinPE 9.0 + $CoreServer = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Intel\LANDesk\EventLog", "CoreServer") +Else + If StringInStr(@OSArch, "86") Then + $CoreServer = RegRead("HKEY_LOCAL_MACHINE\Software\Intel\LANDesk\EventLog", "CoreServer") + $PrefServerFile9 = "c:\program files\landesk\ldclient\sdmcache\preferredservers." & $CoreServer & ".dat" + $LDMSPath = "c:\program files\landesk\ldclient\" + ElseIf StringInStr(@OSArch, "64") Then + $CoreServer = RegRead("HKEY_LOCAL_MACHINE\Software\Wow6432Node\Intel\LANDesk\EventLog", "CoreServer") + $PrefServerFile9 = "c:\program files (x86)\landesk\ldclient\sdmcache\preferredservers." & $CoreServer & ".dat" + $LDMSPath = "c:\program files (x86)\landesk\ldclient\" + EndIf +EndIf + +Dim $PrefServerFile = "" + + + +; =========================================================================================== +; Validate command line parameters +; =========================================================================================== + +For $n = 1 to $CmdLine[0] + $s = "" + If ValParam($CmdLine[$n], "shr", $s) Then + $share = $s + ElseIf ValParam($CmdLine[$n], "drv", $s) Then + $drvletter = $s + ElseIf ValParam($CmdLine[$n], "usr", $s) Then + $user = $s + ElseIf ValParam($CmdLine[$n], "pwd", $s) Then + $pwd = $s + ElseIf ValParam($CmdLine[$n], "var", $s) Then + $varname = $s + ElseIf ValParam($CmdLine[$n], "log", $s) Then + $logfilename = $s + ElseIf $CmdLine[$n] = "/v" Or $CmdLine[$n] = "-v" Then + $bVerbose = True; + Else + Usage() + EndIf +Next + +if $logfilename = "" Then $logfilename = StringTrimRight(@ScriptFullPath, 3) & "log" +$log = FileOpen($logfilename, 2) + +if $varname = "" Then + ; No variable name (/var) is specified. The other 3 parameters (/drv, /shr, /usr) must be present + if $share = "" then Usage() + if $user = "" then Usage() + if $drvletter = "" then Usage() +EndIf +If $share <> "" Or $user <> "" Or $drvletter <> "" Then + ; if one of (/drv, /shr, /usr) is present, all 3 must be present + if $share = "" then Usage() + if $user = "" then Usage() + if $drvletter = "" then Usage() + ; validate format of /drv + if StringLen($drvletter) > 2 Then Usage() + if StringLen($drvletter) = 1 Then $drvletter &= ":" + if StringRight($drvletter, 1) <> ":" Then Usage() + $drvletter = StringUpper($drvletter) + if $drvletter < "A:" Or $drvletter > "Z:" Then Usage() +EndIf + +;If Not IsWinPE() Then ErrorExit("This program must be run under WinPE", 2) + +If not GetPrefServerFile() Then + ; =================================================================================== + ; Use sdclient to download a small dummy file from the core server. As a side effect, + ; a preferredserver.dat file is left in x:\LANDesk\ManagementSuite\sdmcache. + ; Whether the download is successful does not matter + ; =================================================================================== + + ;$CoreServer = RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Intel\LANDesk\LDWM", "CoreServer") + if $bVerbose Then MsgBox(0, $progname, "core server: " & $CoreServer, 5) + If IsWinPE() Then + $SdclientCommandLine = "X:\ldclient\sdclient.exe /f /o /dest=x:\ldclient\win_prov_files.xml /p=http://" & $CoreServer & "/ldlogon/provisioning/win_prov_files.xml" + if $bVerbose Then MsgBox(0, $progname, "command line: " & $SdclientCommandLine, 10) + LogMessage("Dummy download from core server so sdclient/lddwnld.dll gets hold of preferredserver(s).dat") + LogMessage("command line: " & $SdclientCommandLine) + RunWait($SdclientCommandLine, "x:\ldclient") + Else + $SdclientCommandLine = $LDMSPath & "sdclient.exe /f /o /p=http://" & $CoreServer & "/ldlogon/provisioning/win_prov_files.xml /requirepref" + if $bVerbose Then MsgBox(0, $progname, "command line: " & $SdclientCommandLine, 10) + LogMessage("Dummy download from core server so sdclient/lddwnld.dll gets hold of preferredserver(s).dat") + LogMessage("command line: " & $SdclientCommandLine) + RunWait($SdclientCommandLine, $LDMSPath) + EndIf +EndIf + +If not GetPrefServerFile() Then ErrorExit("preferredserver(s).dat not found", 3) +LogMessage("preferredserver.dat found at " & $PrefServerFile) +$line = FileReadLine($PrefServerFile) +if $line = "" Then ErrorExit("PreferredServer(s).dat file is empty", 4) +LogMessage("preferredserver(s).dat file contents: " & $line) + +; =================================================================================== +; Found preferredserver.dat. It is a text file with no CR-LF. If there are multiple preferred servers, +; they are separated by a semicolon. The preferred server list may or may not be prefixed with a time stamp +; and a question mark. +; Expected formats for LDMS 8.8: +; SERVER1 +; SERVER1;SERVER2 +; Expected formats for LDMS 8.8: +; 12349439485?SERVER1 +; 12349439485?SERVER1;SERVER2 +; =================================================================================== + +$serverlist = "" +$array = StringSplit($line,"?") +If $array[0] = 1 Then + ; there was no question mark + $serverlist = $line +ElseIf $array[0] = 2 Then + ; there was 1 question mark - take the substring after the question mark + $serverlist = $array[2] +Else + ErrorExit("preferredserver.dat, invalid format", 41) +EndIf + +$array = StringSplit($serverlist,";") +$servername = $array[1] + +; =================================================================================== +; When using local user names, we may need something like \. +; If the username we got from the command line includes a substring "$server$", replace +; with server name from preferredserver.dat +; =================================================================================== + +$user = StringReplace($user, "$server$", $servername) + +if $bVerbose Then MsgBox(0, $progname, "preferred server: " & $servername, 5) +LogMessage("preferred server: " & $servername) + +if $share <> "" Then + $unc = "\\" & $servername & "\" & $share + + if $bVerbose Then MsgBox(0, $progname, "connecting " & $drvletter & " to " & $unc & " as " & $user, 5) + LogMessage("connecting " & $drvletter & " to " & $unc & " as " & $user) + + $ret = DriveMapAdd($drvletter, $unc, 0, $user, $pwd) + if $ret = 0 Then + $errmsg = "DriveMapAdd(" & $drvletter & ", " & $unc & ", " & $user & ", ) failed. " + if @error = 1 Then $errmsg &= "Win32 error code " & @extended + if @error = 2 Then $errmsg &= "Access Denied" + if @error = 3 Then $errmsg &= "Drive letter already assigned" + if @error = 4 Then $errmsg &= "Invalid drive letter" + if @error = 5 Then $errmsg &= "UNC path not found" + if @error = 6 Then $errmsg &= "Invalid password" + ErrorExit($errmsg, 5) + EndIf + + if $bVerbose Then MsgBox(0, $progname, "connection successful", 5) + LogMessage("connection successful") +EndIf + +if $varname <> "" Then + $base = "HKLM\System\CurrentControlSet\Control\Session Manager\Environment" + RegWrite($base, $varname, "REG_SZ", $servername) + if @error Then ErrorExit("RegWrite, error " & @error, 6) + LogMessage("Environment variable set") +EndIf + +FileClose($log) + + +; =========================================================================================== +; The location of the preferredserver.dat file is different between LDMS 8.8 and 9.0. This function looks in the +; two possible places and sets a global variable ($PrefServerFile) to the correct path. If the file is found in +; neither place, the return value is false. +Func GetPrefServerFile() +; =========================================================================================== + $PrefServerFile = "" + If FileExists($PrefServerFile8) Then + $PrefServerFile = $PrefServerFile8 + Return True + EndIf + If FileExists($PrefServerFile9) Then + $PrefServerFile = $PrefServerFile9 + Return True + EndIf + Return False +EndFunc + +; =========================================================================================== +; Return true if running under WinPE +Func IsWinPE() +; =========================================================================================== + If EnvGet("SystemDrive") = "X:" Then Return True + Return False +EndFunc + +; =========================================================================================== +Func ErrorExit($msg, $exitcode) +; =========================================================================================== + + LogMessage($msg) + FileClose($log) + if not $bSilent Then MsgBox(0x40010, $progname, $msg, 10) ; 10 is timeout, i.e. the msgbox closes after 10 seconds + Exit $exitcode + +EndFunc + +; =========================================================================================== +; parse command line parameter such as /keyw=something. Examples: +; ValParam("/path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("-path=c:\temp", "path", $value) sets $value to "c:\temp" and returns True +; ValParam("/path=c:\temp", "dir", $value) sets $value to "" and returns False +Func ValParam($param, $keyword, ByRef $value) +; =========================================================================================== + $value = "" + Local $p1 = "/" & $keyword & "=" + Local $p2 = "-" & $keyword & "=" + Local $len = StringLen($p1) + if StringLen($param) < ($len + 1) Then Return False + Local $t = StringLeft($param, $len) + if ($t <> $p1) And ($t <> $p2) Then Return False + $value = StringMid($param, $len + 1) ; 1 based + Return True + +EndFunc + +; =========================================================================================== +Func LogMessage($msg) +; =========================================================================================== + FileWriteLine($log, $msg) +EndFunc + +; =========================================================================================== +Func Usage() +; =========================================================================================== + Msgbox (0, $progname & " by Jan Buelens", _ + "This program maps a drive to the preferred server." & @CRLF _ + & @CRLF & "Usage:" _ + & @CRLF & " /shr= share" _ + & @CRLF & " /drv= drive letter" _ + & @CRLF & " /usr= user name" _ + & @CRLF & " /pwd= password" _ + & @CRLF & " /var= environment variable" _ + & @CRLF & " /v verbose" & @CRLF _ + & @CRLF & "Use this program only under WinPE." _ + & @CRLF & "If there are multiple preferred servers, the first one will be used." _ + & @CRLF & "If you are using a local machine account to connect, you may want to" _ + & @CRLF & "include a $server$ substring in the user name. The program will replace" _ + & @CRLF & "it with the preferred server name." _ + & @CRLF & "" _ + & @CRLF & "If a /var parameter is specified, a system environment variable will" _ + & @CRLF & "set to the preferred server name. You probably need the RunEnv tool to" _ + & @CRLF & "use the environment variable. If you only want prefmap to set an" _ + & @CRLF & "environment variable, without mapping a drive, use the /var parameter" _ + & @CRLF & "only." _ + & @CRLF & "" _ + ) + + Exit 1 + +EndFunc + diff --git a/Tools/Landesk_Autoit/prefmap.exe b/Tools/Landesk_Autoit/prefmap.exe new file mode 100644 index 0000000..3bb2d0d Binary files /dev/null and b/Tools/Landesk_Autoit/prefmap.exe differ diff --git a/check-missing-package-files/CheckMissingFilesForPackages.ps1 b/check-missing-package-files/CheckMissingFilesForPackages.ps1 new file mode 100644 index 0000000..20710b3 --- /dev/null +++ b/check-missing-package-files/CheckMissingFilesForPackages.ps1 @@ -0,0 +1,67 @@ + +#-------------------------- connecteur SQL ---------------------------------- +$dataSource = "sql.leblogosd.lan" +$user = "compteSQL" +$PassSQL = 'Password' +$database = "EPM2021" +$connectionString = "Server=$dataSource;uid=$user; pwd=$PassSQL;Database=$database;Integrated Security=False;" +$connection = New-Object System.Data.SqlClient.SqlConnection +$connection.ConnectionString = $connectionString +$connection.Open() + + +#------------------------ Query ----------------------------------------------------- + +$query = "SELECT * FROM [dbo].[PACKAGE]" +$command = $connection.CreateCommand() +$command.CommandText = $query +$result = $command.ExecuteReader() +$Packages = new-object System.Data.DataTable +$Packages.Load($result) + +$query = "SELECT * FROM [dbo].[PACKAGE_FILES_HASH]" +$command = $connection.CreateCommand() +$command.CommandText = $query +$result = $command.ExecuteReader() +$FilesHash = new-object System.Data.DataTable +$FilesHash.Load($result) + + +$PackageError = 0 + +foreach ($Package in $Packages) { + $PackageName = $Package.NAME + $PackageInstall = $Package.INSTALL + $PackageFileHashIDN = $Package.PACKAGE_FILES_HASH_IDN + + foreach ($FileHash in $FilesHash) { + $FileHashIDN = $FileHash.PACKAGE_FILES_HASH_IDN + $FileHashPath = $FileHash.FULL_PATH + + if ($PackageFileHashIDN -eq $FileHashIDN) { + If ($FileHashPath -like "http*") { + try { + $Request = Invoke-WebRequest -uri $FileHashPath + } Catch { + $PackageError = $PackageError+1 + If ($PackageInstall -eq 1) { #Package reelle <> bundle + write-host "MISSING : $PackageName => $FileHashPath" + } + } + + If ($FileHashPath -like "\\*") { + If (Test-path $FileHashPath) { + } Else { + $PackageError = $PackageError+1 + write-host "MISSING : $PackageName => $FileHashPath" + } + } + } + } + + } +} + + + + diff --git a/check-missing-package-files/readme.md b/check-missing-package-files/readme.md new file mode 100644 index 0000000..7eac1b4 --- /dev/null +++ b/check-missing-package-files/readme.md @@ -0,0 +1,28 @@ +# Check EPM Package Files — README + +Validate that **Ivanti EPM** package file references exist (HTTP/HTTPS and UNC). +The script connects to SQL, reads `[dbo].[PACKAGE]` and `[dbo].[PACKAGE_FILES_HASH]`, and reports missing files. + +## Requirements +- Windows PowerShell 5.1 +- Network access to SQL (`EPM2021` DB in the sample) +- SQL account with read access to `dbo.PACKAGE` and `dbo.PACKAGE_FILES_HASH` + +## Configure +Edit these variables at the top of the script: +```powershell +$dataSource = "sql.leblogosd.lan" # SQL Server / instance +$user = "compteSQL" # SQL login +$PassSQL = "Password" # SQL password (plaintext in sample) +$database = "EPM2021" # EPM database +``` +## What it does +- SELECT * FROM dbo.PACKAGE and SELECT * FROM dbo.PACKAGE_FILES_HASH +- For each package/file hash:
+-- If FULL_PATH starts with http → Invoke-WebRequest (200 = OK, else MISSING)
+-- If FULL_PATH starts with \\ → Test-Path on UNC (exists = OK, else MISSING)
+ +## What it does +```powershell +powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\Check-EpmPackageFiles.ps1 +``` \ No newline at end of file diff --git a/check-ports/CheckPortGUI.ps1 b/check-ports/CheckPortGUI.ps1 new file mode 100644 index 0000000..e836203 --- /dev/null +++ b/check-ports/CheckPortGUI.ps1 @@ -0,0 +1,272 @@ +# Load the Windows Forms assembly +Add-Type -AssemblyName System.Windows.Forms + +# Create the form +$form = New-Object System.Windows.Forms.Form +$form.Text = 'Test Ports GUI' +$form.Size = New-Object System.Drawing.Size(500,500) +$form.StartPosition = 'CenterScreen' +$form.FormBorderStyle = [System.Windows.Forms.FormBorderStyle]::FixedSingle +$form.MaximizeBox = $false + +# Create the label for target input +$labelTarget = New-Object System.Windows.Forms.Label +$labelTarget.Location = New-Object System.Drawing.Point(10,10) +$labelTarget.Size = New-Object System.Drawing.Size(480,20) +$labelTarget.Text = 'Target:' +$form.Controls.Add($labelTarget) + +# Create the textbox for target input +$textboxTarget = New-Object System.Windows.Forms.TextBox +$textboxTarget.Location = New-Object System.Drawing.Point(10,30) +$textboxTarget.Size = New-Object System.Drawing.Size(460,20) +$form.Controls.Add($textboxTarget) + +# Create the label for port selection +$labelPort = New-Object System.Windows.Forms.Label +$labelPort.Location = New-Object System.Drawing.Point(10,60) +$labelPort.Size = New-Object System.Drawing.Size(480,20) +$labelPort.Text = 'Port:' +$form.Controls.Add($labelPort) + +# Create the combobox for port selection +$comboBoxPort = New-Object System.Windows.Forms.ComboBox +$comboBoxPort.Location = New-Object System.Drawing.Point(10,80) +$comboBoxPort.Size = New-Object System.Drawing.Size(460,20) +$comboBoxPort.DropDownStyle = 'DropDownList' +# Add the port options +$comboBoxPort.Items.AddRange(@('FTP','HTTP','SMB','LDAP','SQL','EPMtestCore','EPMtestClient','VNC','Synology')) +$form.Controls.Add($comboBoxPort) + + + +# Create the button to trigger port testing +$button = New-Object System.Windows.Forms.Button +$button.Location = New-Object System.Drawing.Point(10,110) +$button.Size = New-Object System.Drawing.Size(460,20) +$button.Text = 'Test Port' +$button.BackColor = [System.Drawing.Color]::LightBlue +$button.ForeColor = [System.Drawing.Color]::Black +$button.Font = New-Object System.Drawing.Font("Arial", 10, [System.Drawing.FontStyle]::Bold) +$button.Add_MouseEnter({ $button.BackColor = [System.Drawing.Color]::RoyalBlue }) +$button.Add_MouseLeave({ $button.BackColor = [System.Drawing.Color]::LightBlue }) + +$button.Add_Click({ + $outputBox.Clear() + $progressBar.Value = 0 + $progressBar.Maximum = $comboBoxPort.Items.Count + $result = Test-Ports -TargetHost $textboxTarget.Text -Protocol $comboBoxPort.SelectedItem.ToString() + foreach ($line in $result) { + $outputBox.AppendText("$line`r`n") + $progressBar.PerformStep() + } + $progressBar.Value = $progressBar.Maximum # Compléter la barre de progression +}) +$form.Controls.Add($button) + +# Créer le bouton pour déclencher le test de ping +$pingButton = New-Object System.Windows.Forms.Button +$pingButton.Location = New-Object System.Drawing.Point(10,140) +$pingButton.Size = New-Object System.Drawing.Size(460,20) +$pingButton.Text = 'Test Ping' +$pingButton.BackColor = [System.Drawing.Color]::LightBlue +$pingButton.ForeColor = [System.Drawing.Color]::Black +$pingButton.Font = New-Object System.Drawing.Font("Arial", 10, [System.Drawing.FontStyle]::Bold) +$pingButton.Add_MouseEnter({ $pingButton.BackColor = [System.Drawing.Color]::RoyalBlue }) +$pingButton.Add_MouseLeave({ $pingButton.BackColor = [System.Drawing.Color]::LightBlue }) +$pingButton.Add_Click({ + $outputBox.Clear() + $progressBar.Value = 0 + $pingResult = Test-Ping -TargetHost $textboxTarget.Text + $outputBox.AppendText($pingResult) +}) +$form.Controls.Add($pingButton) + +# Create the output console +$outputBox = New-Object System.Windows.Forms.TextBox +$outputBox.Multiline = $true +$outputBox.ScrollBars = 'Vertical' +$outputBox.Location = New-Object System.Drawing.Point(10,180) +$outputBox.Size = New-Object System.Drawing.Size(460,220) +$form.Controls.Add($outputBox) + + +# Créer la barre de progression +$progressBar = New-Object System.Windows.Forms.ProgressBar +$progressBar.Location = New-Object System.Drawing.Point(10, 420) +$progressBar.Size = New-Object System.Drawing.Size(460, 20) +$progressBar.Style = [System.Windows.Forms.ProgressBarStyle]::Continuous +$form.Controls.Add($progressBar) + +# Function to test ports (Place your existing function here with slight modifications) + +# Fonction pour tester le ping +function Test-Ping { + param ( + [string]$TargetHost = "localhost" + ) + + try { + $ping = New-Object System.Net.NetworkInformation.Ping + $result = $ping.Send($TargetHost) + if ($result.Status -eq 'Success') { + return "Ping to $TargetHost successful: $($result.RoundtripTime)ms" + } else { + return "Ping to $TargetHost failed: $($result.Status)" + } + } catch { + return "Ping failed: $_" + } +} + +function Test-Ports { + param ( + [string]$TargetHost = "localhost", + [string]$Protocol = "FTP" + ) + + # Définir une liste de ports avec leurs descriptions + $FTP = @( + @{ Port = 20; Description = "FTP Data Transfer" }, + @{ Port = 21; Description = "FTP Command Control"} + @{ Port = 22; Description = "SFTP" }, + @{ Port = 990; Description = "FTPS Command Control (Explicit Mode)"}, + @{ Port = 989; Description = "FTPS Data Transfert (Explicit Mode)" } + ) + + $HTTP = @( + @{ Port = 80; Description = "HTTP" }, + @{ Port = 443; Description = "HTTPS"} + ) + + $SMB = @( + @{ Port = 139; Description = "SMB" }, + @{ Port = 445; Description = "SMB"} + ) + + $VNC = @( + @{ Port = 5800; Description = "VNC"}, + @{ Port = 5900; Description = "VNC (java)"} + ) + + $LDAP = @( + @{ Port = 389; Description = "LDAP standard" }, + @{ Port = 636; Description = "LDAP sur SSL/TLS (LDAPS)" }, + @{ Port = 3268; Description = "LDAP Query globales MS AD" }, + @{ Port = 3269; Description = "LDAPS Query globales MS AD" }, + @{ Port = 464; Description = "Kerberos - set/change password" }, + @{ Port = 88; Description = "Kerberos - Authentification" }, + @{ Port = 9389; Description = "AD DS Web Services" }, + @{ Port = 53; Description = "DNS standard" }, + @{ Port = 5353; Description = "mDNS (Multicast DNS)" } + ) + + $SQL= @( + @{ Port = 1433; Description = "SQL" } + ) + + $EPMtestClient = @( + @{ Port = 139; Description = "SMB" }, + @{ Port = 445; Description = "SMB"}, + @{ Port = 9593; Description = "Agent discovery, Software distribution"}, + @{ Port = 9594; Description = "Agent discovery and management" }, + @{ Port = 9595; Description = "Agent discovery and management"}, + @{ Port = 33354; Description = "Peer Download"}, + @{ Port = 33355; Description = "Peer Download"}, + @{ Port = 33370; Description = "Peer Download"}, + @{ Port = 33371; Description = "Peer Download"}, + @{ Port = 44343; Description = "WS Remote Control" } + ) + + $EPMtestCore = @( + @{ Port = 80; Description = "HTTP" }, + @{ Port = 443; Description = "HTTPS"}, + @{ Port = 139; Description = "SMB" }, + @{ Port = 445; Description = "SMB"}, + @{ Port = 9593; Description = "Agent discovery, Software distribution"}, + @{ Port = 9594; Description = "Agent discovery and management"}, + @{ Port = 9595; Description = "Agent discovery and management"} + ) + + + $SynologyNASPorts = @( + @{ Port = 5000; Description = "HTTP access" }, + @{ Port = 5001; Description = "HTTPS access" }, + @{ Port = 21; Description = "FTP access" }, + @{ Port = 22; Description = "SSH access" }, + @{ Port = 2049; Description = "NFS service" }, + @{ Port = 445; Description = "SMB service" }, + @{ Port = 5432; Description = "PostgreSQL database service" }, + @{ Port = 3306; Description = "MySQL database service" }, + @{ Port = 137; Description = "NetBIOS name service" }, + @{ Port = 138; Description = "NetBIOS datagram service" }, + @{ Port = 139; Description = "NetBIOS session service" }, + @{ Port = 80; Description = "HTTP access (additional)" }, + @{ Port = 443; Description = "HTTPS access (additional)" }, + @{ Port = 873; Description = "rsync" }, + @{ Port = 3260; Description = "iSCSI" }, + @{ Port = 1194; Description = "OpenVPN service" }, + @{ Port = 5353; Description = "DNS-SD service" }, + @{ Port = 6690; Description = "Synology Cloud Station" }, + @{ Port = 6881; Description = "BitTorrent service" }, + @{ Port = 1900; Description = "UPnP/DLNA" } + ) + + + + # Résultats du tableau + $results = @() + + # Sélectionner les ports en fonction du protocole + switch ($Protocol) { + "FTP" { $filteredPorts = $FTP } + "HTTP" { $filteredPorts = $HTTP } + "SMB" { $filteredPorts = $SMB } + "LDAP" { $filteredPorts = $LDAP } + "SQL" { $filteredPorts = $SQL } + "EPMtestClient" { $filteredPorts = $EPMtestClient } + "EPMtestCore" { $filteredPorts = $EPMtestCore } + "VNC" { $filteredPorts = $VNC } + "Synology" { $filteredPorts = $SynologyNASPorts } + } + + $OriginalProgressPreference = $Global:ProgressPreference + $Global:ProgressPreference = 'SilentlyContinue' + + # Mettre à jour la barre de progression + $progressBar.Value = 0 + $progressBar.Maximum = $filteredPorts.Count + $progressBar.Step = 1 + + # Tester chaque port + foreach ($port in $filteredPorts) { + $testResult = Test-NetConnection -ComputerName $TargetHost -Port $port.Port -InformationLevel Quiet + #write-host "Test-NetConnection -ComputerName $TargetHost -Port $($port.Port)" + #write-host $testResult + $results += [PSCustomObject]@{ + "Host" = $TargetHost + "Port" = $port.Port + "Description" = $port.Description + "Status" = if ($testResult -eq $true) { "Open" } else { "Closed" } + } + $progressBar.PerformStep() # Mettre à jour la barre de progression + } + + $Global:ProgressPreference = $OriginalProgressPreference + + $resultsText = @() + foreach ($result in $results) { + $Hostalign = $($result.Host).PadRight(30) + $Portalign = $($result.Port).ToString().PadRight(8) + $Statalign = $($result.Status).PadRight(8) + $Desralign = $($result.Description) + + + $resultsText += "$Portalign $Statalign $Desralign" + } + + return $resultsText +} + +# Show the form +$form.ShowDialog() diff --git a/check-ports/readme.jpg b/check-ports/readme.jpg new file mode 100644 index 0000000..0884aad Binary files /dev/null and b/check-ports/readme.jpg differ diff --git a/check-ports/readme.md b/check-ports/readme.md new file mode 100644 index 0000000..6a98e30 --- /dev/null +++ b/check-ports/readme.md @@ -0,0 +1,36 @@ +# CheckPortGUI.ps1 — Simple Port Tester + +Small PowerShell GUI to test **common ports** and **ICMP ping** against a target host. Uses `Test-NetConnection` under the hood and shows a per-port status with a progress bar. + +![Screenshot](./readme.jpg) + +## Requirements +- Windows PowerShell 5.1 (x64 recommended) +- Network access to the target + +## Included checks +Dropdown protocols mapped to port sets: +- FTP (20, 21, 22, 989, 990) +- HTTP (80, 443) +- SMB (139, 445) +- LDAP/AD (389, 636, 3268, 3269, 464, 88, 9389, 53, 5353) +- SQL (1433) +- EPMtestCore (80, 443, 139, 445, 9593, 9594, 9595) +- EPMtestClient (139, 445, 9593, 9594, 9595, 33354, 33355, 33370, 33371, 44343) +- VNC (5800, 5900) +- Synology (5000, 5001, 21, 22, 2049, 445, 5432, 3306, 137, 138, 139, 80, 443, 873, 3260, 1194, 5353, 6690, 6881, 1900) + +## Install +Save the script as `CheckPortGUI.ps1` in your working directory + +## Run +```powershell +powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\CheckPortGUI.ps1 +``` + +## Usage +- Enter the target hostname or IP. +- Pick a protocol from the dropdown. +- Click “Test Port” to run all ports in that set (progress bar updates). +- Click “Test Ping” for an ICMP reachability check. +Results appear in the textbox (one line per port: Port, Status, Description). \ No newline at end of file diff --git a/deploy-add-to-task/addtotask.ps1 b/deploy-add-to-task/addtotask.ps1 new file mode 100644 index 0000000..efc4f0a --- /dev/null +++ b/deploy-add-to-task/addtotask.ps1 @@ -0,0 +1,93 @@ +[void][System.Reflection.Assembly]::LoadWithPartialName('presentationframework') + +[xml]$XAML = @' + + + + + + + + + + + + + +