Changes

Inventory script

15,278 bytes added, 08:34, 12 May 2011
Created page with "This Autoit script can be used to read the per client XML files that get copied to a network share once wpkg.js has finished running (I use the 'Execute after' option) [http://wp..."
This Autoit script can be used to read the per client XML files that get copied to a network share once wpkg.js has finished running (I use the 'Execute after' option) [http://wpkg.org/Viewing_software_installed_on_workstations]

<pre>
To have the latest version of wpkg.xml copied to the server, you can either:

use WPKG client, and copy this file as "Execute after" action,
in config.xml, configure wpkg.js to save this file on the server.
</pre>

The script also reads in the 'master' package XML files. It then compares the 'revision=' of the master to the clients 'revision=' and flags up any differences that can be emailed to whoever using the third party tool mailsend.exe [http://www.muquit.com/muquit/software/mailsend/mailsend.html]. It also creates a per client pc CSV file in a subdirectory on the server share where the client XML files are saved (\invent\) and concats all the CSV files into a single all.csv file.

The output of a client invent XML files looks like:

<pre>
PC NAME,DATE OF XML FILE,DESCRIPTION,PACKAGE ID NAME,PRIORITY,INSTALLED REVISION,MASTER XML REVISION,UPGRADE/DOWNGRADE/BLANK=NOTHING REQUIRED
RECOVERY,09/05/2011_15:37,7-Zip,7zip,10,920,920,
RECOVERY,09/05/2011_15:37,Activation MS Office 2010,msoffice2010-activation,71,1,1,
RECOVERY,09/05/2011_15:37,Adobe Acrobat 9,acrobat9,17,944,944,
RECOVERY,09/05/2011_15:37,Adobe Shockwave Player 11,shockwave,50,11.5.7.601,11.5.7.609,Upgrade required
</pre>

==Autoit script==

Compile and cmd exe

<pre>
#Region ;**** Directives created by AutoIt3Wrapper_GUI ****
#AutoIt3Wrapper_Outfile=wpkg_invent_chk.exe
#AutoIt3Wrapper_Change2CUI=y
#EndRegion ;**** Directives created by AutoIt3Wrapper_GUI ****
#include <File.au3>
#include <Array.au3>
#include <Date.au3>
#include <Constants.au3>

; ***********************************************************************************************************************
;
; Script to look at the WPKG generated XML files that get copied to the \win-info\wpkg-xml\ share after WPKG has run on
; each pc and compare the installed packages to the master set of SML files on \wpkg\server\WPKG-1.1.2\packages\. A per
; pc csv file is created showing what is installed on that pc. Another csv file is made concatting all the indervidual
; csv files. This 'all' csv file is then read in and all pakcages that require up or downgrading are noted and if required,
; can be emailed to whoever is specified as the first argument to the exe of this script.
;
;C. Mortimer May 2011
;
; ***********************************************************************************************************************


Dim $master_or_computer_path, $master_or_computer_invent_array, $invent

$pc_xml_path = EnvGet("LOGONSERVER") & "\win-info\wpkg-xml"
$master_xml_path = EnvGet("LOGONSERVER") & "\wpkg\server\WPKG-1.1.2\packages"

If @Compiled = 1 Then
If $CmdLine[0] > 0 Then
If ($CmdLine[1] = "/?") OR ($CmdLine[1] = "?") Then
ConsoleWrite("Usage" & @CRLF & @CRLF & "Program to produce a report file per machine name showing the installed WPKG packages as stored in the auto created WPKG files in" & _
" " & $pc_xml_path & "\[machine name].xml. These files are copied from \\[machine name]\c$\windows\temp\wpkg.xml to " & $pc_xml_path & " when ever the wpkg.js scipt has " & _
"finished running. The report files are stored in " & $pc_xml_path & "\invent\. " & $pc_xml_path & "\invent\all.csv is a concat of all the csv files. If this script is " & _
"is passed an argument of an email address, a report of any machines with packages out of sync with the master WPKG XML file (" & $master_xml_path & "\ can be emailed to whoever." & _
@CRLF & @CRLF & "C. Mortimer May 2011" & @CRLF)
Exit
ElseIf StringInStr($CmdLine[1], "@") Then
$email_address = $CmdLine[1]
Else
$email_address = ""
EndIf
Else
$email_address = ""
EndIf
Else
$email_address = "foo@gmail.com"
EndIf

$csv_title_txt = "PC Name,Date of XML File,Description,Package ID Name,Priority,Installed Revision,Master XML Revision,Upgrade/Downgrade/blank=Nothing Required"
$downgrade_string = "Downgrade required"
$upgrade_string = "Upgrade required"
$mailsend = EnvGet("LOGONSERVER") & "\netlogon\bin\mailsend.exe"
$s_domain = "somewhere"
$s_SmtpServer = "smtp.somewhere.cam.ac.uk"
$s_FromName = ""
$s_FromAddress = "wibble@gmail.com"
$s_ToAddress = "-t " & $email_address
$s_Subject = "PC's with missmatched WPKG programs"

If Not FileExists($pc_xml_path & "\invent\*") Then DirCreate($pc_xml_path & "\invent\")

; Lets work out the current master revision numbers for each id
$invent = ""
_make_xml_array($master_xml_path)

; Now work out the list of installed packages for each machine generated xml file...
$filedelete = FileDelete($pc_xml_path & "\invent\*.csv")
_make_xml_array($pc_xml_path)

; Now sort out the mailing of the machines needing up/downgrading
$error_list = $csv_title_txt & @CRLF
If FileExists($pc_xml_path & "\invent\all.csv") Then

Dim $all_csv_file
_FileReadToArray($pc_xml_path & "\invent\all.csv", $all_csv_file)
$all_error_occurance_id = _ArrayFindAll($all_csv_file, "grade required", "", "", "", 1)
For $o = 0 To _ArrayMaxIndex($all_error_occurance_id) Step 1
$error_list = $error_list & $all_csv_file[$all_error_occurance_id[$o]] & @CRLF
Next
ConsoleWrite("Machines and packages that differ from the Master XML files = " & @CRLF & @CRLF & $error_list & @CRLF)

If StringLen($email_address) > 0 Then
If FileExists($mailsend) Then

$wpkg_invent_email_file = EnvGet("temp") & "\wpkg_invent_email.txt"
$write2file = FileOpen($wpkg_invent_email_file, 2)
FileWriteLine($write2file, $error_list)
FileClose($write2file)

$sendmail = $mailsend & " -v -d " & $s_domain & " -smtp " & $s_SmtpServer & " " & $s_ToAddress & " -f " & $s_FromAddress & _
" -sub """ & $s_Subject & """ +cc +bc -m """ & $wpkg_invent_email_file & """,text/plain,i"
$std_run_reg = Run($sendmail, "", "", $STDERR_CHILD + $STDOUT_CHILD)

$q = 1
$timewatch = TimerInit() ; Make a note of the current time
While $q = 1

$std_out_read = StdoutRead($std_run_reg)
$std_err_read = StderrRead($std_run_reg)
If (StringLen($std_out_read) > 0) OR (StringLen($std_err_read) > 0) Then
ConsoleWrite(@CRLF & @CRLF & "Email sent" & @CRLF)
$q = 2
EndIf
If TimerDiff($timewatch) > 5000 Then
$q = 2
ConsoleWrite(@CRLF & @CRLF & "Error sending email :(" & @CRLF)
EndIf
WEnd
Sleep(1000)
FileDelete($wpkg_invent_email_file)
Else
ConsoleWrite("The file '" & EnvGet("LOGONSERVER") & "\netlogon\bin\mailsend.exe' is missing, unable to send any email" & @CRLF)
EndIf
EndIf
Else
ConsoleWrite("The file '" & $pc_xml_path & "\invent\all.csv' is missing, unable to send any email or write to STDOUT the list of out of date pcs" & @CRLF)
EndIf

; =======================================================================================================================

Func _make_xml_array($master_or_computer_path)

$xml_files = _FileListToArray($master_or_computer_path, "*.xml", 1) ; make an array listing each master xml file
;~ _ArrayDisplay ($xml_files)

For $p = 1 To $xml_files[0] Step 1 ; for each xml file...
If $master_or_computer_path = $pc_xml_path Then
;~ ConsoleWrite ("pc = " & StringReplace($xml_files[$p], ".xml", "") & @CRLF)
$invent = ""
EndIf

Dim $xml_file_contents
_FileReadToArray($master_or_computer_path & "\" & $xml_files[$p], $xml_file_contents) ; create an array, $xml_file_contents listing its contents
;~ _ArrayDisplay ($xml_file_contents)
$occurance_id = _ArrayFindAll($xml_file_contents, " revision=", "", "", "", 1) ; in the array $xml_file_contents, return all the indices (lines) containing ' revision='
;~ _ArrayDisplay ($occurance_id)
For $o = 0 To _ArrayMaxIndex($occurance_id) Step 1
$id_line = FileReadLine($master_or_computer_path & "\" & $xml_files[$p], $occurance_id[$o])

Do ; replace tabs with a single space
$id_line = StringReplace($id_line, " ", " ")
Until @extended = 0

Do ; replace double space with a single space
$id_line = StringReplace($id_line, " ", " ")
Until @extended = 0

Do ; replace a space at the start of the line with null
If StringLeft($id_line, 1) = " " Then $id_line = StringTrimLeft($id_line, 1)
Until StringLeft($id_line, 1) <> " "

Do ; replace <wpkg> at the start of the line with null
If StringLeft($id_line, 6) = "<wpkg>" Then $id_line = StringTrimLeft($id_line, 6)
Until StringLeft($id_line, 6) <> "<wpkg>"
;~ ConsoleWrite ("$id_line = " & $id_line & @CRLF)

; Now make an array and run a For loop to replace the %version%/%shortversion%/%subversion% int he XML file with it's variable value
Dim $_aArray[3]

$_aArray[0] = "shortversion"
$_aArray[1] = "version"
$_aArray[2] = "subversion"

For $ver In $_aArray
If StringInStr($id_line, "%" & $ver & "%") Then
;~ ConsoleWrite("line number = " & $occurance_id[0] & "(" & $ver & ")" & @CRLF)
$doloop = 1
$doloop_line_no = $occurance_id[$o]
Do
$find_version = FileReadLine($master_or_computer_path & "\" & $xml_files[$p], $doloop_line_no + 1) ; Read the line 1 line after the line containing ' revision=' in the xml file
;ConsoleWrite("$find_version = " & $find_version & " on line " & $doloop_line_no & @CRLF)
If StringInStr($find_version, "<variable name=""" & $ver & """") Then ; If this '1 line after revision=' contains $ver (%version%, %shortversion% or %subversion%...
$find_version_split = StringSplit($find_version, '""') ; make an array of this line...
If @error = 1 Then $find_version_split = StringSplit($find_version, '''') ; if no double quotes are used, split using single quotes.
$find_version_value = $find_version_split[_ArraySearch($find_version_split, "value=", "", "", "", 1) + 1] ; and note the value set in the array indice one after 'value='
;ConsoleWrite("$find_version_value = " & $find_version_value & @CRLF)
$doloop = 2
;ConsoleWrite($id_line & @CRLF)
;_ArrayDisplay($find_version_split)
EndIf
$doloop_line_no = $doloop_line_no + 1 ; increment $doloop_line_no by one and run the Do loop again, this time looking for the next line down.
Until $doloop = 2
$id_line = StringReplace($id_line, "%" & $ver & "%", $find_version_value)
;~ ConsoleWrite("$id_line = " & $id_line & @CRLF)
EndIf
Next
;~ ConsoleWrite("$id_line = " & $id_line & @CRLF)

If $master_or_computer_path = $master_xml_path Then
$id_line_split = StringSplit($id_line, '""') ; split the line with double quotes as the deliminator.
If @error = 1 Then $id_line_split = StringSplit($id_line, '''') ; if no double quotes are used, split using single quotes.
$invent = $invent & "," & $id_line_split[_ArraySearch($id_line_split, "id=", "", "", "", 1) + 1] ; Create a string $invent contianing the id name...
$invent = $invent & "," & $id_line_split[_ArraySearch($id_line_split, "revision=", "", "", "", 1) + 1] ; and the revision number.
If StringLeft($invent, 1) = "," Then $invent = StringTrimLeft($invent, 1) ; If the first character on the left if a ',' remove it.
;~ ConsoleWrite("$invent after reading master files = " & $invent & @CRLF)
$master_or_computer_invent_array = StringSplit($invent, ",") ; Turn the string $invent into an array.
ElseIf $master_or_computer_path = $pc_xml_path Then
$id_line_split = StringSplit($id_line, '""')
;~ _ArrayDisplay ($id_line_split)
$invent = $invent & StringReplace($xml_files[$p], ".xml", "") ; start creating the indevidual package csv line by obtaining the pc name...
$time = FileGetTime($master_or_computer_path & "\" & $xml_files[$p], 0, 0) ; then the date and time the pc's xml file was created
$invent = $invent & "," & $time[2] & "/" & $time[1] & "/" & $time[0] & "_" & $time[3] & ":" & $time[4]
$invent = $invent & "," & $id_line_split[_ArraySearch($id_line_split, "name=", "", "", "", 1) + 1] ; then add the 'name' text...
$id = _ArraySearch($id_line_split, "id=", "", "", "", 1)
$invent = $invent & "," & $id_line_split[$id + 1] ; then the 'id' for the package...
$invent = $invent & "," & $id_line_split[_ArraySearch($id_line_split, "priority=", "", "", "", 1) + 1]
$revision = _ArraySearch($id_line_split, "revision=", "", "", "", 1)
$invent = $invent & "," & $id_line_split[$revision + 1] ; then the revision number...
$master_revision = $master_or_computer_invent_array[_ArraySearch($master_or_computer_invent_array, $id_line_split[$id + 1], "", "", "", 0) + 1] ; now add the revision number for the same id but from the master xml files
$invent = $invent & "," & $master_revision

If $id_line_split[$revision + 1] = $master_revision Then
$invent = $invent & "," & ""
ElseIf $id_line_split[$revision + 1] > $master_revision Then
$invent = $invent & "," & $downgrade_string
ElseIf $id_line_split[$revision + 1] < $master_revision Then
$invent = $invent & "," & $upgrade_string
EndIf

$invent = $invent & @CRLF
EndIf
Next

; Now save each output to a per machine name file and concat all of the output into one file

If $master_or_computer_path = $pc_xml_path Then
ConsoleWrite("Inventory of installed packages on " & StringUpper ($xml_files[$p]) & " = " & @CRLF & @CRLF & $csv_title_txt & @CRLF & $invent & @CRLF)

;~ ConsoleWrite ("FileReadLine (" & $pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv, 1) = " & FileReadLine ($pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv", 1) & @CRLF)
If FileReadLine($pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv", 1) = "" Then
$save_csv = FileOpen($pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv", 1)
FileWrite($save_csv, StringUpper($csv_title_txt) & @CRLF)
FileClose($save_csv)
;~ ConsoleWrite ("writing title to " & $pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv" & "(" & FileReadLine ($pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv", 1) & ")" & @CRLF)
EndIf

$save_csv = FileOpen($pc_xml_path & "\invent\" & StringReplace($xml_files[$p], ".xml", "") & ".csv", 1)
;~ ConsoleWrite ("now saving $invent to " & StringReplace($xml_files[$p], ".xml", "") & ".csv" & @CRLF)
FileWrite($save_csv, $invent)
FileClose($save_csv)

;~ ConsoleWrite ("FileReadLine (" & $pc_xml_path & "\invent\all.csv, 1) = " & FileReadLine ($pc_xml_path & "\invent\all.csv", 1) & @CRLF)
If FileReadLine($pc_xml_path & "\invent\all.csv", 1) = "" Then
$save_csv_all = FileOpen($pc_xml_path & "\invent\all.csv", 1)
FileWrite($save_csv_all, StringUpper($csv_title_txt) & @CRLF)
FileClose($save_csv_all)
;~ ConsoleWrite ("writing title to " & $pc_xml_path & "\invent\all.csv" & "(" & FileReadLine ($pc_xml_path & "\invent\all.csv", 1) & ")" & @CRLF)
EndIf

$save_csv_all = FileOpen($pc_xml_path & "\invent\all.csv", 1)
;~ ConsoleWrite ("now saving $invent to " & $pc_xml_path & "\invent\all.csv" & @CRLF)
FileWrite($save_csv_all, $invent)
FileClose($save_csv_all)
EndIf
Next
EndFunc ;==>_make_xml_array
</pre>
15
edits