Sign in to follow this  
Followers 0
Webs

Schedule Script that Searches Local Registry

4 posts in this topic

#1 ·  Posted (edited)

So my script is below and what I want to do is figure out a way to schedule this script so that it runs by itself. The script searches the registry for a specified string which is stored in an INI file. When found the script notifies an email group that the server this script is running on has the proxy enabled. This script will help us pass an upcoming audit so we need this functionality.

The problem is I don't have the time to run this script on 60-70 servers myself. I was hoping to automate this script and schedule it to run daily with a service account. I have tested it locally on my machine and it works just fine when I run the EXE. When I schedule it I can see it running in Task Manager but it just keeps running chewing up CPU resources. Even though when I run it locally on my machine I do not have this problem. I think the problem is a scheduled task can only interact with the registry using an account that is currently logged in.

I am open to ideas that are outside the box or any solutions someone can pass along that help me solve the problem of running a script that searches the registry for a specific item and runs on 60-70 servers. I was thinking about trying to use psexec, but it seems my problem is that an account needs to be logged in and running this script for the gui of the registry to be accessible.

Any ideas?

BTW, the attached zip is the INI file used by the script.

#include <Array.au3>
#include <GuiConstantsEx.au3>
#include <ClipBoard.au3>
#include <WinAPI.au3>
#include <WindowsConstants.au3>
#include <INet.au3>


;   NOTE:
;The following variable will need to be updated if the path this script runs from changes
;
$iniFile = "C:\regsearch\settings.ini"                      ;ini file storing items for SendMail function and path variables


$searchFinClass = "#32770"                                  ;Class value of "finished searching registry" window
$searchFinTitle = "Registry Editor"                         ;Title of "finished searching registry" window
Dim $aPathsFound[10] = ["Beginning"]                        ;array of found values
$loopEnd = 8                                                ;value loop run to, set to 8 loop will run 9 tiumes, counter starts at 0
$loopCounter = 0                                            ;loop counter that keeps track of the number of times loop has ran
Local $boolFinSearchFound = False                           ;boolean used to determine if "finished searching registry" window is found
$regKeyFound = False                                        ;boolean used to determine if all reg keys have been found
$emailSubjectError = "Registry Found Script Error: "        ;variable with a commonly used string for the subject of error notifications

;SendMail function variables
$emailSubject = ""
$emailBody0 = ""
$emailBody2 = ""
$emailBody4 = ""
$emailBody5 = ""

;read path information from sendmail.ini
$pathDrive = IniRead ( $iniFile, "Settings", "1", "Error" ) ;path drive letter
$pathRoot = IniRead ( $iniFile, "Settings", "2", "Error" ) ;path root folder location
$regEdit = IniRead ( $iniFile, "Settings", "3", "Error" ) ;Registry Editory and full path
$regSearch = IniRead ( $iniFile, "Settings", "4", "Error" ) ;registry key to search for
$pathFull = $pathDrive & $pathRoot

;Check if script was able to read from INI
If $pathDrive = "Error" or $pathRoot = "Error" or $regEdit = "Error" or $regSearch = "Error" Then
    $emailSubject = "INI Read Error"
    $emailBody0 = "The script could not read the settings.ini file, specifically the Path section."
    $emailBody2 = "If any of the below variables show as error, check to make sure the INI file exists and is being called and read by the script properly."
    $emailBody4 = "$pathDrive: " & $pathDrive & ". $pathRoot: " & $pathRoot & ". $regEdit: " & $regEdit & ". $regSearch: " & $regSearch
    $emailBody5 = "Location of Error: run Registry Editor program loop on server: " & @ComputerName
    SendMail ( $emailSubject, $emailBody0, $emailBody2, $emailBody4, $emailBody5 )
    Exit
EndIf

While 1                 ; Window close loop
    $WindowTitle = WinGetTitle ( "", "" )
    Select
        Case $WindowTitle <> ""
            $winTitleKill = WinList()
            For $i = 1 to $winTitleKill[0][0]
                ; Only display visble windows that have a title
                If $winTitleKill[$i][0] <> "" AND IsVisible ( $winTitleKill[$i][1] ) Then
                    ;Close each open window
                    WinKill ( $winTitleKill[$i][0] )
                EndIf
            Next
            ExitLoop
        Case Else
            ;No open Windows exist, continue with script
            ExitLoop
    EndSelect
WEnd

Sleep ( 5000 )

While 1         ;run Registry Editor program loop
    Select
        Case FileExists ( $regEdit )
            Sleep ( 2000 )
            Run ( $regEdit )
            Sleep ( 2000 )
            Send ( "{HOME}" )
            Sleep ( 500 )
            ExitLoop
        Case Else
            ;Registry Editor program could not be found
            $emailSubject = "Registry Editor program not Found"
            $emailBody0 = "The Registry Editor program should be located at: " & $regEdit
            $emailBody2 = "Edit the path and/or filename in the settings.ini file to fix this issue"
            $emailBody4 = ""
            $emailBody5 = "Location of Error: run Registry Editor program loop"
            SendMail ( $emailSubject, $emailBody0, $emailBody2, $emailBody4, $emailBody5 )
            Exit
    EndSelect
WEnd

Sleep ( 500 )

;Run loop from loop counter to loop end variable
Do
    If $loopCounter = 0 Then
        ;When $loopCounter = 0 the loop is running for the first time, so open the search dialogue,
        ; paste in the search string, and tab to the "Enter" button and send the enter key to search
        Send ( "{F3}" )
        Sleep ( 500 )
        Send ( $regSearch, 1 )
        Sleep ( 500 )
        Send ( "{TAB}" )
        Sleep ( 500 )
        Send ( "{TAB}" )
        Sleep ( 500 )
        Send ( "{TAB}" )
        Sleep ( 500 )
        Send ( "{TAB}" )
        Sleep ( 500 )
        Send ( "{ENTER}" )

        ;The following loop looks at the window title and determines if the string was found
        While 1
            $WindowTitle = WinGetTitle ( "", "" )           ;Store Window title in variable
            Select
                Case $WindowTitle = "Find"
                    ;Still searching for search string
                Case Else
                    ;No longer searching, value found, or the value wasn't found at all, so exit loop.
                    ;This will exit the If statement too and so the code under the Else will not execute.
                    ExitLoop
            EndSelect
        WEnd

    ;Else statement below belongs to the IF statement above and will only execute if the script
    ; found the search string after the first search
    Else
        Send ( "{F3}" )
        While 1
            $WindowTitle = WinGetTitle ( "", "" )           ;Store Window title in variable
            Select
                Case $WindowTitle = "Find"
                    ;Still searching for search string
                Case Else
                    ;No longer searching, value found, exit loop which will also exit the IF statement
                    ExitLoop
            EndSelect
        WEnd
    EndIf

    Sleep ( 2000 )

    ;Call the winClass function to determine if the finished searching the registry popup has appeared
    $boolFinSearchFound = winClass ( $searchFinClass, $searchFinTitle )

    ;This loop will take two different actions depending on if the registry search has finished or not
    While 1
        Select
            ;Finished searching the registry popup has NOT been found
            Case $boolFinSearchFound = False
                ;Copy key to clipboard
                Sleep ( 1500 )
                Send ( "{TAB}" )
                Sleep ( 1000 )
                Send ( "!e" )
                Sleep ( 1500 )
                Send ( "c" )
                Sleep ( 500 )
                $WindowTitle = WinGetTitle ( "", "" )           ;Store Window title in variable
                _ClipBoard_Open ( $WindowTitle )                ;Open the clipboard so it cannot be changed
                $keyPath = ClipGet()                            ;put clipboard contents into variable
                _ClipBoard_Close ()                             ;Clipboard contents is stored in variable, close clipboard
                Sleep ( 2000 )
                ExitLoop
            ;Finished searching the registry popup HAS been found
            Case $boolFinSearchFound = True
                ;The class of the finished searching registry popup was found, set loop end to stop loop
                $loopEnd = $loopCounter
                $loopEnd += 1
                Sleep ( 500 )
                Send ( "{ENTER}" )
                Sleep ( 500 )
                Send ( "{HOME}" )
                Sleep ( 500 )
                $regKeyFound = True
                ExitLoop
        EndSelect
    WEnd
    $keyPathFull = $keyPath & "\" & $regSearch      ;Concatnate the search string to the found path
    $aPathsFound[$loopCounter] = $keyPathFull       ;add the key path copied from the registry to the array
    $loopCounter += 1                               ;add one to the counter
Until $loopCounter = $loopEnd

While 1
    $WindowTitle = WinGetTitle ( "", "" )               ;Store Window title in variable
    Select
        Case $WindowTitle = "Registry Editor"
            WinActivate ( $WindowTitle )
            WinClose ( $WindowTitle )                           ;Close registry if open
            ExitLoop
    EndSelect
WEnd

While 1
    Select
        Case $regKeyFound = True
            ;Proxy registry key found, send out email
            $emailSubject = "Server: '" & @ComputerName & "' has Proxy Currently Turned on"
            $emailBody0 = "Registry key used for setting IE proxy has been found. Please turn off this setting."
            $emailBody2 = "Server: " & @ComputerName & " needs to have the proxy turned off."
            $emailBody4 = "Go into Internet Options, Connections tab, LAN settings, and uncheck box for proxy setting."
            SendMail ( $emailSubject, $emailBody0, $emailBody2, $emailBody4, "" )
            ExitLoop
    EndSelect
WEnd

Func winClass ( $winClass, $winTitle )
    Local $aWindows, $i, $text, $winClassTemp = "", $winTitleTemp = ""
    $aWindows = _WinAPI_EnumWindows()

    Sleep ( 2000 )
    ;Check through the handles to find the class associated with the finished searching the registry popup
    For $i = 1 To $aWindows[0][0]
        ;variables with class value and window title from current array position
        $winClassTemp = $aWindows[$i][1]
        $winTitleTemp = WinGetTitle($aWindows[$i][0])
        ;convert to string
        ;$winClassTemp = StringFormat ( )
        ;If statement to check if the class from the current array position is equal to class value passed to this function
        If $winClassTemp = $winClass and $winTitleTemp = $winTitle Then
            ;class values match so exit the loop which should exit the function
            $boolFinSearchFound = True
            ExitLoop
        Else
            $boolFinSearchFound = False

        EndIf
    Next
    Return $boolFinSearchFound
EndFunc

;Sendmail Function
Func SendMail ( $emailSubject, $emailBody0, $emailBody2, $emailBody4, $emailBody5 )
    $s_FromAddress = IniRead ( $iniFile, "Mail", "1", "Error" ) ;"RegistryScript@DONOTREPLY.com"
    $s_ToAddress =   IniRead ( $iniFile, "Mail", "2", "Error" ) ;"RGTopTools@johndeere.com"
    $s_SmtpServer =  IniRead ( $iniFile, "Mail", "3", "Error" ) ;"mail.dx.deere.com"
    $s_FromName = "Registry Script Notifications - DO NOT REPLY"
    $s_Subject = "DO NOT REPLY -- " & $emailSubject
    Dim $as_Body[7]
    $as_Body[0] = $emailBody0
    $as_Body[1] = ""
    $as_Body[2] = $emailBody2
    $as_Body[3] = ""
    $as_Body[4] = $emailBody4
    $as_Body[5] = ""
    $as_Body[6] = $emailBody5
    _INetSmtpMail ( $s_SmtpServer, $s_FromName, $s_FromAddress, $s_ToAddress, $s_Subject, $as_Body )
EndFunc

;Window Visible Function, used for Window Close Loop
Func IsVisible ( $handle )
    If BitAnd ( WinGetState ( $handle), 2 ) Then
        Return 1
    Else
        Return 0
    EndIf
EndFunc

settings.zip

Edited by Webs

Share this post


Link to post
Share on other sites



If you are not on an active desktop, things like this can't work:

$WindowTitle = WinGetTitle ( "", "" )

; ...

              WinActivate ( $WindowTitle )

Windows do exist and can be manipulated, but no window can be ACTIVE. So WinActivate() fails, and WinGetTitle("", "") attempts to get the title of the current active window, which fails.

:(


Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
Share on other sites

If you are not on an active desktop, things like this can't work:

$WindowTitle = WinGetTitle ( "", "" )

; ...

              WinActivate ( $WindowTitle )

Windows do exist and can be manipulated, but no window can be ACTIVE. So WinActivate() fails, and WinGetTitle("", "") attempts to get the title of the current active window, which fails.

:(

So that explains why the script hangs and doesn't get far. Makes sense. Is there a way to get the same functionality I am looking at through some other means? That is one of the reasons for posting this question on the forum. For instance, can I make a script that remotes into a server and then starts the script? Or something along those lines?

Share this post


Link to post
Share on other sites

#4 ·  Posted (edited)

If you use things like WinExists(), ControlSetText() and ControlSend() the window can be automated and doesn't ever have to be active. Just avoid things like WinActivate() and Send() which depend on having a certain window active.

Once you get it scripted to work that way, launch your executable from a batch file kicked off by the task manager. You can place the required file(s) over the network, and remotely schedule execution via SCHTASKS.exe.

:(

P.S. We are also ignoring the obvious: If the remote registry service is up on these servers, you don't have to run anything on them. You can check the registry remotely from your admin PC.

:)

Edited by PsaltyDS

Valuater's AutoIt 1-2-3, Class... Is now in Session!For those who want somebody to write the script for them: RentACoder"Any technology distinguishable from magic is insufficiently advanced." -- Geek's corollary to Clarke's law

Share this post


Link to post
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
Sign in to follow this  
Followers 0