Vig
Starting to like KiXtart
Registered: 2001-11-14
Posts: 166
Loc: Saudi Arabia
|
At long last I think I'm ready to post my solution to inventorying/viewing installed software across a network.
I'm using 4.10, 4.02, and KixForms 2.0.3
There are three phases to the process.
First the data collection which is done by the SoftwareUDF.kix script. It's in the form of a UDF so it can be used for "scanning" remote computers. It hangs when it cannot connect to the remote host so when I use it I work a ping in there to test network connectivity.
Example: Computer($computer,$logpath)
The $computer var should not contain "\\" and the $logpath should end in a "\".
code:
Function Software($Computer,$LogPath) Dim $programs Dim $Subkeys $index = 0 While @error = 0 ReDim preserve $subkeys[Ubound($subkeys)+1] $index = $index+1 ?$computer $subkeys[Ubound($subkeys)] = EnumKey("\\$Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall",$index) Loop $nul = ReDirectOutput ("$logpath$computer.log",1) For Each $key in $subkeys $Displayname = ReadValue ("\\$Computer\HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$key","Displayname") If $Displayname <> "" ReDim preserve $programs[Ubound ($programs)+1] $programs[Ubound($programs)] = $Displayname EndIf Next join($programs,"~*~") $nul = ReDirectOutput("") EndFunction
Second phase is parsing all of the .log files obtained from the first script and adding the data to a microsoft access data base.
You'll need to create an access database with one table called TBL_PROGRAM. In the table there should be two columns, first "Computer" second "Program".
Since I'm no expert on COM scripting, this script will only work with 4.02. Props to Breaker since I only modified his script. I should also add that any program name with a ' in it will have it striped out.
$Loggpath should point to the directory where the .dat files are located (should end in "\"). $DBPATH should point to where the data base is located (should end in "\"). $DBFile should be the name of your data base file.
code:
$Loggpath = "H:\loggs\" $DBPath = "H:\loggs\" $DBFile = "inventory.mdb"
$RC=SetOption("WrapAtEOL","On") $DSN="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBPath$DBFile" $Connection = CreateObject("ADODB.Connection") $Command = CreateObject("ADODB.Command") $Recordset = CreateObject("ADODB.Recordset") If $Connection ? "Connected" $Connection.ConnectionString = $DSN $Connection.Open() $Command.ActiveConnection = $Connection $Recordset.CursorType = 3 $Recordset.LockType = 3 $Recordset.ActiveCommand = $Command $file = Dir("$loggPath*.log") While $file <> "" AND @error = 0 $computer = SubStr($file,1,InStr($file,".log")-1) $nul = Open(1,"$loggpath$file") If @error <> 0 ?@serror Exit EndIf $ProgArray = ReadLine(1) If @error <> 0 ?@serror Gosub End EndIf $ProgArray = Split($ProgArray,"~*~") For Each $program in $ProgArray If InStr($Program,"'") <> 0 $A = Split($Program,"'") For Each $B in $A $C=$C+$B Next $Program = $C $C="" EndIf $CHECK_ENTRY_PROGRAM = "SELECT * FROM TBL_PROGRAM WHERE COMPUTER='$computer' AND PROGRAM='$program';" $Command.CommandText = $CHECK_ENTRY_PROGRAM $Recordset.Open($Command) If $Recordset.RecordCount < 1 $Recordset.AddNew If @ERROR <> 0 ?@SERROR EndIf $Recordset.Fields("Computer").Value = "$computer" If @ERROR <> 0 ?@SERROR EndIf $Recordset.Fields("Program").Value = "$program" If @ERROR <> 0 ?@SERROR EndIf EndIf $Recordset.Update $Recordset.Close() Next ?"$computer Completed Successfully" :End $nul=Close(1) $file = Dir() Loop $Connection.Close() $Connection = 0 $Recordset = 0 $Command = 0 Else Goto error EndIf :end ?$numarr Exit 321 :error Exit
Last phase is the feedback form. Basically there’s two ways to view the information in the data base. First is a list of all computers in the DB, as you select a computer name it shows what software is installed on that computer. Second is list of all software on the computers you collected data from. As you select a software name it returns a list of computers that software is installed on.
Since the current release of KixForm does not automatically sort the listbox, the software listbox is a bit of a mess. I'm hoping the KixForm 2.0.4 release will include the Sorted property which will make the software list much easier to navigate through. I could use one of the sort array UDF's, but that will dramatically lengthen the time between clicking on "Search for Software by Computer" and the list popping up. Because this process is already lengthy (longer depending on how many computers you collected data from) I've added a progress bar so you don't think the script is hanging.
$DBPath should point to where you data base is located (should end in "\"). $DBFile is the name of your data base.
code:
Break on
Dim $SearArr $DBPath = "h:\loggs\" $DBFile = "inventory.mdb"
$FORM = CreateObject("Kixtart.FORM")
$FORM.CAPTION = "Software Inventory" $FORM.HEIGHT = 200 $FORM.WIDTH = 210 $FORM.FONTNAME = "Arial" $FORM.FONTSIZE = 9 $FORM.CENTER
$SoftButton = $FORM.CommandButton("Search for Software by Computer",3,3,$FORM.Width-12,$FORM.Height/2-34) $CompButton = $FORM.CommandButton("Search for Computer by Software",3,$SoftButton.Height+7,$FORM.Width-12,$FORM.Height/2-34) $QuitButton = $FORM.CommandButton("Quit",3,$CompButton.Top + $CompButton.Height + 4,$FORM.Width-12,30) $SoftButton.OnClick = '$$CompForm.Show if ubound($$ReturnData) = -1 $$ReturnData=GetDBData() CompForm($$ReturnData) endif' $CompButton.OnClick = '$$SoftForm.Show if ubound($$ReturnData2) = -1 $$ReturnData2=GetDBData() SoftForm($$ReturnData2) endif' $QuitButton.OnClick = 'Quit()'
$CompForm = CreateObject("Kixtart.FORM") $CompForm.CAPTION = "Search for Software by Computer" $CompForm.HEIGHT = 437 $CompForm.WIDTH = 337 $CompForm.FONTNAME = "Arial" $CompForm.FONTSIZE = 9 $CompForm.CENTER $FraComp = $CompForm.Frame("",5,5,320,402) $SelCompTxt = $FraComp.Label("Select a Computer:",10,20,150,20) $SelCompBox = $FraComp.ListBox(,10,40,150,150) $InsProTxt = $FraComp.Label("Installed Programs:",10,200,150,20) $InsProBox = $FraComp.ListBox(,10,220,300,150) $ExitButton = $FraComp.CommandButton("Exit",165,40,150-2,30) $ProgComp = $FraComp.ProgressBar(,10,375,300,20) $ProgComp.Min = 0 $ExitButton.OnClick = '$$CompForm.Show(0)'
$SoftForm = CreateObject("Kixtart.FORM") $SoftForm.CAPTION = "Search for Computer by Software" $SoftForm.HEIGHT = 437 $SoftForm.WIDTH = 337 $SoftForm.FONTNAME = "Arial" $SoftForm.FONTSIZE = 9 $SoftForm.CENTER $FraSoft = $SoftForm.Frame("",5,5,320,402) $SelProgTxt = $FraSoft.Label("Select Software:",10,20,150,20) $SelProBox = $FraSoft.ListBox(,10,40,300,150) $InsCompTxt = $FraSoft.Label("Installed on this Computer:",10,200,150,20) $InsCompBox = $FraSoft.ListBox(,10,220,150,150) $ExitButton2 = $FraSoft.CommandButton("Exit",165,220,150-2,30) $ProgSoft = $FraSoft.ProgressBar(,10,375,300,20) $ExitButton2.OnClick = '$$SoftForm.Show(0)'
$FORM.Show $Form.SetFocus
While $FORM.Visible OR $CompForm.Visible OR $SoftForm.Visible $=Execute($FORM.DoEvents) Loop
Function CompForm($ReturnData) $1=1 $0=0 $CompForm.SetFocus $ProgComp.Max = Val(Ubound($ReturnData[0])) $SelCompBox.List = StripCopies($ReturnData[0]) $SelCompBox.OnClick = '$$InsProBox.List = GetInfo($$SelCompBox.Value,$$0,$$1,$$ReturnData)' EndFunction
Function SoftForm($ReturnData) $1=1 $0=0 $SoftForm.SetFocus $ProgSoft.Max = Val(Ubound($ReturnData[1])) $SelProBox.List = StripCopies($ReturnData[1]) $SelProBox.OnClick = '$$InsCompBox.List = GetInfo($$SelProBox.Value,$$1,$$0,$$ReturnData2)' EndFunction
Function GetDBData() Dim $CompArr Dim $ProgArr Dim $DBArr[2] $connect = CreateObject("ADODB.Connection") $connectstring = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=$DBPath$DBFile" $connect.Open($connectstring) $queryDB = "SELECT * FROM TBL_PROGRAM" $queryDB = $connect.Execute($queryDB) While NOT $queryDB.EOF $dataComp=$queryDB.Fields("Computer").value $dataProg=$queryDB.Fields("Program").value $queryDB.movenext ReDim preserve $CompArr[Ubound($CompArr)+1] ReDim preserve $ProgArr[Ubound($ProgArr)+1] $CompArr[Ubound($CompArr)] = $dataComp $ProgArr[Ubound($ProgArr)] = $dataprog Loop $connect.Close $DBArr[0] = $CompArr $DBArr[1] = $ProgArr $GetDBData = $DBArr EndFunction
Function GetInfo($SearchFor,$SMultiNum,$RMultiNum,$Array) Dim $InfoArray $inter = 0 For Each $find in $Array[$SMultiNum] If $find = "$SearchFor" ReDim preserve $InfoArray[Ubound($InfoArray)+1] $InfoArray[Ubound($InfoArray)] = $Array[$RMultiNum][$inter] EndIf $inter = $inter + 1 Next $GetInfo = $InfoArray EndFunction
Function StripCopies($striArray) $on = 1 Dim $searArr For Each $add in $StriArray If Ubound($SearArr) = -1 ReDim $searArr[0] $SearArr[0] = $add EndIf $counter = 0 While Ubound($SearArr)+1 <> $counter If $add = $searArr[$counter] $on = 1 EndIf $counter = $counter + 1 Loop $counter = 0 If $on = 0 ReDim preserve $SearArr[Ubound($SearArr)+1] $SearArr[Ubound($SearArr)] = $add EndIf $on = 0 $ProgComp.Value = $ProgComp.Value+1 $ProgSoft.Value = $ProgSoft.Value+1 Next $ProgComp.Value = 0 $ProgSoft.Value = 0 $StripCopies = $SearArr EndFunction
Don't know why I bother but here are the pics hosted from geocities.
If those don't work just go here http://www.geocities.com/greenmaze/ and take a look at menu.jpg sbc.jpg and cbs.jpg.
Let me know how to improve this. Thanks.
|