
JMiller
Members-
Posts
16 -
Joined
-
Last visited
Everything posted by JMiller
-
Oh, sorry for the untimely reply. I thought I had e-mail notification turned on. Basically what it does is this: Takes the specified .reg file and creates a new temporary file. The temporary file contents are the same, except where [HKEY_CURRENT_USER\ is encountered, in which case it changes that to [HKEY_USERS\temp\. Whenever you export user-level settings from the registry, it's from HKEY_CURRENT_USER. (It also replaces [-HKEY_CURRENT_USER\ to [-HKEY_USERS\temp\ in the event that you want automate key deletion with the .reg file. Maybe you want to purge a key before writing the values back to it, so you know exactly what's in it.) So the new file references [HKEY_USERS\temp instead, which is where the program will be temporarily loading user profiles to in the registry. After the temporary .reg file has been created with the correct paths, the script loops through each user profile and uses the REG LOAD command to load the profile (ntuser.dat) to HKEY_USERS\temp. Then, when the profile is loaded, it uses the regedit.exe command to merge the temporary .reg file into the user profile. Finally, it unloads the user's profile and proceeds to the next one. So, to answer your question, it doesn't export the user's hive. It actually just temporarily loads the hive to a specific location in the registry and merges a modified .reg file that references that same location. Hope this explanation helps!
-
This is a little utility I wrote awhile back and figured I might as well share in case anyone would find it useful. The idea is simple... let's say you have some user-specific settings (i.e. in HKCU branch of the registry) that you want to apply to existing user profiles on a computer. Maybe you made a configuration change to a program and want other users to have the new settings (without having to delete the profile and lose other settings/files they may have). You simply export the appropriate section of HKCU and use this program to apply it to the existing profiles. ;Include required files. #include <GUIConstants.au3> ;Set script options. Opt("TrayIconHide", 1) Opt("GUIOnEventMode", 1) ;Ensure the required files are present. $systemDrive = EnvGet("systemdrive") $regExePath = @WindowsDir & "\system32\reg.exe" $regeditExePath = @WindowsDir & "\regedit.exe" If Not FileExists($regExePath) Or Not FileExists($regeditExePath) Then MsgBox(0, "Error", "Sorry, this program is only compatible with Windows XP.") Exit EndIf ;Create GUI elements. $mainWindow = GUICreate("Import Registry File", 400, 480, -1, -1, -1, $WS_EX_ACCEPTFILES) ;Create description area. GUICtrlCreateGroup("Description", 10, 10, 380, 88) GUICtrlCreateLabel("This program is designed to allow you to apply registry settings from an exported registry (.reg) file to existing user profiles on the computer. Only files exported from the HKEY_CURRENT_USER section of the registry can be imported. You must be a member of the Administrators group to access other profiles. Profiles that are locked by the OS will be skipped.", 20, 25, 360, 72) ;Create options area. GUICtrlCreateGroup("Options", 10, 108, 380, 120) GUICtrlCreateLabel("Select the registry file to import.", 20, 125, 360, 20) ;Create Browse button to select the registry file. $browseButton = GUICtrlCreateButton("Browse...", 20, 142, 70, 20) GUICtrlSetOnEvent($browseButton, "browseClicked") $regPathInput = GUICtrlCreateInput("", 100, 142, 280, 20) GUICtrlSetState($regPathInput, $GUI_ACCEPTFILES) ;Create checkboxes to specify which profiles to update. GUICtrlCreateLabel("Which profiles do you want to update?", 20, 167, 360, 20) GUICtrlCreateLabel("Default User profile", 40, 185, 250, 20) $defaultUser = GUICtrlCreateCheckbox("", 22, 185, 14, 14) GUICtrlCreateLabel("Existing user profiles (besides Default User)", 40, 205, 250, 20) $existingUsers = GUICtrlCreateCheckbox("", 22, 205, 14, 14) ;Create status area. GUICtrlCreateGroup("Status", 10, 238, 380, 200) $statusBox = GUICtrlCreateEdit("", 20, 255, 360, 173, BitOR($WS_HSCROLL, $WS_VSCROLL, $ES_MULTILINE, $ES_READONLY), 0) ;Create Action buttons section. $updateButton = GUICtrlCreateButton("Update Registry", 85, 448, 110, 25) GUICtrlSetOnEvent($updateButton, "updateClicked") $closeButton = GUICtrlCreateButton("Close Program", 205, 448, 110, 25) GUICtrlSetOnEvent($closeButton, "closeClicked") ;Set close event. GUISetOnEvent($GUI_EVENT_CLOSE, "closeClicked") ;Build the GUI. GUISetState(@SW_SHOW) While 1 Sleep(1000) ;Idle around WEnd Func browseClicked() ;Display a file open dialog box. $regFilePath = FileOpenDialog("Please select the registry file to import.", @ScriptDir & "\", "Registry Files (*.reg)", 1) GUICtrlSetData($regpathInput, $regFilePath) EndFunc Func updateClicked() ;Import the registry file into the specified profiles. $tempString = "temp" $tempFilePath = @ScriptDir & "\import_" & $tempString & ".reg" $tempKey = "HKU\" & $tempString $UNICODE_MODE = 32 $error = 0 $UNABLE_TO_OPEN = 1 $UNABLE_TO_DELETE = 2 $UNABLE_TO_UNLOAD = 3 $hkcuFound = False If StringLen(GUICtrlRead($regPathInput)) <> 0 Then ;The string was at least 1 character long. If FileExists(GUICtrlRead($regPathInput)) Then ;The registry file was found. If GUICtrlRead($defaultUser) = $GUI_CHECKED Or GUICtrlRead($existingUsers) = $GUI_CHECKED Then ;At least one of the checkboxes was checked. Start processing the registry file. ;Disable the action buttons while running. GUICtrlSetState($updateButton, $GUI_DISABLE) GUICtrlSetState($closeButton, $GUI_DISABLE) ;Begin writing the log to the status box. GUICtrlSetData($statusBox, "[" & @HOUR & ":" & @MIN & ":" & @SEC & "] Process started.") ;Delete the temporary file if it exists. If FileExists($tempFilePath) Then FileDelete($tempFilePath) If FileExists($tempFilePath) Then ;The delete was unsuccessful. Write an error message to the status box. $error = $UNABLE_TO_DELETE Else ;Open the temporary file for writing. $tempFile = FileOpen($tempFilePath, 1) EndIf Else ;Open the temporary file for writing. $tempFile = FileOpen($tempFilePath, 1) EndIf If $error = 0 Then ;Open the original registry file for reading. $origFile = FileOpen(GUICtrlRead($regPathInput), 0 + $UNICODE_MODE) ;Check if original registry file opened successfully. If $origFile = -1 Then MsgBox(0, "Error", "Unable to open registry file (" & $origFile & ").") $error = $UNABLE_TO_OPEN EndIf If $error = 0 Then ;Write the boiler-plate line to the top of the temporary file. FileWriteLine($tempFile, "Windows Registry Editor Version 5.00" & @CRLF) ;Read each line from the original registry file. While 1 $line = FileReadLine($origFile) If @error = -1 Then ExitLoop If StringInStr($line, "Windows Registry Editor Version 5.00") Or StringInStr($line, "REGEDIT4") Then ;Skip the line, because it is already accounted for. Else ;GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & $line) If StringInStr($line, "[HKEY_CURRENT_USER\") Then ;Modify the line, because it was exported from HKCU. $hkcuFound = True $line = StringReplace($line, "[HKEY_CURRENT_USER\", "[HKEY_USERS\" & $tempString & "\") EndIf If StringInStr($line, "[-HKEY_CURRENT_USER\") Then ;Modify the line, because it was exported from HKCU. $hkcuFound = True $line = StringReplace($line, "[-HKEY_CURRENT_USER\", "[-HKEY_USERS\" & $tempString & "\") EndIf FileWriteLine($tempFile, $line) EndIf Wend ;Close the original registry file. FileClose($origFile) ;Close the temporary registry file. FileClose($tempFile) If $hkcuFound = True Then ;At least one entry referred to HKEY_CURRENT_USER. Proceed to importing the temporary registry file. ;Check for the presence of the temporary hive and close it if needed. SetError(0) ;Set the error to none to begin. RegRead($tempKey, "") If @error = 1 Then ;The key did not exist, indicating that it is safe to proceed. SetError(0) ;Set error back to none after testing. Else ;Attempt to close the key, because it shouldn't exist. $command = $regExePath & " UNLOAD " & $tempKey RunWait($command) ;Check again for the presence of the key, to see if it was successfully removed. SetError(0) ;Set the error to none to begin. RegRead($tempKey, "") If @error = 1 Then ;The key was successfully unloaded. Continue the process. SetError(0) ;Set error back to none after testing. Else ;The key was not unloaded. Generate an error in the status box. $error = $UNABLE_TO_UNLOAD GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: A hive was already mapped to the temporary key (" & $tempKey & ") and could not be unloaded.") EndIf EndIf If $error = 0 Then ;There were no errors. Begin importing hives and merging the temporary registry file. If GUICtrlRead($defaultUser) = $GUI_CHECKED And GUICtrlRead($existingUsers) = $GUI_UNCHECKED Then ;Only the default user profile should be updated. If FileExists($systemDrive & "\Documents and Settings\Default User\ntuser.dat") Then ;Attempt to load the ntuser.dat file into the registry. ;GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Loading hive " & $systemDrive & "\Documents and Settings\Default User\ntuser.dat.") $command = $regExePath & " LOAD " & $tempKey & " """ & $systemDrive & "\Documents and Settings\Default User\ntuser.dat" & """" RunWait($command, "", @SW_HIDE) ;Ensure the loaded key exists. RegRead($tempKey, "") If @error <> -1 Then ;There was some kind of error, skip importing the file. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Notice: Unable to open " & $systemDrive & "\Documents and Settings\Default User\ntuser.dat.") SetError(0) ;Clear the error. Else ;Import registry settings. SetError(0) ;Set error back to none after testing. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Updating " & $systemDrive & "\Documents and Settings\Default User\ntuser.dat.") $command = $regeditExePath & " /s """ & $tempFilePath & """" RunWait($command, "", @SW_HIDE) ;Unload the registry hive. ;GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Unloading hive " & $systemDrive & "\Documents and Settings\Default User\ntuser.dat.") $command = $regExePath & " UNLOAD " & $tempKey RunWait($command, "", @SW_HIDE) ;Ensure the hive was unloaded. RegRead($tempKey, "") If @error = 1 Then ;The hive was no longer present. Continue normally. SetError(0) ;Set the error back to none after testing. Else ;The hive was not unloaded as expected. Generate an error in the status box. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Unable to unload " & $systemDrive & "\Documents and Settings\Default User\ntuser.dat.") $error = $UNABLE_TO_UNLOAD EndIf EndIf EndIf Else ;Existing user profiles should be updated. $profileDir = $systemDrive & "\Documents and Settings" If FileExists($profileDir) Then ;The root profile path was present. If FileChangeDir($profileDir) Then ;Changed working directory to the root profile path. $search = FileFindFirstFile("*") If $search <> -1 Then ;At least one file or folder was found in the directory. $error = 0 While $error = 0 $currentFile = FileFindNextFile($search) If @error Then ExitLoop If StringInStr(FileGetAttrib($currentFile), "D") Then ;The current file is a directory. If $currentFile = "All Users" Or $currentFile = "LocalService" Or $currentFile = "NetworkService" Then ;Skip the folder, because is a system folder and should not be altered. Else ;See if the folder is for Default User, and if Default User should be updated. If $currentFile <> "Default User" Or GUICtrlRead($defaultUser) = $GUI_CHECKED Then ;Attempt to update the profile. If FileExists($profileDir & "\" & $currentFile & "\ntuser.dat") Then ;Attempt to load the ntuser.dat file into the registry. $command = $regExePath & " LOAD " & $tempKey & " """ & $profileDir & "\" & $currentFile & "\ntuser.dat" & """" RunWait($command, "", @SW_HIDE) ;Ensure the loaded key exists. RegRead($tempKey, "") If @error <> -1 Then ;There was some kind of error, skip importing the file. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Notice: Unable to load " & $profileDir & "\" & $currentFile & "\ntuser.dat.") SetError(0) ;Clear the error. Else ;Import registry settings. SetError(0) ;Set error back to none after testing. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Updating " & $profileDir & "\" & $currentFile & "\ntuser.dat.") $command = $regeditExePath & " /s """ & $tempFilePath & """" RunWait($command, "", @SW_HIDE) ;Unload the registry hive. $command = $regExePath & " UNLOAD " & $tempKey RunWait($command, "", @SW_HIDE) ;Ensure the hive was unloaded. RegRead($tempKey, "") If @error = 1 Then ;The hive was no longer present. Continue normally. SetError(0) ;Set the error back to none after testing. Else ;The hive was not unloaded as expected. Generate an error in the status box. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Unable to unload " & $profileDir & "\" & $currentFile & "\ntuser.dat.") $error = $UNABLE_TO_UNLOAD EndIf EndIf Else ;The NTUSER.DAT registry file was not found. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Notice: Unable to find " & $profileDir & "\" & $currentFile & "\ntuser.dat.") EndIf EndIf EndIf EndIf WEnd Else ;No files or folders were found in the directory. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: No files or folders were found in " & $profileDir & ".") EndIf Else ;Unable to change the working directory. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Unable to set working directory to " & $profileDir & ".") EndIf Else ;Unable to find profile path. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Unable to find " & $profileDir & ".") EndIf EndIf EndIf Else ;No sections in the registry file pointed to HKEY_CURRENT_USER. Generate an error in the status box. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Stopping process because the registry file (" & GUICtrlRead($regPathInput) & ") did not contain any entries from HKEY_CURRENT_USER.") EndIf Else ;Write the error to the status box. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Stopping process because the registry file (" & GUICtrlRead($regPathInput) & ") could not be opened.") EndIf ;Delete the temporary file. FileDelete($tempFilePath) Else ;Write the error to the statux box. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "Error: Stopping process because the temporary file (" & $tempFilePath & ") could not be deleted. Please ensure that you have the appropriate permissions.") EndIf ;Add a final entry to the status box indicating process completion. GUICtrlSetData($statusBox, GUICtrlRead($statusBox) & @CRLF & "[" & @HOUR & ":" & @MIN & ":" & @SEC & "] Process completed. Check above for errors.") ;Re-enable the action buttons. GUICtrlSetState($updateButton, $GUI_ENABLE) GUICtrlSetState($closeButton, $GUI_ENABLE) Else ;Neither checkbox was checked. MsgBox(0, "Error", "Please select which profiles you want to update. At least one box must be checked.") EndIf Else ;The registry file was not found. MsgBox(0, "Error", "The registry file (" & GUICtrlRead($regPathInput) & ") was not found.") EndIf Else ;The registry file path was empty. MsgBox(0, "Error", "You must specify the registry file to import.") EndIf EndFunc Func closeClicked() ;Exit the script. Exit EndFuncimportRegistry.exe
-
I noticed the same behavior. It seems that Word is not locking the file. In fact, I opened a file in Word and deleted it without Word complaining. However, if you open a file using autoit and then try to open the file in Word, you will get a message that it is in use. So, I think this isn't a problem with autoit.
-
You can also pass the location to iexplore.exe through the command line. iexplore.exe https://my.portal.com
-
How do I create a variable from a called command?
JMiller replied to Prodigus's topic in AutoIt General Help and Support
No prob btw I checked the help files in autoit and you have to pass the 4th parameter (2 for stdout) to the Run command to capture the output. It shows that in the above script, but it's easy to miss. -
What other options besides Pause and RunWait?
JMiller replied to Prodigus's topic in AutoIt General Help and Support
You could try the Ping() function with a timeout to see if the system responds before you run logparser.exe. -
I think psexec in combination with StdOutRead() would work. There is information about this command and an added parameter to Run() in the beta help file. Also, here is an example of it being used. Script Hmm actually i'm not sure if that would work... because psexec would spawn the child process, but that information would not necessarily be returned to the psexec process. I'll try testing it. Edit: psexec seems to contain the output from the command. I didn't have another pc handy to test remote execution, but it should work like the following code. One thing that I found is you have to terminate the psexec.exe process for some reason before the script continues. So, you'd have to find a delay that gives the command long enough to run without slowing your script down too much... _psexecTest() Func _psexecTest() Local $ipconfig = Run("psexec.exe -s ipconfig.exe", "", @SW_HIDE, 2) Local $data = "" Sleep(1000) ProcessClose("psexec.exe") While 1 $data &= StdOutRead($ipconfig) If @error = -1 Then ExitLoop WEnd MsgBox(0, "Test", $data) EndFunc
-
How do I create a variable from a called command?
JMiller replied to Prodigus's topic in AutoIt General Help and Support
Hmm I think I might have found a function in autoit that works.. see nfwu's post below. Script I noticed he is using a command called StdoutRead() to get the command output. -
How do I create a variable from a called command?
JMiller replied to Prodigus's topic in AutoIt General Help and Support
I'm not sure what you mean. Where is the IP address returned? From the command output? I don't know if this can be done with autoit, but you might consider vbscript wshshell.exec method (http://www.ss64.com/wsh/exec.html). Of course some of the resident autoit experts probably have a way to do it with autoit. -
Problem with Treeview, $TVS_CHECKBOXES and $TVS_HASBUTTONS
JMiller replied to Vier's topic in AutoIt GUI Help and Support
I had a similar issue. What I did was create an Global array to hold the current state of the upper level items. Then, I set the items state value when it is checked or unchecked. Then, before I check/uncheck the child objects, I see if the state actually changed for the parent item before changing them. If BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) = $GUI_CHECKED And $catStates[$catCounter] <> BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) Then $catStates[$catCounter] = BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) GUICtrlSetState($packElements[$packCounter], $GUI_CHECKED) This isn't really what my code looks like exactly, but I pasted the parts that were relevant. -
GUICtrlSetOnEvent variables / Application Browser
JMiller replied to JMiller's topic in AutoIt GUI Help and Support
Wow it's almost the same exact idea but a lot more thoroughly developed. I'll dig through the code for ideas. Thanks again. -
GUICtrlSetOnEvent variables / Application Browser
JMiller replied to JMiller's topic in AutoIt GUI Help and Support
Alright, cool. I'll search for his posts. I'm surprised by the quick replies. thank you -
GUICtrlSetOnEvent variables / Application Browser
JMiller replied to JMiller's topic in AutoIt GUI Help and Support
Thanks for the quick reply. I think I would need to be able to create those functions on the fly... which I'm not sure is possible. -
I figured out how to accomplish what I was trying to do by using global variables, so I thought I'd provide the completed script in case anyone else would have use. Basically, I have a collection of unattended installs that I add and update often, so the script is made to be dynamic and read what is available before drawing the treeview. The information is derived from the directory structure and informational files within specific package folders. Here's what it looks like: Here is what the directory structure looks like on the share. \\server\share_folder <- share point \common <- category folder \adobe_reader <- specific application \macromedia_flash <- specific application \etc.. <- specific application Here is the code I have so far. ;Include required files. #include <Array.au3> #include <GUIConstants.au3> ;Set script options. Opt("TrayIconHide", 1) Opt("GUIOnEventMode", 1) ;Define global variables. Global $basePath, $infoParams, $infoElements, $actionElements, $infoLabels, $categories, $packages, $catElements, $catStates, $packElements, $progressBar ;Set variables needed for GUI initialization. $basePath = @ScriptDir $infoFile = "install_info.txt" $infoParams = getInfoParams() $categories = getCategories($basePath) Dim $catStates[UBound($categories)] $packages = getPackages($basePath, $categories, $infoFile) $packagesInfo = getPackagesInfo($basePath, $categories, $packages, $infoFile, $infoParams) ;Create GUI elements. $mainWindow = GUICreate("Package Browser", 420, 400) $treeview = GUICtrlCreateTreeView(10, 30, 200, 305, BitOr($TVS_HASBUTTONS, $TVS_DISABLEDRAGDROP, $TVS_HASLINES, $TVS_LINESATROOT, $TVS_SHOWSELALWAYS, $TVS_CHECKBOXES)) $catElements = createCatTreeView($treeview, $categories, $packages) $packElements = createPackTreeView($catElements, $packages, $packagesInfo) $infoElements = createGUIInfoElements() $optionElements = createGUIOptionElements() $actionElements = createGUIActionElements() $progressBar = createGUIProgressBar() ;Set close event. GUISetOnEvent($GUI_EVENT_CLOSE, "closeClicked") ;Build the GUI. GUISetState(@SW_SHOW) While 1 Sleep(1000) ;Idle around WEnd ;Define script functions. Func getInfoParams() ;Return the parameters that will be in $infoFile. Dim $infoParams[8] $infoParams[0] = 7 $infoParams[1] = "Title" $infoParams[2] = "Description" $infoParams[3] = "Version" $infoParams[4] = "Updated" $infoParams[5] = "Install" $infoParams[6] = "Parameters" $infoParams[7] = "MSIBased" Return $infoParams EndFunc Func getCategories($basePath) ;Returns an array in the format totalCategories, "categoryFolder", "...". Local $categories[1] ;Define the categories array. $categories[0] = 0 ;Specify the number of categories. $catHandle = FileFindFirstFile($basePath & "\*") If $catHandle <> -1 Then ;Loop through each directory and add it to the $categories array. While 1 $catFolder = FileFindNextFile($catHandle) If @error Then ExitLoop If $catFolder = "." Or $catFolder = ".." Then ContinueLoop If StringInStr(FileGetAttrib($basePath & "\" & $catFolder), "D") = 0 Then ContinueLoop ReDim $categories[UBound($categories) + 1] $categories[0] = $categories[0] + 1 $categories[UBound($categories) - 1] = $catFolder WEnd FileClose($catHandle) return $categories Else ;An error occcured when accessing the direcotry. MsgBox(0, "Error", "Unable to access directory (" & $basePath & ") in getCategories.") return $categories EndIf EndFunc Func getPackages($basePath, $categories, $infoFile) ;Returns an array in the format totalPackages, "packageFolder:categoryOffset", "...". Local $packages[1] ;Define the packages array. $packages[0] = 0 ;Specify the number of packages. If FileExists($basePath) Then ;Continue the script. If $categories[0] > 0 Then ;At least one category was found. For $catCounter = 1 To $categories[0] $catHandle = FileFindFirstFile($basePath & "\" & $categories[$catCounter] & "\*") If $catHandle <> -1 Then ;Loop through each directory and add it to the $categories array. While 1 $packFolder = FileFindNextFile($catHandle) If @error Then ExitLoop If $packFolder = "." Or $packFolder = ".." Then ContinueLoop If StringInStr(FileGetAttrib($basePath & "\" & $categories[$catCounter] & "\" & $packFolder), "D") = 0 Then ContinueLoop If FileExists($basePath & "\" & $categories[$catCounter] & "\" & $packFolder & "\" & $infoFile) = 0 Then ContinueLoop ReDim $packages[UBound($packages) + 1] $packages[0] = $packages[0] + 1 $packages[UBound($packages) - 1] = $packFolder & ":" & $catCounter WEnd FileClose($catHandle) EndIf Next return $packages Else ;No categories were found. MsgBox(0, "Error", "No categories found in getPackages.") EndIf Else ;Generate an error and terminate the script. MsgBox(0, "Error", "Base path (" & $basePath & ") not found in getPackages." Exit EndIf EndFunc Func getPackagesInfo($basePath, $categories, $packages, $infoFile, $infoParams) ;Returns an array in the format totalPackages, "infoParam1`infoParam2`...`. Local $packagesInfo[$packages[0] + 1] $packagesInfo[0] = $packages[0] For $packCounter = 1 To $packages[0] $packagesInfo[$packCounter] = "" $splitPackage = StringSplit($packages[$packCounter], ":") $packageFolder = $splitPackage[1] $packageCat = $splitPackage[2] $catFolder = $categories[$packageCat] For $paramCounter = 1 To UBound($infoParams) - 1 $packagesInfo[$packCounter] = $packagesInfo[$packCounter] & getParamValue($basePath & "\" & $catFolder & "\" & $packageFolder & "\" & $infoFile, $infoParams[$paramCounter]) If $paramCounter < UBound($infoParams) - 1 Then $packagesInfo[$packCounter] = $packagesInfo[$packCounter] & "`" EndIf Next Next ;_ArrayDisplay($packagesInfo, "Packages Info") Return $packagesInfo EndFunc Func getParamValue($infoPath, $paramName) ;Return the specified param value. Use N/A if not found. $paramValue = "N/A" If FileExists($infoPath) Then $fileHandle = FileOpen($infoPath, 0) ; Check if file opened for reading OK If $fileHandle <> -1 Then While 1 $line = FileReadLine($fileHandle) If @error = -1 Then ExitLoop If StringInStr($line, $paramName & "=""") <> 0 Then $startPoint = StringInStr($line, """") + 1 $endPoint = StringInStr($line, """", 0, 2) - $startPoint $value = StringMid($line, $startPoint, $endPoint) $paramValue = $value EndIf Wend EndIf FileClose($fileHandle) EndIf return $paramValue EndFunc Func createCatTreeView($treeview, $categories, $packages) ;For each category with elements, give it an upper level treeview item. Local $catElements[1] ;Define the categories array. $catElements[0] = 0 ;Specify the number of categories. $catTotals = getCatTotals($categories, $packages) For $catCounter = 1 To $categories[0] ReDim $catElements[UBound($catElements) + 1] If $catTotals[$catCounter] > 0 Then $catElements[$catCounter] = GUICtrlCreateTreeViewitem($categories[$catCounter], $treeview) GUICtrlSetOnEvent($catElements[$catCounter], "categoryClicked") Else $catElements[$catCounter] = 0 EndIf Next Return $catElements EndFunc Func createPackTreeView($catElements, $packages, $packagesInfo) ;For each of the packages, add it as a sub option for the containing category. Local $packElements[1] ;Define the package array. $packElements[0] = 0 ;Specify the number of packages. For $packCounter = 1 To $packages[0] $splitPackage = StringSplit($packages[$packCounter], ":") $packageFolder = $splitPackage[1] $packageCat = $splitPackage[2] ReDim $packElements[UBound($packElements) + 1] $packElements[$packCounter] = GUICtrlCreateTreeViewitem($packageFolder, $catElements[$packageCat]) GUICtrlSetOnEvent($packElements[$packCounter], "packageClicked") Next Return $packElements EndFunc Func createGUIInfoElements() ;Create GUI elements for population with information. Dim $infoElements[8] Dim $infoLabels[2] GUICtrlCreateLabel("Select the packages to install", 10, 8, 190, 15) $infoElements[0] = 7 $packageGroup = GUICtrlCreateGroup("Package Information", 220, 25, 190, 80) $infoElements[1] = GUICtrlCreateLabel("", 230, 43, 170, 32) ;Title field. $infoLabels[0] = GUICtrlCreateLabel("Version:", 230, 63, 50, 16) GUICtrlSetState($infoLabels[0], $GUI_HIDE) $infoElements[3] = GUICtrlCreateLabel("", 270, 63, 100, 16) ;Version field. $infoLabels[1] = GUICtrlCreateLabel("Updated:", 230, 83, 50, 16) GUICtrlSetState($infoLabels[1], $GUI_HIDE) $infoElements[4] = GUICtrlCreateLabel("", 276, 83, 100, 16) ;Updated field. $descriptionGroup = GUICtrlCreateGroup("Package Description", 220, 110, 190, 140) $infoElements[2] = GUICtrlCreateLabel("", 230, 128, 170, 120) ;Description field. $infoElements[5] = 0 $infoElements[6] = 0 $infoElements[7] = 0 Return $infoElements EndFunc Func createGUIOptionElements() ;Create GUI elements used to customize program options. Dim $optionElements[4] $optionElements[0] = 3 $optionGroup = GUICtrlCreateGroup("Installation Options", 220, 255, 190, 80) $optionElements[1] = GUICtrlCreateCheckbox("Copy MSI-based packages", 230, 273, 170, 16) GUICtrlSetState($optionELements[1], $GUI_CHECKED) $optionElements[2] = GUICtrlCreateCheckbox("Delete existing (if present)", 230, 293, 170, 16) $optionElements[3] = GUICtrlCreateCheckbox("Pause after copying", 230, 313, 170, 16) Return $optionElements EndFunc Func createGUIActionElements() ;Create GUI elements used to trigger program actions. Dim $actionElements[3] $actionElements[0] = 2 $actionElements[1] = GUICtrlCreateButton("Begin Installation", 102, 368, 110, 25) GUICtrlSetOnEvent($actionElements[1], "beginInstallation") $actionElements[2] = GUICtrlCreateButton("Close Program", 219, 368, 110, 25) GUICtrlSetOnEvent($actionElements[2], "closeClicked") Return $actionElements EndFunc Func createGUIProgressBar() $progressBar = GUICtrlCreateProgress(10, 344, 400, 17) Return $progressBar EndFunc Func getCatTotals($categories, $packages) ;Get the total packages in each category. Local $catTotals[$categories[0] + 1] $catTotals[0] = $categories[0] ;For each of the categories... For $catCounter = 1 To $categories[0] $catTotals[$catCounter] = 0 ;Go through each package to see if it is a member of that category. Increment $catTotals[$catCounter] by 1 if so. For $packCounter = 1 To $packages[0] $splitPackage = StringSplit($packages[$packCounter], ":") $packageFolder = $splitPackage[1] $packageCat = $splitPackage[2] If $packageCat = $catCounter Then $catTotals[$catCounter] = $catTotals[$catCounter] + 1 EndIf Next Next Return $catTotals EndFunc Func categoryClicked() ;Nothing yet... Dim $catElements, $catStates, $categories, $packElements, $packages, $infoElements, $infoLabels $setPackageState = 0 $catText = "" $packText = "" ;Clear text defining label areas. For $labelCounter = 0 To UBound($infoLabels) - 1 GUICtrlSetState($infoLabels[$labelCounter], $GUI_HIDE) Next ;Clear label values if present. For $infoCounter = 1 To UBound($infoElements) - 1 If $infoElements[$infoCounter] <> 0 Then GUICtrlSetData($infoElements[$infoCounter], "") EndIf Next ;If the main category was checked, check all packages in it. If it was unchecked, uncheck all packages. For $catCounter = 1 To $categories[0] If $catStates[$catCounter] = "" Then ;Make $GUI_UNCHECKED be the default category state. $catStates[$catCounter] = $GUI_UNCHECKED EndIf If @GUI_CtrlID = $catElements[$catCounter] Then ;Modify the package states only if the category state has actually changed. If BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) = $GUI_CHECKED And $catStates[$catCounter] <> BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) Then $catStates[$catCounter] = BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_CHECKED) $setPackageState = $GUI_CHECKED ElseIf BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_UNCHECKED) = $GUI_UNCHECKED And $catStates[$catCounter] <> BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_UNCHECKED) Then $catStates[$catCounter] = BitAND(GUICtrlRead(@GUI_CtrlID), $GUI_UNCHECKED) $setPackageState = $GUI_UNCHECKED EndIf ;Set the appropriate package state if needed. If $setPackageState <> 0 Then For $packCounter = 1 To $packages[0] $splitPackage = StringSplit($packages[$packCounter], ":") $packageFolder = $splitPackage[1] $packageCat = $splitPackage[2] If $packageCat = $catCounter Then GUICtrlSetState($packElements[$packCounter], $setPackageState) EndIf Next EndIf ExitLoop EndIf Next EndFunc Func packageClicked() ;Nothing yet... Dim $infoElements, $infoParams, $infoLabels, $packElements, $packages, $packagesInfo ;Show all labels showing where label values will go. For $labelCounter = 0 To UBound($infoLabels) - 1 GUICtrlSetState($infoLabels[$labelCounter], $GUI_SHOW) Next ;Find the selected package and populate the information fields. For $packCounter = 1 To $packages[0] If @GUI_CtrlID = $packElements[$packCounter] Then $packageInfo = StringSplit($packagesInfo[$packCounter], "`") For $infoCounter = 1 To UBound($infoElements) - 1 If $infoElements[$infoCounter] <> 0 Then GUICtrlSetData($infoElements[$infoCounter], $packageInfo[$infoCounter]) EndIf Next ExitLoop EndIf Next EndFunc Func beginInstallation() ;Find out what, if any, packages were selected and install them. Dim $basePath, $categories, $packages, $packElements, $packagesInfo, $optionElements, $actionElements, $progressBar GUICtrlSetState($actionElements[1], $GUI_DISABLE) GUICtrlSetState($actionElements[2], $GUI_DISABLE) Dim $installPacks[1] $installPacks[0] = 0 $systemDrive = EnvGet("systemdrive") $localSource = $systemDrive & "\Packages" If FileExists($localSource) Then If BitAND(GUICtrlRead($optionElements[2]), $GUI_CHECKED) = $GUI_CHECKED Then ;Delete the existing local source and create a new one. DirRemove($localSource, 1) DirCreate($localSource) EndIf Else ;Create a local source folder. DirCreate($localSource) EndIf For $packCounter = 1 To $packages[0] If BitAND(GUICtrlRead($packElements[$packCounter]), $GUI_CHECKED) = $GUI_CHECKED Then ;The package was selected for installation. $packageInfo = StringSplit($packagesInfo[$packCounter], "`") $splitPackage = StringSplit($packages[$packCounter], ":") $packageFolder = $splitPackage[1] $packageCat = $splitPackage[2] If BitAND(GUICtrlRead($optionElements[1]), $GUI_CHECKED) = $GUI_CHECKED And $packageInfo[7] = 1 Then ;Create a local installation source for the package. If Not FileExists($localSource & "\" & $categories[$packageCat] & "\" & $packageFolder) Then DirCreate($localSource & "\" & $categories[$packageCat]) EndIf $relativePath = "\" & $categories[$packageCat] & "\" & $packageFolder _FileCopy($basePath & $relativePath, $localSource & "\" & $categories[$packageCat]) ReDim $installPacks[UBound($installPacks) + 1] $installPacks[0] = $installPacks[0] + 1 $installPacks[$installPacks[0]] = """" & $localSource & $relativePath & "\" & $packageInfo[5] & """" & $packageInfo[6] Else ;Do not create a local installation source for the package. $relativePath = "\" & $categories[$packageCat] & "\" & $packageFolder ReDim $installPacks[UBound($installPacks) + 1] $installPacks[0] = $installPacks[0] + 1 $installPacks[$installPacks[0]] = """" & $basePath & $relativePath & "\" & $packageInfo[5] & """" & $packageInfo[6] EndIf EndIf Next If $installPacks[0] > 0 Then ;_ArrayDisplay($installPacks, "Install List") disableZoneChecking() If BitAND(GUICtrlRead($optionElements[1]), $GUI_CHECKED) = $GUI_CHECKED And FileExists($localSource) Then ;If a local source was created, remove the read-only attribute. RunWait("attrib.exe -r " & $localSource & "\* /s /d", "", @SW_HIDE) If BitAND(GUICtrlRead($optionElements[3]), $GUI_CHECKED) = $GUI_CHECKED Then ;If the user specified to pause after source creation, create a message box to pause the script. MsgBox(0, "Pausing", "Local source created. Please click OK to begin package installation.") EndIf EndIf $progressIncrement = 100 / $installPacks[0] $increment = $progressIncrement For $installCounter = 1 To $installPacks[0] RunWait(@ComSpec & " /c " & $installPacks[$installCounter], "", @SW_HIDE) If $installCounter = $installPacks[0] Then ;Set the progress bar to 100%. GUICtrlSetData($progressBar, 100) Else ;Increment the progress bar. GUICtrlSetData($progressBar, $increment) $increment = $increment + $progressIncrement EndIf Next MsgBox(0, "Complete", "Selected packages installed.") GUICtrlSetData($progressBar, 0) enableZoneChecking() EndIf GUICtrlSetState($actionElements[1], $GUI_ENABLE) GUICtrlSetState($actionElements[2], $GUI_ENABLE) EndFunc Func _FileCopy($fromFile, $toFile) Local $FOF_RESPOND_YES = 16 Local $FOF_SIMPLEPROGRESS = 256 $winShell = ObjCreate("shell.application") $winShell.namespace($toFile).CopyHere($fromFile, $FOF_RESPOND_YES) EndFunc Func disableZoneChecking() ;Disable IE zone checking so security warnings do not appear when installing unsigned packages. EnvSet("SEE_MASK_NOZONECHECKS", 1) EndFunc Func enableZoneChecking() ;Re-enable IE zone checking. EnvSet("SEE_MASK_NOZONECHECKS") EndFunc Func addSiteToTrustedSites($site) ;Add the specified site to the Trusted Sites zone in IE. RegWrite("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\" & $site, "*", "REG_DWORD", 2) EndFunc Func removeSiteFromTrustedSites($site) ;Remove the specified site from the Trusted Sites zone in IE. RegDelete("HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Internet Settings\ZoneMap\Domains\" & $site) EndFunc Func closeClicked() ;Exit the script. Exit EndFunc