Jump to content

Automated Windows XP setup script help


Recommended Posts

Hello everyone,

I work for a small desktop support company. We do a lot of new system configuration, and the majority of the tasks are the same for every system. I'm trying to develop a script that will automatically configure a Windows XP workstation and install a selection of software. The script needs to be fault tolerant (i.e. If one part of the process hangs, the script can continue). I'd also like it to notify the user as to which parts of the process weren't completed. Here's how I decided to do it. I created a master script whose purpose is to run subscripts (modules also written in autoit). I've timed each task, and the master script will pause for a predetermined length of time while each module runs. If a module exceeds the expected time limit, the master script should end any active autoit scripts excepting itself.

I wrote a function which is designed to first identify the master script's process ID (PID), and then end all other active instances of autoit3.exe

;finds master script pid and assigns it to variable $m.  This should be the first thing the script does so there's only one process running.
$m = ProcessExists("autoit3.exe")

;defines kill function which preserves the master script and kills all other autoit3.exe processes
func kill($i)
    $array = processlist("autoit3.exe")
    While $i <= ($array[0][0])
        if $m = ($array[$i][1]) then 
            $i=$i+1
        Else 
            processclose($array[$i][1])
            $i=$i+1
        endif
    WEnd
EndFunc

When I tested this function initially, it seemed to work like a charm. However, when I intergrated it into my master script it doesn't kill processes that have timed out. To go you an idea of how it all works, here's the first part of the master script:

;look and feel
run("1 look and feel.exe")
sleep(12000)
fileopen("checklist.txt", 0)
if FileReadLine("checklist.txt", 1) <> "Success - Look and Feel" then 
    fileclose("checklist.txt")
    fileopen("checklist.txt", 1)
    FileWriteline("checklist.txt", "Failure - Look and Feel")
    fileclose("checklist.txt")
    kill(1)
Else 
    fileclose("checklist.txt")
EndIf

"1 look and feel.exe" is a module that does basic look and feel modifications to the Windows XP GUI. "Checklist.txt" starts as a blank document, and it serves as a record of which modules completed successfully and which modules timed-out. It's also a way for the master script and modules to communicate with each-other. I've included this section of code at the end of each module:

;write success to checklist
fileopen("checklist.txt", 1)
FileWriteline("checklist.txt", "Success - Look and Feel")
fileclose("checklist.txt")

Here's how it all works: The master script runs the module ("look and feel" in the example). It waits for a pre-defined amount of time. During that time, the module either runs to completion, at which point it writes a line to the checklist document saying that it succeeded, or it hangs. After the master script finishes waiting, it looks at the checklist. If it sees that the last line of text is NOT a success message, it writes that the module failed and then kills all instances of autoit3.exe other than itself. If it sees that the last line of text IS a success message, it moves to the next module.

So, my question is this: Why doesn't the master script kill processes that have hung? Additionally, the checklist usually ends up with "success" and "failure" entries for each and every module (which is worse than useless for the technician running the script)! Is there something wrong with the kill function? Also, is there a better, more stable way to do what I'm trying to do? As you can probably tell from my code, I'm new to scripting and have very little programming experience. Hopefully your experienced eyes will catch the obvious flaw in my logic. Thanks for any help you can provide!

Link to comment
Share on other sites

So, my question is this: Why doesn't the master script kill processes that have hung?

Where did you get this kill() function, and why isn't it included here? Psychic debugging is hard to come by.

:)

Gotta learn to read more carefully...

:)

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
Link to comment
Share on other sites

Hello everyone,

I work for a small desktop support company. We do a lot of new system configuration, and the majority of the tasks are the same for every system. I'm trying to develop a script that will automatically configure a Windows XP workstation and install a selection of software. The script needs to be fault tolerant (i.e. If one part of the process hangs, the script can continue). I'd also like it to notify the user as to which parts of the process weren't completed. Here's how I decided to do it. I created a master script whose purpose is to run subscripts (modules also written in autoit). I've timed each task, and the master script will pause for a predetermined length of time while each module runs. If a module exceeds the expected time limit, the master script should end any active autoit scripts excepting itself.

I wrote a function which is designed to first identify the master script's process ID (PID), and then end all other active instances of autoit3.exe

;finds master script pid and assigns it to variable $m.  This should be the first thing the script does so there's only one process running.
$m = ProcessExists("autoit3.exe")

;defines kill function which preserves the master script and kills all other autoit3.exe processes
func kill($i)
    $array = processlist("autoit3.exe")
    While $i <= ($array[0][0])
        if $m = ($array[$i][1]) then 
            $i=$i+1
        Else 
            processclose($array[$i][1])
            $i=$i+1
        endif
    WEnd
EndFunc

When I tested this function initially, it seemed to work like a charm. However, when I intergrated it into my master script it doesn't kill processes that have timed out. To go you an idea of how it all works, here's the first part of the master script:

;look and feel
run("1 look and feel.exe")
sleep(12000)
fileopen("checklist.txt", 0)
if FileReadLine("checklist.txt", 1) <> "Success - Look and Feel" then 
    fileclose("checklist.txt")
    fileopen("checklist.txt", 1)
    FileWriteline("checklist.txt", "Failure - Look and Feel")
    fileclose("checklist.txt")
    kill(1)
Else 
    fileclose("checklist.txt")
EndIf

"1 look and feel.exe" is a module that does basic look and feel modifications to the Windows XP GUI. "Checklist.txt" starts as a blank document, and it serves as a record of which modules completed successfully and which modules timed-out. It's also a way for the master script and modules to communicate with each-other. I've included this section of code at the end of each module:

;write success to checklist
fileopen("checklist.txt", 1)
FileWriteline("checklist.txt", "Success - Look and Feel")
fileclose("checklist.txt")

Here's how it all works: The master script runs the module ("look and feel" in the example). It waits for a pre-defined amount of time. During that time, the module either runs to completion, at which point it writes a line to the checklist document saying that it succeeded, or it hangs. After the master script finishes waiting, it looks at the checklist. If it sees that the last line of text is NOT a success message, it writes that the module failed and then kills all instances of autoit3.exe other than itself. If it sees that the last line of text IS a success message, it moves to the next module.

So, my question is this: Why doesn't the master script kill processes that have hung? Additionally, the checklist usually ends up with "success" and "failure" entries for each and every module (which is worse than useless for the technician running the script)! Is there something wrong with the kill function? Also, is there a better, more stable way to do what I'm trying to do? As you can probably tell from my code, I'm new to scripting and have very little programming experience. Hopefully your experienced eyes will catch the obvious flaw in my logic. Thanks for any help you can provide!

Welcome to the forums.

You call your kill function with this line:

kill(1)

That would send the string 1 to the kill function

So this line

func kill($i)

becomes this line

func kill(1)

This line

$array = processlist("autoit3.exe")

builds a list of the process IDs for programs that are named "autoit3.exe".

This line

While $i <= ($array[0][0])

becomes this line

While 1 <= ???

where ??? equals the number of processes that are named "autoit3.exe".

So you are never going kill a process named "1 look and feel.exe" if all you have to work with is an array listing the PIDs of the processes named "autoit3.exe".

Just for your info, you could remove the kill func and replace this line:

run("1 look and feel.exe")

with this line

$PID = run("1 look and feel.exe")

And replace this line:

kill(1)

with this line

ProcessClose($PID)

But the overall method may be too flawed to be worth saving.

Additionally, the checklist usually ends up with "success" and "failure" entries for each and every module...

I would have to see more of your code to be find that cause.

It would be best if those that deploy software for a living address the "how to do this better" question.

[size="1"][font="Arial"].[u].[/u][/font][/size]

Link to comment
Share on other sites

Plato,

Thanks for the tip on using "run" to capture a module's PID, that's much cleaner than using the kill function, especially since I'll only need to end one module at a time (the counter part of the Kill function was included to deal with a situation where more than two instances of Autoit3.exe exist).

I'll try that out and see if it improves overall functionality (although theoretically it should achieve the same result) and let you all know how it turns out.

Seagul,

We thought about using Nlite to do deployments, but our shop usually gets systems which have just shipped from Dell or another OEM. Since we don't have the option to do a fresh install on these systems, we need a tool that will configure a generic XP installation; hence this scripting project which is slowly driving me insane. Good thought though.

Thanks everyone, keep those ideas coming!

Link to comment
Share on other sites

... (the counter part of the Kill function was included to deal with a situation where more than two instances of Autoit3.exe exist). ...

There should be two instances of Autoit3.exe when you run a script from within SciTE. If you are running/debugging a script as a text file (no from within SciTE) then you should only have one instances of Autoit3.exe per script.

If one AU3 file (text file) has hung and you start another one - you should have code in the script that looks for and warns about the other copy running.

$S_running = "???????" ;name the script
If WinExists($S_running) Then
      MsgBox(0, "AutoIt", "This script is already running.")
      Exit
EndIf
AutoItWinSetTitle($S_running)

_Singleton is another way to prevent multiple copies of the same script from running.

[size="1"][font="Arial"].[u].[/u][/font][/size]

Link to comment
Share on other sites

Great Success!

I replaced the kill function with the code that Plato suggested and viola!, everything works. I still don't understand why the kill function didn't do what I wanted it to, but that's ok because the project is back on track.

Thanks Plato!

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