Jump to content

Manual logging question


Recommended Posts

This is going to be a doozy so grab ye coffees...

Our office has several field users that are offline and offsite which require to have software updates applied to their workstations/laptops.

We have divised a deployment method using Autoit to deploy the necesary software. After many iterations of optimizing, i have created a more streamlined edition of the deployment script.

Generally speaking the script works in parts: one main script which calls many smaller scripts.

The main script handles the elevation of priviledges as well as some rudimentary logging (which is output from a dos run redirection).

Individually, the scripts handle their own tasks. Each script is pretty much independent as far as what it's doing, but overall, the entirety of all of the small scripts must be run successfully for the entire process to be considered success full. That means that any error from any script will cause the whole deployment to be considered a "failed" deployment. Why this is, is a little be difficult to explain, and is something that isn't quite negotiable (though i wish it were).

so to recap we have:

- many users

- users need to have software updates

- users are offline

- users are offsite

- software deployment script is on CD written in autoit

- structure of script is such that one main script calls many small scripts.

- all smaller scripts must be logged

- all smaller scripts must complete successful to have entire deployment considered as successful

- else entire deployment is fail.

-all smaller scripts are already compiled.

Ok if you're still with me I thank you. My question is as such:

How would I be able to centralize the success/fail results of all of the small script into one major log file?

Given that the success/fail flags are handled inside each small script.

It would be preferable if that log file existed as a variable in the main script and somehow got passed or shared with the smaller scripts.

now here is my one constraint, because of some of the automatic logging functions which are built into the main script, i cannot (prefer not) use cmdline parameters to pass the variable from the main script to the smaller script.

I have drawn a pretty rudimentary diagram of what i'm trying to achieve. I will upload it in a few minutes.

thanks for your time and patience.

-Blademonkey

PS: here's the pic.

Posted Image

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

First off-the-cuff thought:

Have the main script and all sub scripts write to their own named log in a subfolder of the temp directory that the main script creates early on.

After the main program finishes, have it email all the contents each of the log files to a central email address using _INetMail() with $s_MailSubject being the name of the log file, and $s_MailBody being the log's contents.

[u]Helpful tips:[/u]If you want better answers to your questions, take the time to reproduce your issue in a small "stand alone" example script whenever possible. Also, make sure you tell us 1) what you tried, 2) what you expected to happen, and 3) what happened instead.[u]Useful links:[/u]BrettF's update to LxP's "How to AutoIt" pdfValuater's Autoit 1-2-3 Download page for the latest versions of Autoit and SciTE[quote]<glyph> For example - if you came in here asking "how do I use a jackhammer" we might ask "why do you need to use a jackhammer"<glyph> If the answer to the latter question is "to knock my grandmother's head off to let out the evil spirits that gave her cancer", then maybe the problem is actually unrelated to jackhammers[/quote]

Link to comment
Share on other sites

pretty good suggestion, but remember, the users are offline for a long time.

I do have a process that uploads the logs but this happens at the user's discretion. On the server side, i have a script that analyzed one main log file to see if the deployment is successful or not. if the deployment is successful the script enables the users access to their own homefolders (by way of permissions). It then emails the results to a public folder.

The issue is that I do not think that the evaluation of whether or not the entire deployment is valid should fall on the server side script, as there are incomplete log transmissions that may complicate that logic.

BTW, the main script does have it's own logging for each small script(which i refer to as external logging). I require internal logging (from the small script itself) to verify the actual results/status of the small script.

thanks for your time and patience. I hope i'm not confusing you more than i need to.

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

on a side note i think i could do it, if there was a way for me to be able to enumerate whether or not the current script was called from a main script, and then i could potentially reference the main script's ini file in which it would have the main log.

but that just sounds like crazy talk at this point.

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

@blademonkey

Looking at the request, you are looking for a server side logging.

Where the clients are running an agent that use an HTTP session connection to the server, to send the info when coming online.

So far the theory.

regards

ptrex

Link to comment
Share on other sites

@blademonkey

Looking at the request, you are looking for a server side logging.

Where the clients are running an agent that use an HTTP session connection to the server, to send the info when coming online.

So far the theory.

regards

ptrex

Sorry, didn't mean to confuse.

The logging I am looking for is not online or server side. it's offline, and client side. It just happens that there's a process that will upload the logs (when the user RAS' in) to the server. At which point a server side script analyzes the uploaded data and responds accordingly.

I think i have found the answer, but am working out the variations. I will post my makeshift solution when i get it straightened out.

thanks for your time ptrex.

-Blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

Before I became aware of the wonder that is AutoIT, I happened to work on a project where we were tabulating data (using a combination of KiX and VBScript) from machines when users logged on and then wrote an INI-style file to a centralized logging location. I then had a script in PHP (yes a script, not a webpage) that parsed those ini files and wrote them to a SQL database where-by I had a PHP front-end for searching the database.

to make a long story short (but just citing that I do have experience in similar issues): Have your scripts log whatever information you want in whatever format you want, comma/tab delimited, ini, etc and in one or many smaller files. Then just write a script that gets kicked off ever 30 mins or so to check for an internet connection using the Windows Task Scheduler, and if it does, ftp, http, email, etc the file or files to your on-site logging server. Then you can use whatever means u deem appropriate for parsing/organizing the data you're getting.

Edit: And based off of ur last post... if they RAS in... u can just use a UNC path to your server's logging share and move the files there.

Edited by thepip3r

My Additions:- RunAs AdminDeviant Fun:- Variable Sound Volume

Link to comment
Share on other sites

Here is what I would do.

You could use @ScriptName in place of Package1, Package2, etc...

This will give you a registry entry for each package run.

#Include <Date.au3>

$regKey = "HKLM\SOFTWARE\MyDeploymentScript\"
$package = "Package1"
$complete = "complete"
$starttime = "starttime"
$endtime = "endtime"


$result = Number(RegRead($regKey & $package, $complete))

If $result Then Exit

;Set failed flag(by default)
RegWrite($regKey & $package,$complete, "REG_SZ",0)

;Set start time
RegWrite($regKey & $package,$starttime, "REG_SZ",_Now())

;/////////////////////
;Do stuff...if any errors occur...Exit, script will never write success flag
;/////////////////////


;Set success flag
RegWrite($regKey & $package,$complete, "REG_SZ",1)

;Set end time
RegWrite($regKey & $package,$endtime, "REG_SZ",_Now())
Link to comment
Share on other sites

Before I became aware of the wonder that is AutoIT, I happened to work on a project where we were tabulating data (using a combination of KiX and VBScript) from machines when users logged on and then wrote an INI-style file to a centralized logging location. I then had a script in PHP (yes a script, not a webpage) that parsed those ini files and wrote them to a SQL database where-by I had a PHP front-end for searching the database.

to make a long story short (but just citing that I do have experience in similar issues): Have your scripts log whatever information you want in whatever format you want, comma/tab delimited, ini, etc and in one or many smaller files. Then just write a script that gets kicked off ever 30 mins or so to check for an internet connection using the Windows Task Scheduler, and if it does, ftp, http, email, etc the file or files to your on-site logging server. Then you can use whatever means u deem appropriate for parsing/organizing the data you're getting.

Edit: And based off of ur last post... if they RAS in... u can just use a UNC path to your server's logging share and move the files there.

thanks, but the issue is not so much getting the logs to the server as it is getting the entirety of the deployment evaluated in a centralized manner.

thanks for your input, much obliged.

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

Here is what I would do.

You could use @ScriptName in place of Package1, Package2, etc...

This will give you a registry entry for each package run.

#Include <Date.au3>

$regKey = "HKLM\SOFTWARE\MyDeploymentScript\"
$package = "Package1"
$complete = "complete"
$starttime = "starttime"
$endtime = "endtime"


$result = Number(RegRead($regKey & $package, $complete))

If $result Then Exit

;Set failed flag(by default)
RegWrite($regKey & $package,$complete, "REG_SZ",0)

;Set start time
RegWrite($regKey & $package,$starttime, "REG_SZ",_Now())

;/////////////////////
;Do stuff...if any errors occur...Exit, script will never write success flag
;/////////////////////


;Set success flag
RegWrite($regKey & $package,$complete, "REG_SZ",1)

;Set end time
RegWrite($regKey & $package,$endtime, "REG_SZ",_Now())

Ok that's probably the most original suggestion i've heard. I'll have to think about this one.

Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

I have used piccaso's "Another Multi Process Helper" for communicating between multiple scripts, worked flawlessly!! :)

What you want is probably _CoProcReciver() and _CoProcSend()

Edited by TzarAlkex
Link to comment
Share on other sites

I have used piccaso's "Another Multi Process Helper" for communicating between multiple scripts, worked flawlessly!! :)

What you want is probably _CoProcReciver() and _CoProcSend()

I have written a program almost exactly like the OP and I can say this is overkill. Basically you have a host process looping through an array of executables in sequence, the host program already knows when each sub-process begins and ends.

If the host process was using RunWait() to launch each package, you could just use the return value from that to check the exit codes, thereby centralizing the logging into said host process.

EDIT: Program I was referring to:

http://www.autoitscript.com/forum/index.ph...mp;hl=archrival

Edited by weaponx
Link to comment
Share on other sites

I have written a program almost exactly like the OP and I can say this is overkill. Basically you have a host process looping through an array of executables in sequence, the host program already knows when each sub-process begins and ends.

If the host process was using RunWait() to launch each package, you could just use the return value from that to check the exit codes, thereby centralizing the logging into said host process.

EDIT: Program I was referring to:

http://www.autoitscript.com/forum/index.ph...mp;hl=archrival

Well if thats overkill then what you do to the registry is also overkill.... Remember that in the first post he said he only wanted to know if they failed or not, so maybe we should ask him why he doesn't use the "exit codes" from RunWait() instead...... :)
Link to comment
Share on other sites

good question.

because i am not so familiar with exit codes i did a little research and some tests and found that exit codes for compiled scripts didnt work as well as return codes for functions.

I just tried it again and it seems to have worked flawlessly.

Thanks so much for both your suggestions, and sorry for being incompetant with exit codes :/

this will do nicely.

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

meh... each way has it's draws and draw-backs. i'd still institute some sort of temp file storage location with a specific naming convention for your different files. but that's just because i've done a lot of work with files, file locks, unc paths, group policy, etc.

i'm sorry for misunderstanding the problem. but to clarify, i'd create a specific folder on each computer either in the user's temp direcotry or windows temp directory and have each file dump whatever data you want (@error status, STDOUT/STDERR info), in a file of some kind in this temp directory. so say you have 5 scripts (generic).

script1.log

script2.log

script3.log

script4.log

script5.log

..where those files are essentially the flat-file db for the errors/successes (whatever ur looking for) each time they run. you can create a unique index number for the logs based off of the year-month-day-description or however often you run it, then comma, then the error, the success, etc. Then you can make a errorLogParser.au3 to look for the different errors or successes or whatever based off of the line by line entries in each log and you'd know what logs were associated with what fiels based off of the file you're pulling the data from.

but again, it's all up to what you're familiar and comfortable with.

My Additions:- RunAs AdminDeviant Fun:- Variable Sound Volume

Link to comment
Share on other sites

I wish i could assign points to both of you (like on Experts Exchange) for your assistance.

I wonder if that's something the Autoit community would find useful in the long run.

Thanks again everyone, and specifically to WeaponX and TzarAlkex!

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

I wish i could assign points to both of you (like on Experts Exchange) for your assistance.

I wonder if that's something the Autoit community would find useful in the long run.

Thanks again everyone, and specifically to WeaponX and TzarAlkex!

See here.

Link to comment
Share on other sites

to clear up confusion, he's the main script code which is run from a CD (which contains the external scripts as well):

It reads which app its supposed to load from an INI. I'll post the a sample ini below.

$sUser = "*******"
    #include "******\SelfCall.au3"
    _check(@ScriptName,$sUser ,@ComputerName)
    
;~ *******************************
#include<array.au3>
$CD         =   @ScriptDir                                  ;   set $cd to the path of where this script is running from
$sIni       =   StringTrimRight(@ScriptName, 3) & "INI"
$sDate      =   @MON & '/' & @MDAY & '/' &@YEAR
$sTime      =   @HOUR &":"& @MIN
$RVIVersion =   IniRead($sIni, "MAIN", "Version", "NoVersion")
$localpath  =   IniRead($sIni, "MAIN", "PATH", "C:\xpmarker")
$locallog   =   $localpath &  "\" &$RVIVersion& "\RVI_" & $RVIVersion & "_Main.log"
$HL         =   "**********************************************************"
Dim $aSecName

$aSecName = IniReadSectionNames($sIni)
If FileExists($localpath) = 0 Then DirCreate($localpath)
If FileExists($localpath&'\'&$RVIVersion) = 0 Then DirCreate($localpath&'\'&$RVIVersion)
;~  **********  Main ******--->
if hasduplicateitems($aSecName)=1 Then
    MsgBox(0,"INI Error",   "There's a duplicate Section name in the "&$sIni &" File."&@lf& _   
                            "This will need to be fixed before the RVI will proceed." &@LF&@lf& _   
                            "Section names are encapsulated by Brackets (ex [Section] )")
    Exit
EndIf
CheckRequirements()

FileWriteLine($locallog, $HL)
FileWriteLine($locallog, "Start of RVI Log")
FileWriteLine($locallog, "RVI Version :         " & $RVIVersion)
FileWriteLine($locallog, "Number of Modules :       " & $aSecName[0] - 1)
FileWriteLine($locallog, 'Date/time :           ' & $sdate & " " & $sTime)
FileWriteLine($locallog, 'Workstation :         ' & @ComputerName)
FileWriteLine($locallog, $HL)

For $x = 2 To $aSecName[0]
    $name = ""
    $file = ""
    $path = ""
    $options = ""
    $params = ""
    $lsw = "/log"
    $aLoopArray = IniReadSection($sIni, $aSecName[$x])
    For $y = 1 To $aLoopArray[0][0]
        Assign($aLoopArray[$y][0], $aLoopArray[$y][1])
    Next
    $type = StringRight($file,3)
    FileWriteLine($locallog, "Module:       " & $name)
    FileWriteLine($locallog, "Start Time    " & $sTime)
;~  FileWriteLine($locallog, "Unit Log: " & $localpath & '\' & "RVI_" & $RVIVersion & '_' & $name & '.log')
    if StringInStr($params,"NOPOPUP")=0 then SplashTextOn($aSecName[$x],"Installing: " & $name,200, 100,(@DesktopWidth/2)-(200/2),(@DesktopHeight/2)-(100))
    ProcessType($name, $type, $file, $path, $options,$params) 
    FileWriteLine($locallog, "End Time  " & $sTime&@CRLF&@CRLF)
    SplashOff()
Next

FileWriteLine($locallog, $HL)
FileWriteLine($locallog, "END of RVI Log")
FileWriteLine($locallog, $HL)

MsgBox(0,"Security Patch Update","Your laptop has been updated.  Please reboot your computer.")
;~  <---******  Main **********

;~  **********  Functions ******--->
Func ProcessType($name, $type, $file, $path, $options,$params)
    if StringInStr($path,@ScriptDir) =0 then $path = @ScriptDir & '\' & $path
    $fullpath = $path & '\' & $file
    
    if StringInStr($params,"NOLOG")<>0 Then 
        $log = "Log Restricted from INI"
    Else
        $log = $localpath & '\' & $RVIVersion& "\RVI_" & $RVIVersion & '_Sublog_' & $name & '.log'
        $sException = $localpath & '\' & $RVIVersion& "\RVI_" & $RVIVersion& '_Sublog_' & $name & "_Exceptions.log"
    EndIf
    $cmd = ""
    $errorcatch = " && Echo cmdline return:  No errors >> "&$locallog&" || echo cmdline return:     Some errors >> "&$locallog
    Select
        Case $type = 'MSI'
            if StringInStr($params,"NOLOG")<>0 Then 
                $cmd = 'Msiexec /I "' & $fullpath & '" ' & $options &$errorcatch
            Else
                $cmd = 'Msiexec /I "' & $fullpath & '" ' & $options & ' '&$lsw&' "' & $log &'" >> ' & $sException & ' 2>&1' & $errorcatch
            EndIf
        Case $type = 'EXE'
            if StringInStr($params,"NOLOG")<>0 Then 
                $cmd = '("' &$fullpath & '" ' & $options & ')' &$errorcatch
            Else
                $cmd = '("' &$fullpath & '" ' & $options & ' '&$lsw&' "' & $log &'") >> ' & $sException & ' 2>&1'&$errorcatch
            EndIf
        Case $type = 'BAT'
            if StringInStr($params,"NOLOG")<>0 Then 
                $cmd = '"' &$fullpath & '" ' & ' 2>> '&$locallog &$errorcatch
            Else
                $cmd = '"' &$fullpath & '" '& ' >> ' & $log & ' 2>> '&$sException & $errorcatch
            EndIf
        Case $type = 'REG'
            if StringInStr($params,"NOLOG")<>0 Then 
                $cmd = '(reg /import ' & $fullpath& ' 2>> '&$locallog &")"&$errorcatch
            Else
                $cmd = '(reg /import ' & $fullpath &' >> ' & $log & ' 2>> '&$sException& ")"&$errorcatch
            EndIf
    EndSelect
    RunWait(@ComSpec & ' /c ' & $cmd, '', @SW_HIDE)
    FileWriteLine($locallog, 'Run Line:     ' & $cmd)
    if FileExists($Log)=1 then 
        $status = "logcheck:  log write successfull"
    Else
        $status = "logcheck:  no log written"
    EndIf
    FileWriteLine($locallog, "Unit Log: " & $log & " " & $status)
EndFunc   ;==>ProcessType

Func CheckRequirements()
    $log = $localpath & '\' & "RVI_" & $RVIVersion & '_Sublog_MSI31.log'
    $sFileversion = FileGetVersion(@SystemDir & '\msi.dll')
    If $sFileversion <> "3.1.4000.2435" Then
        FileWriteLine($locallog, "MSI Installer Version:        "& $sFileversion &" (Incorrect)")
        FileWriteLine($locallog, "MSI Installer Version:        3.1.4000.2435 (Correct)")
        RunWait(@ComSpec & ' /c ' & 'Data\WindowsInstaller-KB893803-v2-x86.exe /passive /norestart /l ' & $log, '', @SW_HIDE)
    Else
        FileWriteLine($locallog, "MSI Installer Version:        3.1.4000.2435 (Correct)")
    EndIf
EndFunc   ;==>CheckRequirements

Func hasDuplicateItems($array)
    _ArraySort($array)
    for $x = 1 to UBound($array)-2
        if $array[$x]<UBound($array)-1 Then
            if $array[$x] = $array[$x+1] Then
                return 1
            EndIf
        EndIf
        
    Next
    return 0    
EndFunc

;~ <---****** Functions **********

Sample ini(assumes that there's a test.exe file in the relative path "data\"):

;   This is the RVI INI file that will direct the RVI to run as a local admin
;   To deploy applications.
;
;   Main section should be present for tracking purposes
;   If main is not present, RVI template will apply the following values:
;   Version="NoVersion" 
;   PATH=c:\xpmarker
[MAIN]
Version=CPI002
PATH=c:\xpmarker

[Unit1]
Type=exe
Name=Test
FILE=test.exe
Path=Data
params=nopopup


;[UNIT]
;TYPE=[msi | bat | exe | reg]
;NAME=[Name for log purposes]
;FILE=[Filename]
;PATH=[relative path]
;OPTIONS=[external app specific switches (f.e. "/PASSIVE /NORESTART") ]
;PARAMS=[NOPOPUP,NOLOG]
Edited by blademonkey

---"Educate the Mind, Make Savage the Body" -Mao Tse Tung

Link to comment
Share on other sites

I wish i could assign points to both of you (like on Experts Exchange) for your assistance.

:) You could always go to our profiles and leave a nice comment in there and tell the story of how we slayed the dragon that was stopping you from making your script complete.... :)

Edit:spelling

Edited by TzarAlkex
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...