TheSharocko Posted July 1, 2011 Share Posted July 1, 2011 I'm trying to write this script to fix a couple of known errors with an installer I have. The script should theoretically look for some registry issues and repair them and perform restarts as necessary followed by the installation of the program itself. A few restarts are required in a few spots and to handle this I added a registry entry into the RunOnce directory in the HKCU registry. Here's the script: expandcollapse popup#RequireAdmin AutoItSetOption("TrayAutoPause", 0) ;through testing code dies about here when it tries to start back up Global $os = @OSVersion Global $bit = @OSArch Global $log_file = ".\SEP_fix_installer.log" Global $SEP32_path = ".\SEP_11_RU6a_x32.exe" Global $SEP64_path = ".\SEP_11_RU6a_x64.exe" Global $restart = 0 Global $timestamp = @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC ;creates time stamp for log Global $log_title = $timestamp & " -- SEP Installer Log File Initialized" & @CRLF ;first line to be written to log\ Global $read = "" Global $stage = 0 Global $stage_key = "Stage" Global $stage_inc = 10 Global $script_key = "SEP_Installation" Global $runonce_key = "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" Func CreateLog() FileOpen($log_file, 2) FileWriteLine($log_file, $log_title) FileWriteLine($log_file, "") FileClose($log_file) EndFunc Func WriteLog($msg) FileWriteLine($log_file, $msg) EndFunc Func InstallSEP() If ($bit == "X86") Then FileWriteLine($log_file, "Now installing SEP using installer for 32 bit.") Run($SEP32_path) Else FileWriteLine($log_file, "Now installing SEP using installer for 64 bit.") Run($SEP64_path) EndIf WinWaitActive("Symantec Endpoint Protection", "IS ANY OTHER ANTI-VIRUS") Send("{TAB}") Send("{ENTER}") WinWaitActive("Symantec", "Symantec Endpoint Protection 11 Install") Send("{ENTER}") EndFunc Func NextStage() $stage += $stage_inc RegWrite($runonce_key, $stage_key, "REG_DWORD", $stage) WriteLog("Stage saved with value " & RegRead($runonce_key, $stage_key)) If ($restart == 1) Then WriteLog("Restart is required.") $restart = 0 RegWrite($runonce_key, $script_key, "REG_SZ", @ScriptFullPath) WriteLog("Wrote registry with value " & RegRead($runonce_key, $script_key)) Shutdown(2) Exit 0 EndIf EndFunc $start = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") If Not @error Then WriteLog("There was no error reading the file.") Run($start) WriteLog("Re-ran script to see if this trick works.") RegDelete("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") WriteLog("Deleted registry entry so won't run again.") EndIf If Not FileExists($log_file) Then CreateLog() $stage = RegRead($runonce_key, $stage_key) If @error Then $stage = 0 WriteLog("Registry entry couldn't be read. Returned error" & @error) WriteLog("$stage set to " & $stage) Else WriteLog("Registry was read. $stage will be set to " & $stage) EndIf While (True) WriteLog("Currently on stage " & $stage) Switch $stage Case 0 RegWrite("HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders", "AppData", "REG_EXPAND_SZ", "%USERPROFILE%\AppData\Roaming") WriteLog("Fix registry entry that causes rollback issue.") Case 10 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then $stage += $stage_inc WriteLog("Did not find PendingFileRenameOperations registry entry. Skipping next stage.") Else $restart = 1 WriteLog("Found PendingFileRenameOperations registry entry. Will restart to see if it disappears.") EndIf Case 20 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then WriteLog("PendingFileRenameOperations registry entry disappeared. Moving on.") Else $restart = 1 RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") WriteLog("PendingFileRenameOperations registry entry still exists. Deleted entry. Computer will be restarted.") EndIf Case 30 WriteLog("Starting SEP installation.") InstallSEP() WriteLog("Finished SEP installation.") Case 40 RegDelete($runonce_key, $stage_key) WriteLog("Removed registry entry to store $stage value upon restart. Now closing script.") Exit Case Default WriteLog("Something went wrong. Now closing script.") Exit EndSwitch NextStage() WEnd The code is hanging after requiring admin after it restarts in Case 20. Ideas how to fix this? Link to comment Share on other sites More sharing options...
sleepydvdr Posted July 1, 2011 Share Posted July 1, 2011 Your code is complicated, but I think the problem is InstallSEP() function. You are simply running the program. You should use RunAs and insert administrative credentials. By the way, rearranging your code makes it easier to understand. I like to place all sequentially read lines together at the top of the script and throw functions at the end. Something like this: expandcollapse popup#RequireAdmin AutoItSetOption("TrayAutoPause", 0) ;through testing code dies about here when it tries to start back up Global $os = @OSVersion Global $bit = @OSArch Global $log_file = ".\SEP_fix_installer.log" Global $SEP32_path = ".\SEP_11_RU6a_x32.exe" Global $SEP64_path = ".\SEP_11_RU6a_x64.exe" Global $restart = 0 Global $timestamp = @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC ;creates time stamp for log Global $log_title = $timestamp & " -- SEP Installer Log File Initialized" & @CRLF ;first line to be written to log\ Global $read = "" Global $stage = 0 Global $stage_key = "Stage" Global $stage_inc = 10 Global $script_key = "SEP_Installation" Global $runonce_key = "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" $start = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") If Not @error Then WriteLog("There was no error reading the file.") Run($start) WriteLog("Re-ran script to see if this trick works.") RegDelete("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") WriteLog("Deleted registry entry so won't run again.") EndIf If Not FileExists($log_file) Then CreateLog() While (True) WriteLog("Currently on stage " & $stage) Switch $stage Case 0 RegWrite("HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders", "AppData", "REG_EXPAND_SZ", "%USERPROFILE%\AppData\Roaming") WriteLog("Fix registry entry that causes rollback issue.") Case 10 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then $stage += $stage_inc WriteLog("Did not find PendingFileRenameOperations registry entry. Skipping next stage.") Else $restart = 1 WriteLog("Found PendingFileRenameOperations registry entry. Will restart to see if it disappears.") EndIf Case 20 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then WriteLog("PendingFileRenameOperations registry entry disappeared. Moving on.") Else $restart = 1 RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") WriteLog("PendingFileRenameOperations registry entry still exists. Deleted entry. Computer will be restarted.") EndIf Case 30 WriteLog("Starting SEP installation.") InstallSEP() WriteLog("Finished SEP installation.") Case 40 RegDelete($runonce_key, $stage_key) WriteLog("Removed registry entry to store $stage value upon restart. Now closing script.") Exit Case Default WriteLog("Something went wrong. Now closing script.") Exit EndSwitch NextStage() WEnd $stage = RegRead($runonce_key, $stage_key) If @error Then $stage = 0 WriteLog("Registry entry couldn't be read. Returned error" & @error) WriteLog("$stage set to " & $stage) Else WriteLog("Registry was read. $stage will be set to " & $stage) EndIf ; Now begin functions: Func CreateLog() FileOpen($log_file, 2) FileWriteLine($log_file, $log_title) FileWriteLine($log_file, "") FileClose($log_file) EndFunc Func WriteLog($msg) FileWriteLine($log_file, $msg) EndFunc Func InstallSEP() If ($bit == "X86") Then FileWriteLine($log_file, "Now installing SEP using installer for 32 bit.") Run($SEP32_path) Else FileWriteLine($log_file, "Now installing SEP using installer for 64 bit.") Run($SEP64_path) EndIf WinWaitActive("Symantec Endpoint Protection", "IS ANY OTHER ANTI-VIRUS") Send("{TAB}") Send("{ENTER}") WinWaitActive("Symantec", "Symantec Endpoint Protection 11 Install") Send("{ENTER}") EndFunc Func NextStage() $stage += $stage_inc RegWrite($runonce_key, $stage_key, "REG_DWORD", $stage) WriteLog("Stage saved with value " & RegRead($runonce_key, $stage_key)) If ($restart == 1) Then WriteLog("Restart is required.") $restart = 0 RegWrite($runonce_key, $script_key, "REG_SZ", @ScriptFullPath) WriteLog("Wrote registry with value " & RegRead($runonce_key, $script_key)) Shutdown(2) Exit 0 EndIf EndFunc #include <ByteMe.au3> Link to comment Share on other sites More sharing options...
TheSharocko Posted July 1, 2011 Author Share Posted July 1, 2011 (edited) I would concur with your solution if it ever entered the InstallSEP() function. It runs Case 0 and Case 10 inside the switch statement, then restarts the computer. After the restart, it should start the script in Case 20 then follow with 30 and 40 but rather it asks for administrative rights and doesn't continue with the script. My last log file looked like the following:06/28/2011 11:05:57 -- SEP Installer Log File InitializedRegistry entry couldn't be read. Returned error-1$stage set to 0Currently on stage 0Fix registry entry that causes rollback issue.Stage saved with value 10Currently on stage 10Found PendingFileRenameOperations registry entry. Will restart to see if it disappears.Stage saved with value 20Restart is required.Wrote registry with value C:\Users\Clean Room\Desktop\StimPak\Virus Removal\Symantec Endpoint Protection\SEP.exeAlso, I'm a C and java programmer so I just have habits to arrange my code to the syntax required in those languages which is:library includesvariablesfunction definitionsmain function Edited July 1, 2011 by TheSharocko Link to comment Share on other sites More sharing options...
martin Posted July 1, 2011 Share Posted July 1, 2011 Instead of adding an entry in the RunOnce section of the registry, I have had success using the following approach. Create a scheduled task which runs your program. Give maximum rights etc and set it to run on startup. It seemed to get round programs asking for admin rights for me, presumably because I had given the task admin rights to run your program. I had an installation where after installing the program it ran fine but after updating it the user would be ask for permission to run it and this was the only way I could get round it (other than renaming the exe which worked but gave me other problems). Not guaranteed to work since I have very limited experience of doing this. If it works for you then you would have to find another way to stop it running when you don't want it to run. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
TheSharocko Posted July 1, 2011 Author Share Posted July 1, 2011 Problem with this suggestion is that I'm running this script on multiple machines and I really don't want to have to schedule tasks on each machine unless you have a suggestion as far as a code snippet goes =) Link to comment Share on other sites More sharing options...
martin Posted July 1, 2011 Share Posted July 1, 2011 Problem with this suggestion is that I'm running this script on multiple machines and I really don't want to have to schedule tasks on each machine unless you have a suggestion as far as a code snippet goes =)Sorry I haven't. It is very strange that the script doesn't even get as far as the global variable definitions. Are you sure that's correct? There isn't some OnAUtoItStartRegister you haven't shown? Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
TheSharocko Posted July 2, 2011 Author Share Posted July 2, 2011 Sorry I haven't. It is very strange that the script doesn't even get as far as the global variable definitions. Are you sure that's correct? There isn't some OnAUtoItStartRegister you haven't shown?I posted all the code I wrote, but what is this OnAutoItStart Register you speak of? This may be the fix I'm looking for. Link to comment Share on other sites More sharing options...
GEOSoft Posted July 2, 2011 Share Posted July 2, 2011 It looks like your problem is more related to the RunOnce entry. Windows should run a RunOnce entry on Startup and then delete the entry . You are attempting to read a reg value that may not exist at that point. In AutoIt syntax terms Windows looks at them as Run() as opposed to RunWait(). George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
TheSharocko Posted July 2, 2011 Author Share Posted July 2, 2011 I thought that may be an issue later down the road but I strictly speaking starting the script upon restart. Are you suggesting that I move it to Run directory rather than the RunOnce directory? If so, I've already tested that theory and unfortunately that did not work either. I have another theory and if anyone has some feedback that would be great. As GEOSoft suggested, what if I wrote a second registry entry in which to tell the script to run itself from? Does anyone believe this might work? Link to comment Share on other sites More sharing options...
GEOSoft Posted July 3, 2011 Share Posted July 3, 2011 I would consider something like writing a separate registry key to store the value you want passed then read that when you start the program, change it as required, restart, delete the key on completion, OR you could pass the value to the command line for your script at $CmdLine and start it with the reguired parameter. Of course that would mean that you have to change your $stage to read $CmdLine[1]. These are ideas just off the top of my head without testing so handle accordingly. George Question about decompiling code? Read the decompiling FAQ and don't bother posting the question in the forums.Be sure to read and follow the forum rules. -AKA the AutoIt Reading and Comprehension Skills test.*** The PCRE (Regular Expression) ToolKit for AutoIT - (Updated Oct 20, 2011 ver:3.0.1.13) - Please update your current version before filing any bug reports. The installer now includes both 32 and 64 bit versions. No change in version number. Visit my Blog .. currently not active but it will soon be resplendent with news and views. Also please remove any links you may have to my website. it is soon to be closed and replaced with something else. "Old age and treachery will always overcome youth and skill!" Link to comment Share on other sites More sharing options...
TheSharocko Posted July 3, 2011 Author Share Posted July 3, 2011 Okay. I see how that would help the program with that bug if it were to occur. The real issue is the start up of the script upon restart. It just doesn't do it. Anyone else got an idea? Link to comment Share on other sites More sharing options...
martin Posted July 3, 2011 Share Posted July 3, 2011 Okay. I see how that would help the program with that bug if it were to occur. The real issue is the start up of the script upon restart. It just doesn't do it. Anyone else got an idea?You have confused me, though that is not difficult.In your first post you said that "code dies about here" so you were saying it started and had asked for permission to run. In my last post I asked if you were sure but you didn't confirm or deny. Now you are saying that it doesn't start? If so then the problem must be much more simple to solve and what GeoSoft suggested makes more sense to me, but if not then please clarify. Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
TheSharocko Posted July 3, 2011 Author Share Posted July 3, 2011 I guess I didn't state that very well. My apologies. It is a problem that I find difficult to describe. Basically it runs through this code: expandcollapse popup#RequireAdmin AutoItSetOption("TrayAutoPause", 0) Global $os = @OSVersion Global $bit = @OSArch Global $log_file = ".\SEP_fix_installer.log" Global $SEP32_path = ".\SEP_11_RU6a_x32.exe" Global $SEP64_path = ".\SEP_11_RU6a_x64.exe" Global $restart = 0 Global $timestamp = @MON & "/" & @MDAY & "/" & @YEAR & " " & @HOUR & ":" & @MIN & ":" & @SEC ;creates time stamp for log Global $log_title = $timestamp & " -- SEP Installer Log File Initialized" & @CRLF ;first line to be written to log\ Global $read = "" Global $stage = 0 Global $stage_key = "Stage" Global $stage_inc = 10 Global $script_key = "SEP_Installation" Global $runonce_key = "HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce" Func CreateLog() FileOpen($log_file, 2) FileWriteLine($log_file, $log_title) FileWriteLine($log_file, "") FileClose($log_file) EndFunc Func WriteLog($msg) FileWriteLine($log_file, $msg) EndFunc Func NextStage() $stage += $stage_inc RegWrite($runonce_key, $stage_key, "REG_DWORD", $stage) WriteLog("Stage saved with value " & RegRead($runonce_key, $stage_key)) If ($restart == 1) Then WriteLog("Restart is required.") $restart = 0 RegWrite($runonce_key, $script_key, "REG_SZ", @ScriptFullPath) WriteLog("Wrote registry with value " & RegRead($runonce_key, $script_key)) Shutdown(2) Exit 0 EndIf EndFunc $start = RegRead("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") If Not @error Then WriteLog("There was no error reading the file.") Run($start) WriteLog("Re-ran script to see if this trick works.") RegDelete("HKCU\Software\Microsoft\Windows\CurrentVersion\RunOnce", "SEP_Installation") WriteLog("Deleted registry entry so won't run again.") EndIf If Not FileExists($log_file) Then CreateLog() $stage = RegRead($runonce_key, $stage_key) If @error Then $stage = 0 WriteLog("Registry entry couldn't be read. Returned error" & @error) WriteLog("$stage set to " & $stage) Else WriteLog("Registry was read. $stage will be set to " & $stage) EndIf While (True) WriteLog("Currently on stage " & $stage) Switch $stage Case 0 RegWrite("HKEY_USERS\.DEFAULT\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders", "AppData", "REG_EXPAND_SZ", "%USERPROFILE%\AppData\Roaming") WriteLog("Fix registry entry that causes rollback issue.") Case 10 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then $stage += $stage_inc WriteLog("Did not find PendingFileRenameOperations registry entry. Skipping next stage.") Else $restart = 1 WriteLog("Found PendingFileRenameOperations registry entry. Will restart to see if it disappears.") EndIf Case 20 $read = RegRead("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") If @error Then WriteLog("PendingFileRenameOperations registry entry disappeared. Moving on.") Else $restart = 1 RegDelete("HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager", "PendingFileRenameOperations") WriteLog("PendingFileRenameOperations registry entry still exists. Deleted entry. Computer will be restarted.") EndIf EndSwitch NextStage() WEnd Which creates this log: 06/28/2011 11:05:57 -- SEP Installer Log File Initialized Registry entry couldn't be read. Returned error-1 $stage set to 0 Currently on stage 0 Fix registry entry that causes rollback issue. Stage saved with value 10 Currently on stage 10 Found PendingFileRenameOperations registry entry. Will restart to see if it disappears. Stage saved with value 20 Restart is required. Wrote registry with value C:\Users\Clean Room\Desktop\StimPak\Virus Removal\Symantec Endpoint Protection\SEP.exe The computer it runs on reboots. On start up, I get a request for the UAC and then the script does not appear to continue further than the #RequireAdmin on line 1. I've tried logging it to see if that's really where it stops and based off of everything I've tried, that appears to be true. My current assumption is that there is a problem with this set of lines: RegWrite($runonce_key, $script_key, "REG_SZ", @ScriptFullPath) WriteLog("Wrote registry with value " & RegRead($runonce_key, $script_key)) Shutdown(2) Exit 0 From my understanding, writing the script's path to the RunOnce directory in HKCU on a Window's registry should start the problem upon restart. Apparently this is wrong and I guess I'm wondering if there is a reason for this or a better option than the one I'm trying specifically for the reinitialization of the script after a reboot. I hope this clarifies the problem. =) Link to comment Share on other sites More sharing options...
martin Posted July 7, 2011 Share Posted July 7, 2011 The only time I use RunOnce is to tidy up after an uninstall and I have only ever used HKLM not HKCU but I don't see that's relevant. I also insert an exclamation mark at the start of the $script_key, ('!' & $scriptkey) because that indicates to windows that the entry shouldn't be deleted untill the program to be run has executed successfully.I would try having a registry setting for a run number which gets incremented every time the program runs. Then instead of writing the way you do to the registry for RunOnce, I would try something like thisRegWrite($runonce_key, $script_key & $runNumber, "REG_SZ", @ScriptFullPath)so that you aren't rying to replace the registry entry which Windows is trying to delete in case that's the problem. Especially if you used the exclamation idea because Windows would try to delete the key after the program had run but it would already have been altered. (If my undedrstanding is correct.) Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script. Link to comment Share on other sites More sharing options...
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now