Jump to content

Script won't start up on restart


Recommended Posts

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:

#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

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:

#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

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 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

Also, 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 includes

variables

function definitions

main function

Edited by TheSharocko
Link to comment
Share on other sites

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

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

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

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

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

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

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

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:

#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

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 this

RegWrite($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

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 account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...