Shaun_Hill
(Getting the hang of it)
2004-11-15 01:59 PM
Asset Inventory to Access Database

Hi Guys,

I wonder if you geniuses can help me. I am having a problem with a script that i've been setting up. I'm capturing information from workstations and then writing it to an access database. The script works brilliantly and is fast accept that when I run it as a logon script it cant find my database path which is in a variable! It works well if i run it straight. I've included the script seeing as i have never contributed anything before I might as well now... But does anybody know what the reason for this is? I'm not exacly a pro but I can usually manage!

Herewith the script, enjoy:

;*** CREATE AN ACCESS DATABASE WITH A TABLE NAMED COMPUTERS****
;*** CREATE THE FOLLOWING FIELDS: COMPUTERNAME, DOMAIN, SYSNAME
;*** OSNAME, MANUFACTURER, OSVERSION, OSBUILD, OSTYPE, LANGUAGE
;*** SERVICEPACK, BOOTDEVICE, SYSTEMDEVICE, WINDIR, SYSDIR, INSTALLDATE
;*** LASTBOOTTIME, OSSERIAL, SYSMANUFACTURER, SYSMODEL, SYSSERIAL, SYSBIOSVER
;*** SYSBIOSDATE, CPUMANUFACTURER, CPUDESCRIPTION, CPUSPEED, MAXCLOCK, FAMILY
;*** STEPPING, DEVICEID, SYSMEMORY, DISKNAMES, VOLNAMES, DISKNAMES, DISKSIZE
;*** FILESYS, FREESPACE, VIDEOCARD, VIDEORES, PRINTERS, NICCARD, MODIFYDATETIME
;*** APPLICATIONS, SERVICES, USERNAME

DIM $DBpath
;*** CONFIGURE DATABASE PATH***
$DBpath = "\\SERVERNAME\FOLDER\FOLDER\ITAssets.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

BREAK ON CLS

;**** DECLARE VARIABLES ***

DIM $CNstring, $CMDtxt, $cn, $cmd, $rs
DIM $ModifyDateTime, $computername, $username, $domain, $sysname, $osname
DIM $Manufacturer, $OSVersion, $OSBuild, $OSType, $Language, $ServicePack
DIM $BootDevice, $SystemDevice, $WinDir, $SysDir, $InstallDate, $LastBoottime
DIM $OSSerial, $SysManufacturer, $SysModel, $SysSerial, $SystemBIOSVer, $SysBIOSDate
DIM $CPUManufacturer, $CPUDescription, $CPUSpeed, $MaxClock, $Family, $Stepping
DIM $DeviceID, $SysMemory, $DiskNames, $VolNames, $DiskSize
DIM $FileSys, $FreeSpace, $VideoCard, $VideoRes, $Modem, $Printers, $ptr, $NicCard, $nic



If Exist("$DBpath") = 0
? "IT Assets Database Not Found. Aborting..."
Sleep 3
Goto end
EndIf

;*** CONFIGURE DATABASE CONNECTION STRING ***
$CNstring = "provider=microsoft.jet.oledb.4.0;data source=$DBpath;persist security info=false"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)

;*** COLLECT WORKSTAION ASSET INFORMATION

$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$domain = @domain
$sysname = WMIQuery("CSName","Win32_OperatingSystem")
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$Manufacturer = WMIQuery("Manufacturer","Win32_OperatingSystem")
$OSVersion = WMIQuery("Version","Win32_OperatingSystem")
$OSBuild = WMIQuery("BuildNumber","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$Language = WMIQuery("OSLanguage","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$BootDevice = WMIQuery("BootDevice","Win32_OperatingSystem")
$SystemDevice = WMIQuery("SystemDevice","Win32_OperatingSystem")
$WinDir = WMIQuery("WindowsDirectory","Win32_OperatingSystem")
$SysDir = WMIQuery("SystemDirectory","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = WMIQuery("LastBootupTime","Win32_OperatingSystem")
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$SystemBIOSVer = WMIQuery("SMBIOSBIOSVersion","Win32_BIOS")
$SysBIOSDate = WMIQuery("Version","Win32_BIOS")
$CPUManufacturer = WMIQuery("manufacturer","Win32_Processor")
$CPUDescription = WMIQuery("description","Win32_Processor")
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
$MaxClock = WMIQuery("maxclockspeed","Win32_Processor")
$Family = WMIQuery("family","Win32_Processor")
$Stepping = WMIQuery("stepping","Win32_Processor")
$DeviceID = WMIQuery("deviceid","Win32_Processor")
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
$DiskNames = WMIQuery("name","Win32_LogicalDisk")
$VolNames = WMIQuery("volumename","Win32_LogicalDisk")
$DiskSize = WMIQuery("size","Win32_LogicalDisk")
$FileSys = WMIQuery("filesystem","Win32_LogicalDisk")
$FreeSpace = WMIQuery("freespace","Win32_LogicalDisk")
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
$Modem = WMIQuery("Description","Win32_POTSModem")
$Printers = WMIQuery("Name","Win32_printer")
for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
$NicCard = $nic
$Applications = WMIQuery("Caption","Win32_Product")
$Services = WMIQuery("Caption","Win32_Service")

endif
next

FUNCTION WMIQuery($what,$where,)
dim $strQuery, $objEnumerator, $value
$strQuery = "Select $what From $where"
$SystemSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//@WKSTA")
$objEnumerator = $SystemSet.ExecQuery($strQuery)
For Each $objInstance in $objEnumerator
If @Error = 0 and $objInstance <> ""
$=execute("$$value = $$objInstance.$what")
$WMIQuery="$value"+"|"+"$WMIQuery"
EndIf
Next
$WMIQuery=left($WMIQuery,len($WMIQuery)-1)
exit @error
ENDFUNCTION

;*** ADD RECORDS TO THE DATABASE ***

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
$rs.addnew
EndIf

$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("DOMAIN").value = $domain
$rs.fields.item("SYSNAME").value = $Sysname
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("MANUFACTURER").value = $Manufacturer
$rs.fields.item("OSVERSION").value = $OSVersion
$rs.fields.item("OSBUILD").value = $OSBuild
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("LANGUAGE").value = $Language
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("BOOTDEVICE").value = $BootDevice
$rs.fields.item("SYSTEMDEVICE").value = $SystemDevice
$rs.fields.item("WINDIR").value = $WinDir
$rs.fields.item("SYSDIR").value = $SysDir
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("SYSBIOSVER").value = $SystemBIOSVer
$rs.fields.item("SYSBIOSDATE").value = $SysBIOSDate
$rs.fields.item("CPUMANUFACTURER").value = $CPUManufacturer
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
$rs.fields.item("MAXCLOCK").value = $MaxClock
$rs.fields.item("FAMILY").value = $Family
$rs.fields.item("STEPPING").value = $Stepping
$rs.fields.item("DEVICEID").value = $DeviceID
$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("DISKNAMES").value = $DiskNames
$rs.fields.item("VOLNAMES").value = $VolNames
$rs.fields.item("DISKNAMES").value = $DiskNames
$rs.fields.item("DISKSIZE").value = $DiskSize
$rs.fields.item("FILESYS").value = $FileSys
$rs.fields.item("FREESPACE").value = $FreeSpace
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
$rs.fields.item("PRINTERS").value = $Printers
$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("APPLICATIONS").value = $Applications
$rs.fields.item("SERVICES").value = $Services
$rs.fields.item("USERNAME").value = $Username

$rs.update

$rs.Close


JochenAdministrator
(KiX Supporter)
2004-11-15 02:10 PM
Re: Asset Inventory to Access Database

Smells like the server isn't available at logon ... maybe there is a mapped drive behind this ??

Shaun_Hill
(Getting the hang of it)
2004-11-15 02:15 PM
Re: Asset Inventory to Access Database

No. The database and path are accessible! the script runs beutifully if I drag the .kix file on kix32.exe. 100% no problems. Only when I'm logging on to the domain does it not find/hold the path. I dont understand why not.

Howard Bullock
(KiX Supporter)
2004-11-15 02:23 PM
Re: Asset Inventory to Access Database

What symptoms indicate that the script can not find the DB file? I do not see any logging in your script that would document what exactly the problem is. Please add some additional conditionals as well as check @error and @serror frequently and log a description of the check, the values of variables, and the result to a file. This way you can review all the nasty details of the script execution.



Shaun_Hill
(Getting the hang of it)
2004-11-15 02:30 PM
Re: Asset Inventory to Access Database

mmmm... and im so not in the mood for debugging today. Thanks I will add some error checking. Thought maybe this is a common problem that is well documented.

LonkeroAdministrator
(KiX Master Guru)
2004-11-15 02:31 PM
Re: Asset Inventory to Access Database

lol.
well documented common problem?
hehee...


Howard Bullock
(KiX Supporter)
2004-11-15 02:49 PM
Re: Asset Inventory to Access Database

Are you even sure the script is executing during logon? Is this an XP client? If so, could the XP fast logon optimization be causing you grief?

Windows XP Professional Fast Logon Optimization


Les
(KiX Master)
2004-11-15 02:56 PM
Re: Asset Inventory to Access Database

Well... you say it runs outside of the logon context. when you do run it after logon, are you running all the same scripts that would run at logon, or just this one? This does not look like your entire logon script so you may have some var scope issues if called from another script.

There are a few things that don't sit right.

$DBpath = "\\SERVERNAME\FOLDER\FOLDER\ITAssets.mdb"
is not right.

$DBpath = "\\SERVERNAME\SHARE\FOLDER\ITAssets.mdb"
is more like it.

You should not put vars in quotes!
If Exist("$DBpath") = 0

If Exist($DBpath) = 0

and don't use GOTO!


Les
(KiX Master)
2004-11-15 02:59 PM
Re: Asset Inventory to Access Database

I think he is CALLing that script and his CALL is assuming the correct folder and is failing to find the script.

Howard Bullock
(KiX Supporter)
2004-11-15 05:47 PM
Re: Asset Inventory to Access Database

That would go back to the proper logging of script execution. His log should be recording if the script to be called has been found or not.

Code:
Function CallScript($ScriptFile)

dim $ScriptFile
WriteLog("Calling " + $ScriptFile)
If Exist($ScriptFile)
WriteLog("Executing " + $ScriptFile)
Call $ScriptFile
WriteLog ("Returned from " + $ScriptFile)
Else
WriteLog ("File Not Found: " + $ScriptFile )
Endif
Endfunction

Function WriteLog($text)
dim $RC, $text, $LogFile, $Filehandle
$Filehandle = 1
$LogFile = "%temp%\logon.log"
$RC=Writeline ($Filehandle, "@Date @Time - $Text" + Chr(13) + Chr(10))
if $RC<0
$RC=Close ($Filehandle)
$RC=Open ($Filehandle, $LogFile, 5)
Select
Case $RC=-1
$RC=MessageBox ("Invalid file name ($LogFile) specified for log file.","Logon Script Error",48)
Case $RC=0
WriteLog ($Text)
Case $RC=>0
$RC=MessageBox ("Error($RC) while attempting to open log file ($LogFile).","Logon Script Error",48)
Endselect
Endif
EndFunction



And i know that the code has not yet been cleaned up and that some vars are in strings.


Shaun_Hill
(Getting the hang of it)
2004-11-16 06:37 AM
Re: Asset Inventory to Access Database

Morning Gentlmen,

Well I've resolved the problem! Script is executing properly now and I never changed a thing in the script.
I had a primary script which contains a number of calls to various scripts. ie
if ingroup("screensaver")
blahblah
call wadawada.kix
endif
if ingroup("othergroups")
blahblah
etc etc
endif

There must have been about 10 different ones and the Asset script was the last in the list to be called if member of that group. All i did was make it the first called script!
How on earth does that make a difference???? Im bedazzled and confused! Maybe you could shed some light on this matter! as i said in the beggining, the script always worked as is. just had the problem when it was called from the during logon process. It definately was calling the script! Thanks for all your help. Later ill post my Symantec Corporate edition scriot for you all! its very powerful and is an awesome compliment to SAV


Shaun_Hill
(Getting the hang of it)
2004-11-16 07:10 AM
Re: Asset Inventory to Access Database

I think Les was correct. It has something to do with global variables! only thing that makes sense to me... Could probably have also got it to work if I had shell that particular script

Sealeopard
(KiX Master)
2004-11-17 03:36 AM
Re: Asset Inventory to Access Database

You might want to consider converting the sub-scripts to UDFs that are getting CALLed as this will make it easier to pass parameters. You might also want to take a look at the DB...() UDFs, which offer a couple of canned database functions.

geemeetheway
(Lurker)
2004-11-17 02:40 PM
Re: Asset Inventory to Access Database

it is possible to post the last version of that script. Please

Kdyer
(KiX Supporter)
2004-11-24 09:28 AM
Re: Asset Inventory to Access Database

Looking at your script, there needs to be some logic for say more than one printer..

Kent


Shaun_Hill
(Getting the hang of it)
2004-12-01 08:36 AM
Re: Asset Inventory to Access Database

I have about 20 printers installed and it gets them all!
I've noticed that the software is not 100%
Actually it only records software that was installed via windows installer... eg SQL server is not listed even though I have it installed. Probably have to get the software list from registry


Shaun_Hill
(Getting the hang of it)
2004-12-02 10:27 AM
Re: Asset Inventory to Access Database

Just to inform you all that may be using this script. The software section has a small little problem in that the software i.e. WMI32_Product only returns software that was installed using windows installer! Thus it is not 100% accurate. I suggest on the software section to pull the data from the registry! maybe sombody has a neat script to do this already and it can be incorporated into this existing script.

Also, to write the data to SQL database just change the connection string and wambam thank you mam!

$CNstring = "DRIVER={SQL Server};SERVER=MTCDEV1;UID=assetsdb;PWD=assetsdb;DATABASE=Assets"




NTDOCAdministrator
(KiX Master)
2004-12-02 07:00 PM
Re: Asset Inventory to Access Database

I have a fairly extensive script here that you could modify or review the code to grab what you want from it.

My Computer Info - for Help Desk use PART 3
http://www.kixtart.org/ubbthreads/showflat.php?Cat=&Number=116475


Shaun_Hill
(Getting the hang of it)
2004-12-04 02:08 PM
Re: Asset Inventory to Access Database

Updated Script: Writes to SQL DB, GET ALL SOFTWARE BUT IN TWO DB.FIELDS

;*** CREATE A SQL DATABASE WITH A TABLE NAMED COMPUTERS****
;*** CREATE THE FOLLOWING FIELDS: COMPUTERNAME, DOMAIN, SYSNAME
;*** OSNAME, MANUFACTURER, OSVERSION, OSBUILD, OSTYPE, LANGUAGE
;*** SERVICEPACK, BOOTDEVICE, SYSTEMDEVICE, WINDIR, SYSDIR, INSTALLDATE
;*** LASTBOOTTIME, OSSERIAL, SYSMANUFACTURER, SYSMODEL, SYSSERIAL, SYSBIOSVER
;*** SYSBIOSDATE, CPUMANUFACTURER, CPUDESCRIPTION, CPUSPEED, MAXCLOCK, FAMILY
;*** STEPPING, DEVICEID, SYSMEMORY, DISKNAMES, VOLNAMES, DISKNAMES, DISKSIZE
;*** FILESYS, FREESPACE, VIDEOCARD, VIDEORES, PRINTERS, NICCARD, MODIFYDATETIME
;*** APPLICATIONS, APPLICATIONS2, SERVICES, USERNAME,

CLS
AT (1,1) "Your IT Department is conducting an Asset Audit of this Workstation."
AT (2,1) "Please wait while the information is collected."

;**** DECLARE VARIABLES ***

DIM $CNstring, $CMDtxt, $cn, $cmd, $rs
DIM $ModifyDateTime, $computername, $username, $domain, $sysname, $osname
DIM $Manufacturer, $OSVersion, $OSBuild, $OSType, $Language, $ServicePack
DIM $BootDevice, $SystemDevice, $WinDir, $SysDir, $InstallDate, $LastBoottime
DIM $OSSerial, $SysManufacturer, $SysModel, $SysSerial, $SystemBIOSVer, $SysBIOSDate
DIM $CPUManufacturer, $CPUDescription, $CPUSpeed, $MaxClock, $Family, $Stepping
DIM $DeviceID, $SysMemory, $DiskNames, $VolNames, $DiskSize
DIM $FileSys, $FreeSpace, $VideoCard, $VideoRes, $Modem, $Printers, $ptr, $NicCard, $nic
DIM $Applications, $Services, $Applications2, $InstalledSoftwareArray
DIM $element, $Software



function ASort($array, OPTIONAL $order)
; sort order: 0 = ascending, 1 = decending
dim $index, $x, $y, $tmp, $changed
$Asort=$array
$order=0+$order
do
$changed=0
for $index = 0 to ubound($asort)-1
$x=$asort[$index]
$y=$asort[$index+1]
if ($x > $y and 1-$order) or ($x < $y and $order)
$tmp=$x
$asort[$index]=$y
$asort[$index+1]=$tmp
$changed=1
endif
next
until $changed=0
endfunction

FUNCTION GetSoftwareList (OPTIONAL $sort)
DIM $arrayindex, $enumindex, $component, $dn, $regkey, $swarray[200]
$regkey='HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall'
$enumindex=0
$arrayindex=0
:gisloop
$component=EnumKey($regkey, $enumindex)
IF NOT @error
IF NOT (Len($component)=7 AND Left($component,1)='Q')
; above line excludes hotfixes from listing
IF NOT (0+ReadValue($regkey+'\'+$component,'SystemComponent'))
$dn=ReadValue($regkey+'\'+$component,'DisplayName')
IF $dn
$swarray[$arrayindex]=$dn
$arrayindex=$arrayindex+1
ENDIF
ENDIF
$enumindex=$enumindex+1
GOTO gisloop
ENDIF
ENDIF
REDIM PRESERVE $swarray[$arrayindex]
IF $sort
$getsoftwarelist=asort($swarray)
ELSE
$getsoftwarelist=$swarray
ENDIF
ENDFUNCTION ; - GetSoftwareList -


;*** CONFIGURE DATABASE CONNECTION STRING ***
$CNstring = "DRIVER={SQL Server};SERVER=MTCDEV1;UID=assetsdb;PWD=assetsdb;DATABASE=Assets"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)

;*** COLLECT WORKSTAION ASSET INFORMATION

$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$domain = @domain
$sysname = WMIQuery("CSName","Win32_OperatingSystem")
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$Manufacturer = WMIQuery("Manufacturer","Win32_OperatingSystem")
$OSVersion = WMIQuery("Version","Win32_OperatingSystem")
$OSBuild = WMIQuery("BuildNumber","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$Language = WMIQuery("OSLanguage","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$BootDevice = WMIQuery("BootDevice","Win32_OperatingSystem")
$SystemDevice = WMIQuery("SystemDevice","Win32_OperatingSystem")
$WinDir = WMIQuery("WindowsDirectory","Win32_OperatingSystem")
$SysDir = WMIQuery("SystemDirectory","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = WMIQuery("LastBootupTime","Win32_OperatingSystem")
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$SystemBIOSVer = WMIQuery("SMBIOSBIOSVersion","Win32_BIOS")
$SysBIOSDate = WMIQuery("Version","Win32_BIOS")
$CPUManufacturer = WMIQuery("manufacturer","Win32_Processor")
$CPUDescription = WMIQuery("description","Win32_Processor")
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
$MaxClock = WMIQuery("maxclockspeed","Win32_Processor")
$Family = WMIQuery("family","Win32_Processor")
$Stepping = WMIQuery("stepping","Win32_Processor")
$DeviceID = WMIQuery("deviceid","Win32_Processor")
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
$DiskNames = WMIQuery("name","Win32_LogicalDisk")
$VolNames = WMIQuery("volumename","Win32_LogicalDisk")
$DiskSize = WMIQuery("size","Win32_LogicalDisk")
$FileSys = WMIQuery("filesystem","Win32_LogicalDisk")
$FreeSpace = WMIQuery("freespace","Win32_LogicalDisk")
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
$Modem = WMIQuery("Description","Win32_POTSModem")
$Printers = WMIQuery("Name","Win32_printer")
$Applications = WMIQuery("Caption","Win32_Product")
$InstalledSoftwareArray=GetSoftwareList(1)
$Software = Join($InstalledSoftwareArray,"|")
$Services = WMIQuery("Caption","Win32_Service")
for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
$NicCard = $nic

endif
next

FUNCTION WMIQuery($what,$where,)
dim $strQuery, $objEnumerator, $value
$strQuery = "Select $what From $where"
$SystemSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//@WKSTA")
$objEnumerator = $SystemSet.ExecQuery($strQuery)
For Each $objInstance in $objEnumerator
If @Error = 0 and $objInstance <> ""
$=execute("$$value = $$objInstance.$what")
$WMIQuery="$value"+"|"+"$WMIQuery"
EndIf
Next
$WMIQuery=left($WMIQuery,len($WMIQuery)-1)
exit @error
ENDFUNCTION

;*** ADD RECORDS TO THE DATABASE ***

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
$rs.addnew
EndIf

$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("DOMAIN").value = $domain
$rs.fields.item("SYSNAME").value = $Sysname
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("MANUFACTURER").value = $Manufacturer
$rs.fields.item("OSVERSION").value = $OSVersion
$rs.fields.item("OSBUILD").value = $OSBuild
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("LANGUAGE").value = $Language
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("BOOTDEVICE").value = $BootDevice
$rs.fields.item("SYSTEMDEVICE").value = $SystemDevice
$rs.fields.item("WINDIR").value = $WinDir
$rs.fields.item("SYSDIR").value = $SysDir
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("SYSBIOSVER").value = $SystemBIOSVer
$rs.fields.item("SYSBIOSDATE").value = $SysBIOSDate
$rs.fields.item("CPUMANUFACTURER").value = $CPUManufacturer
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
$rs.fields.item("MAXCLOCK").value = $MaxClock
$rs.fields.item("FAMILY").value = $Family
$rs.fields.item("STEPPING").value = $Stepping
$rs.fields.item("DEVICEID").value = $DeviceID
$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("DISKNAMES").value = $DiskNames
$rs.fields.item("VOLNAMES").value = $VolNames
$rs.fields.item("DISKNAMES").value = $DiskNames
$rs.fields.item("DISKSIZE").value = $DiskSize
$rs.fields.item("FILESYS").value = $FileSys
$rs.fields.item("FREESPACE").value = $FreeSpace
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
$rs.fields.item("PRINTERS").value = $Printers
$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("APPLICATIONS").value = $Applications
$rs.fields.item("APPLICATIONS2").value = $Software
$rs.fields.item("SERVICES").value = $Services
$rs.fields.item("USERNAME").value = $Username

$rs.update

$rs.Close



Sealeopard
(KiX Master)
2004-12-04 02:39 PM
Re: Asset Inventory to Access Database

Please post code within CODE tags.

You should separate out functions and regular code from each other and not intermingle it.

It's also very bad programing preactices to use GOTO at all, you might want to gt rid of it.

Finally, the inventory will not detect if hardware changes on an already inventoried system.


basad
(Fresh Scripter)
2004-12-27 01:15 PM
Re: Asset Inventory to Access Database

I'm trying to run this script on my machine and it fails to update my Access 2000 database.

I can see that the script has gets a hold of the mdb file and starts to create the ldf file but finally machine information is not recorded even though it is successfully queried. Any help?

John


NTDOCAdministrator
(KiX Master)
2004-12-27 06:57 PM
Re: Asset Inventory to Access Database

Hello basad and welcome to the board.

Please let us know what KiXtart version you're using.

Please add error debugging to the script either to console or a file so that you can determine what is happening.


basad
(Fresh Scripter)
2004-12-28 05:25 AM
Re: Asset Inventory to Access Database

Thanks doc, I have solved the problem. I don't know why but by changing providers .

This:$CNstring = "provider=microsoft.jet.oledb.4.0;data source=$DBpath;persist security info=false"

To this:
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"

Regards,


willem05
(Lurker)
2005-01-03 01:33 PM
Re: Asset Inventory to Access Database

Hi,

I was just reading the code etc. . Thought it was great. I did a simple copy/paste and used it. Now I noticed that several fields in the database are not updated. Fields like DISKNAME, APPLICATIONS, INSTALLDATE etc. There are more fields NOT updated than that are... Is it my OS ?

I use kix4.22.0.0 and my laptop has XPSP2. I used the SQL-version on a SQL2000 server. Created 1 table called COMPUTERS...

Thanx for helping..

Gr,
Willem

Hi,
Little update... Make sure the fields in your Table are big eneough
That is surely a showstopper. Nothing said here....


backfight
(Getting the hang of it)
2013-10-30 12:40 PM
Re: Asset Inventory to Access Database

Hey there,

when i run the script (writing in the mdb file) i get in some cases the value "0" for Memory. How can i fix that?
Not all PCīs returns "0", but some.

Greets
Backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-10-30 01:31 PM
Re: Asset Inventory to Access Database

Try this:
 Code:
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
Be sure to download and insert the Memory UDF. The one I wrote a few years ago was discussed quite a bit and found to be the most consistent and accurate in its reporting. I haven't used it in a while, but just tested it on Windows 8 and Server 2012 before responding to your post and it reported accurate values. Download the latest version from the Kixtart UDF Library on my web site.

Note that this UDF returns System RAM, not Installed RAM Modules (the amount of RAM available to the system, not including shared Video or BIOS Cache). In my Server 2012 test, there is 4G RAM physically installed - 4x1G modules. The RAM reported was 4032, which is 64MB shy of the full amount. This is the memory "hole" for the BIOS. On my workstation, with 4G RAM, it reports 3327MB, the result of my video card sharing a 768MB block of RAM. If you are looking for total Installed RAM, you can fudge the result a bit with the following code. This assumes that you know the smallest RAM module installed in the hardware you are interrogating. For example, if you've determined that the smallest RAM module is 512MB for the majority of your systems, then set $MSize to 512. The result will be pretty accurate, but could be up to 512MB short, particularly with systems using shared video RAM.
 Code:
$MSize = 512				; Smallest RAM module in service

$M = Memory()				; get available RAM in MBytes
$Ma = $M / $MSize			; Divide by smallest module size
If $M Mod $MSize $Ma = $Ma + 1 EndIf	; If a fractional module is detected, add another full module
$Ma = $Ma * $MSize			; calc installed RAM by multiplying modules * ModuleSize

'  Reported: ' $M ?
'  Adjusted: ' $Ma ?
'Difference: ' 4096 - $Ma ?
With the code above (knowing that all of my systems have either 1 or 4G modules), both computers properly report 4096MB installed.

Glenn


AllenAdministrator
(KiX Supporter)
2013-10-30 02:16 PM
Re: Asset Inventory to Access Database

I don't remember the particulars and I don't know if Glenn has updated the memory UDF, but I ran into some issues with the Memory UDF a couple of years back. If you need another way to check this...

GetMemoryInfo - Get Information Related to the Memory and Slots on a PC
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201815#Post201815

How to use UDFs -
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=81943#Post81943

The rest of the UDFs are here -
http://www.kixtart.org/forums/ubbthreads.php?ubb=postlist&Board=7&page=1


Glenn BarnasAdministrator
(KiX Supporter)
2013-10-30 02:21 PM
Re: Asset Inventory to Access Database

It was updated to deal with X64 systems when you reported the issue. It currently works on all current platforms - XP through Win8; Server 2003 through 2012, and both x86 and x64 platforms.

Glenn


backfight
(Getting the hang of it)
2013-10-31 11:27 AM
Re: Asset Inventory to Access Database

Hi Glenn,
i have updated my script with your Memory UDF and your Code below. Now the entry in the mdb says that my pc has 3035MB Ram. The truth is that my pc has 2x4 GB Ram

How to read the dimms? and add. them?

Greetz
Backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-11-01 01:48 PM
Re: Asset Inventory to Access Database

I'm picking up a new workstation today w/ an i7 CPU and 8G RAM. It's the first of the "i" series that I'll be testing with. I'll be able to look into this on a wider platform base in the coming days and let you know what I find.

The issue is that the newer systems report the memory allocation differently than prior systems - I need to find the difference, find a way to identify the format, and then update the code to use the proper formula based on the data format.

Glenn


Glenn BarnasAdministrator
(KiX Supporter)
2013-11-03 02:47 PM
Re: Asset Inventory to Access Database

Found the bug - the updated UDF is posted in this thread for now. Once it has been script tested and K-Team approved, ;\) I'll update the UDF here and on my site.

Give it a try and let me know if it works.

Glenn


backfight
(Getting the hang of it)
2013-11-04 10:05 AM
Re: Asset Inventory to Access Database

Hi there,
it works!!! Thanks a lot!

May you have an idea to get the correct CPU Names?
In my mdb the description is like this: "x64 Family 6 Model 23 Stepping 10"

Greetz
Backfight


Mart
(KiX Supporter)
2013-11-05 05:06 PM
Re: Asset Inventory to Access Database

This works for me.

 Code:
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")

For Each $wmiObj in $wmiColl
    ? $wmiObj.Name	
Next

Sleep 5


backfight
(Getting the hang of it)
2013-11-06 08:48 AM
Re: Asset Inventory to Access Database

Hi,
thanks for your reply. Can you help me to intigrate the code?

Now i use this code:

 Code:
$CPUDescription = WMIQuery("description","Win32_Processor")


Do i have to "Dim" $wmiColl, $wmiObj and $wmiObj.Name?

Sorry iīm new in scripting.

Greetz
Backfight

EDIT:

Think this is the right intigration:

 Code:
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
$CPUDescription = $wmiObj.Name	
Next
Sleep 5


Works for me :-)


backfight
(Getting the hang of it)
2013-11-06 09:57 AM
Re: Asset Inventory to Access Database

Hi again,

the only thing i missed in the script is to list the connectet monitors.

iīve found a script but itīs hard to intigrate it.

 Code:
; Return monitor info.
 
Break ON
 
$=SetOption("Explicit","ON")
$=SetOption("WrapAtEOL","ON")
$=SetOption("ASCII","ON")

GLOBAL $VERBOSE

$VERBOSE=1	; Set to "0" to disable debug info
 
Dim $KEY_DISPLAY
Dim $iIndexPri,$iIndexSub
Dim $sMonitor,$sDevice
 
$KEY_DISPLAY="HKLM\SYSTEM\CurrentControlSet\Enum\Display"
 
; Iterate through possible displays.
Log("Starting scan for monitor info...")
$iIndexPri=0
$sMonitor=EnumKey($KEY_DISPLAY,$iIndexPri)
While Not @ERROR
	$sMonitor=$KEY_DISPLAY+"\"+$sMonitor
	Log("--------------------------------------------")
	Log("Primary key is '"+$sMonitor+"'")
	$iIndexSub=0
	$sDevice=EnumKey($sMonitor,$iIndexSub)
	while Not @ERROR
		$sDevice=$sMonitor+"\"+$sDevice
		Log(" Secondary key is '"+$sDevice+"'")
		If KeyExist($sDevice+"\Control")
			Log("  Control found - device assumed to be active")
			If Instr(ReadValue($sDevice,"HardwareID"),"Monitor\")=1
				Log("   Device type is monitor.")
				ParseEDID(ReadValue($sDevice+"\Device Parameters","EDID"))
			Else
				Log("   Device type is not monitor.")
			EndIf
		Else
			Log("  Control not found - device assumed to be inactive")
		EndIf
		$iIndexSub=$iIndexSub+1
		$sDevice=EnumKey($sMonitor,$iIndexSub)
	Loop
	$iIndexPri=$iIndexPri+1
	$sMonitor=EnumKey($KEY_DISPLAY,$iIndexPri)
Loop

Log("Completed scan for monitor info.")
Exit 0
 
Function ParseEDID($sEDID)
	Dim $iOffset, $sBlock
	If $sEDID="" 
		Log("    No EDID information associated with device")
		Exit 0
	EndIf
	; Check for valid EDID data
	If SubStr($sEDID,1,16)="00ffffffffffff00"
		Log("    EDID signature is valid")
	Else
		Log("    EDID signature is invalid: "+SubStr($sEDID,1,16))
		Exit 0
	EndIf
	Log("    "+$sEDID)
	Log("    EDID Version number is "
		+Execute("Exit &"+SubStr($sEDID,(&12+1)*2-1,2))
		+"."
		+Execute("Exit &"+SubStr($sEDID,(&13+1)*2-1,2)))
	; Look for serial number and model number in descriptor blocks.
	For $iOffset=54 To 108 Step 18
		$sBlock=SubStr($sEDID,$iOffset*2+1,18*2)
		Select
		Case Left($sBlock,8)="000000fc"
			"                 Model: "
			Bin2Str(SubStr($sBlock,9)) ?
		Case Left($sBlock,8)="000000fe"
			"            Other info: "
			Bin2Str(SubStr($sBlock,9)) ?
		Case Left($sBlock,8)="000000ff"
			"EDID 1.3 Serial number: "
			Bin2Str(SubStr($sBlock,9)) ?
		Case "Unknown type"
			Log("    Unknown type: "+Left($sBlock,8))
		EndSelect
	Next
	"EDID 1.2 Serial number: "+Execute("Exit &"+SubStr($sEDID,(&1C+1)*2-1,8))+@CRLF
	"   Week of manufacture: "+Execute("Exit &"+SubStr($sEDID,(&10+1)*2-1,2))+@CRLF
	"   Year of manufacture: "+(1990+Execute("Exit &"+SubStr($sEDID,(&11+1)*2-1,2)))+@CRLF
EndFunction
 
Function Bin2Str($s)
	Dim $c
 
	While $s
		$c=Execute("Exit &"+Left($s,2))
		; Truncate string at CR
		If $c=10 Exit 0 EndIf
		iF $c $Bin2Str=$Bin2Str+Chr($c) EndIf
		$s=SubStr($s,3)
	Loop

	Exit 0
EndFunction

Function Log($s)
	If $VERBOSE @DATE+" "+@TIME+" "+$s+@CRLF EndIf
	Exit 0
EndFunction


the lgofile looks like this:

 Code:
2013/01/10 12:29:52 Starting scan for monitor info...
2013/01/10 12:29:52 --------------------------------------------
2013/01/10 12:29:52 Primary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\ACR0027'
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\ACR0027\4&6cb7ad2&0&UID16843008'
2013/01/10 12:29:52   Control not found - device assumed to be inactive
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\ACR0027\4&6cb7ad2&0&UID50529024'
2013/01/10 12:29:52   Control not found - device assumed to be inactive
2013/01/10 12:29:52 --------------------------------------------
2013/01/10 12:29:52 Primary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\Default_Monitor'
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\Default_Monitor\4&6cb7ad2&0&12345678&00&02'
2013/01/10 12:29:52   Control not found - device assumed to be inactive
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\Default_Monitor\4&6cb7ad2&0&UID16843008'
2013/01/10 12:29:52   Control not found - device assumed to be inactive
2013/01/10 12:29:52 --------------------------------------------
2013/01/10 12:29:52 Primary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\SAM0831'
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\SAM0831\4&6cb7ad2&0&UID16843008'
2013/01/10 12:29:52   Control found - device assumed to be active
2013/01/10 12:29:52    Device type is monitor.
2013/01/10 12:29:52     EDID signature is valid
2013/01/10 12:29:52     00ffffffffffff004c2d3108343332302f1601030e301b782a90c1a259559c270e5054bfef80714f8100814081809500950fa940b300023a801871382d40582c4500dd0c1100001e000000fd00384b1e5111000a202020202020000000fc00534d533232413230302f343630000000ff0048344d434230343437320a2020000f
2013/01/10 12:29:52     EDID Version number is 1.3
2013/01/10 12:29:52     Unknown type: 023a8018
2013/01/10 12:29:52     Unknown type: 000000fd
                 Model: SMS22A200/460
EDID 1.3 Serial number: H4MCB04472
EDID 1.2 Serial number: 1498782759
   Week of manufacture: 47
   Year of manufacture: 2012
2013/01/10 12:29:52 --------------------------------------------
2013/01/10 12:29:52 Primary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\SAM0832'
2013/01/10 12:29:52  Secondary key is 'HKLM\SYSTEM\CurrentControlSet\Enum\Display\SAM0832\4&6cb7ad2&0&UID50529024'
2013/01/10 12:29:52   Control found - device assumed to be active
2013/01/10 12:29:52    Device type is monitor.
2013/01/10 12:29:52     EDID signature is valid
2013/01/10 12:29:52     00ffffffffffff004c2d3208343332302f16010380301b782a92c1a259559e270e5054bfef80714f8100814081809500b300a940950f023a801871382d40582c4500dd0c1100001e000000fd00384b1e5111000a202020202020000000fc00534d533232413230302f343630000000ff0048344d434230343435370a20200194
2013/01/10 12:29:52     EDID Version number is 1.3
2013/01/10 12:29:52     Unknown type: 023a8018
2013/01/10 12:29:52     Unknown type: 000000fd
                 Model: SMS22A200/460
EDID 1.3 Serial number: H4MCB04457
EDID 1.2 Serial number: 1498783271
   Week of manufacture: 47
   Year of manufacture: 2012
2013/01/10 12:29:52 Completed scan for monitor info.


but i only need "model", "SN" and "manufactur"

can anybody help me?

Backfight


ShaneEP
(MM club member)
2013-11-07 05:57 PM
Re: Asset Inventory to Access Database

You can try the Win32_DesktopMonitor query. Not sure if it will get all the info you are after.

 Code:
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")
For Each $wmiObj in $wmiColl
   $MonitorDescription = $wmiObj.Name
Next


ShaneEP
(MM club member)
2013-11-07 06:04 PM
Re: Asset Inventory to Access Database

Here is a link to the other information you get from Win32_DesktopMonitor, if the .Name is not sufficient.

http://msdn.microsoft.com/en-us/library/aa394122(v=vs.85).aspx


backfight
(Getting the hang of it)
2013-11-08 09:13 AM
Re: Asset Inventory to Access Database

Hey,

sorry but i only get "Standard" results. Like "Standard PNP Monitor"

Can you help me to intigrate my code and select only manufactor type and sn?

backfight


NTDOCAdministrator
(KiX Master)
2013-11-08 09:31 AM
Re: Asset Inventory to Access Database

Most monitors don't implement the required information to obtain it.

backfight
(Getting the hang of it)
2013-11-08 09:36 AM
Re: Asset Inventory to Access Database

Hi NTDOC,
the code i posted before is nearly perfekt. But i have problems to filter only that information i need and intigrate it.

backfight


ShaneEP
(MM club member)
2013-11-08 06:09 PM
Re: Asset Inventory to Access Database

I was afraid of that. Let me see about trimming that code that posted down.

ShaneEP
(MM club member)
2013-11-08 07:20 PM
Re: Asset Inventory to Access Database

So far, got it down to this version. Not sure what the best way to return the info is.

 Code:
getDisplays()

Function getDisplays()
   $KEY_DISPLAY="HKLM\SYSTEM\CurrentControlSet\Enum\Display"
   $iIndexPri=0
   $sMonitor=EnumKey($KEY_DISPLAY,$iIndexPri)
   While Not @ERROR
      $sMonitor=$KEY_DISPLAY+"\"+$sMonitor
      $iIndexSub=0
      $sDevice=EnumKey($sMonitor,$iIndexSub)
      while Not @ERROR
         $sDevice=$sMonitor+"\"+$sDevice
         If KeyExist($sDevice+"\Control")
            If Instr(ReadValue($sDevice,"HardwareID"),"Monitor\")=1
               $sEDID = ReadValue($sDevice+"\Device Parameters","EDID")
               If Len($sEDID) AND SubStr($sEDID,1,16)="00ffffffffffff00"
                  "Monitor "+(1+$iIndexSub) ?
                  "------------------------------" ?
                  For $iOffset=54 To 108 Step 18
                     $sBlock=SubStr($sEDID,$iOffset*2+1,18*2)
                     Select
                     Case Left($sBlock,8)="000000fc"
                        "                 Model: "
                        Bin2Str(SubStr($sBlock,9)) ?
                     Case Left($sBlock,8)="000000fe"
                        "            Other info: "
                        Bin2Str(SubStr($sBlock,9)) ?
                     Case Left($sBlock,8)="000000ff"
                        "EDID 1.3 Serial number: "
                        Bin2Str(SubStr($sBlock,9)) ?
                     EndSelect
                  Next
                  "EDID 1.2 Serial number: "+Execute("Exit &"+SubStr($sEDID,(&1C+1)*2-1,8)) ?
                  @CRLF+@CRLF
               EndIf
            EndIf
         EndIf
         $iIndexSub=$iIndexSub+1
         $sDevice=EnumKey($sMonitor,$iIndexSub)
      Loop
      $iIndexPri=$iIndexPri+1
      $sMonitor=EnumKey($KEY_DISPLAY,$iIndexPri)
   Loop
EndFunction

get $

Exit 0

Function Bin2Str($s)
   Dim $c
   While $s
      $c=Execute("Exit &"+Left($s,2))
      ; Truncate string at CR
      If $c=10 Exit 0 EndIf
      iF $c $Bin2Str=$Bin2Str+Chr($c) EndIf
      $s=SubStr($s,3)
   Loop
   Exit 0
EndFunction


NTDOCAdministrator
(KiX Master)
2013-11-09 01:00 AM
Re: Asset Inventory to Access Database

You really don't much choice except perhaps to either leave the entry blank or mark it as "Undetected" or something like that. If there is no data then there is no data.

ShaneEP
(MM club member)
2013-11-09 04:15 PM
Re: Asset Inventory to Access Database

Strangely, the registry method does seem to return much more info than WMI. At least on my test system. I'm just trying to decide how to return the info...Probably some type of array of arrays containing the Model, SNs for each monitor found.

NTDOCAdministrator
(KiX Master)
2013-11-12 07:03 AM
Re: Asset Inventory to Access Database

You could incorporate a an array and try to fill it with information from both locations. I'm just saying that some monitors do not provide SQUAT about them and in those cases you'd still need to account for blank information.

backfight
(Getting the hang of it)
2013-11-26 09:55 AM
Re: Asset Inventory to Access Database

Good Morning,

@ ShaneEP: Is there anything new? Do you get the infos returned?

Greetz Backfight


backfight
(Getting the hang of it)
2013-11-29 11:14 AM
Re: Asset Inventory to Access Database

Hi again,

got another question.
Iīve found some code from Allen in this forum:

 Code:

Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
            ? $Product + ': ' + $Key 
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)
      
  function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 
Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop
  Exit VarType($SearchReg) = 8
EndFunction
 
Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
 EndFunction




Can somebody help me to integrate the results in my Database?
Wanna get all MS Produkt Keys in seperate rows per PC

Thanx a lot

Greetz Backfight


LonkeroAdministrator
(KiX Master Guru)
2013-11-29 05:30 PM
Re: Asset Inventory to Access Database

you did not specify what was by Allen.
I did not see get_product_key() as an udf but there is getcdkey() which seems to accomplish the same.

so, I figure the non-udf part is yours. given that searchreg() is employed to find all the productid's, this part seems repeating:
 Code:
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
            ? $Product + ': ' + $Key 
        EndIf
      EndIf

well, maybe MS does some extra mangling on the data, but yet this is:
$guid="{" + split(split($value,"{")[1],"}")[0] + "}"

that is wrong as if the value does not contain { kixtart will crash.

and then finally to your original actual question.
can someone help you integrate? yes. somebody can. if you actually give enough information in your post on what kind of database you are using.
usually this comes in a form that you have already started coding it but have issues with getting the calls right.
at the moment it looks to me that you want your code written by you.
if that is the case, unless you offer decent bounty, you can count me out.


AllenAdministrator
(KiX Supporter)
2013-11-29 06:06 PM
Re: Asset Inventory to Access Database

Pretty sure he is referring to this...
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729


backfight
(Getting the hang of it)
2013-12-02 09:49 AM
Re: Asset Inventory to Access Database

Hi Lonkero,

sorry for my incomplete question. Iīm a fresh scripter and need help to get code intigrated.
Yes i wanna code my self.

My Code is nearly the same as posted at the beginning of this posting:

 Code:
;*** CREATE AN ACCESS DATABASE WITH A TABLE NAMED COMPUTERS****
;*** CREATE THE FOLLOWING FIELDS: COMPUTERNAME, DOMAIN
;*** OSNAME, MANUFACTURER, OSVERSION, OSBUILD, OSTYPE, LANGUAGE
;*** SERVICEPACK, BOOTDEVICE, SYSTEMDEVICE, WINDIR, SYSDIR, INSTALLDATE
;*** LASTBOOTTIME, OSSERIAL, SYSMANUFACTURER, SYSMODEL, SYSSERIAL, SYSBIOSVER
;*** SYSBIOSDATE, CPUMANUFACTURER, CPUDESCRIPTION, CPUSPEED, MAXCLOCK, FAMILY
;*** STEPPING, DEVICEID, SYSMEMORY, DISKNAMES, VOLNAMES, DISKNAMES, DISKSIZE
;*** FILESYS, FREESPACE, VIDEOCARD, VIDEORES, PRINTERS, NICCARD, MODIFYDATETIME
;*** APPLICATIONS, SERVICES, USERNAME

DIM $DBpath
;*** CONFIGURE DATABASE PATH***
$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

BREAK ON CLS

;**** DECLARE VARIABLES ***

DIM $CNstring, $CMDtxt, $cn, $cmd, $rs
DIM $ModifyDateTime, $computername, $username, $osname
DIM $OSType, $ServicePack
DIM $InstallDate, $LastBoottime
DIM $OSSerial, $SysManufacturer, $SysModel, $SysSerial
DIM $CPUDescription, $CPUSpeed
DIM $SysMemory, $DiskSize
DIM $FreeSpace, $VideoCard, $VideoRes, $ptr, $NicCard, $nic

DIM $Privilegien, $IP, $MAC, $Uhrzeit, $MonitorDescription, $MonHersteller


If Exist("$DBpath") = 0
? "IT Assets Database Not Found. Aborting..."
Sleep 1
Goto end
EndIf

;*** CONFIGURE DATABASE CONNECTION STRING ***
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)

;*** COLLECT WORKSTAION ASSET INFORMATION

$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
$CPUDescription = $wmiObj.Name	
Next
Sleep 5
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")

;;FUNCTION		Memory() 
;; 
;;AUTHOR		Glenn Barnas
;; 
;;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
;; 
;;SYNTAX		Memory([system]) 
;; 
;;VERSION		4.0 
;; 
;;DATE			v1.0 - 2004/02/04
;; 
;;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
;; 
;;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;;
;;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;;			or video adapters and this memory is not reported. This can be adjusted for using
;;			the second example below.
;; 
;;RETURNS		Integer - Available Physical RAM (in Megabytes) 
;; 
;;DEPENDENCIES		None 
;; 
;;TESTED WITH		WinXP, Vista, Win7, Win8
;;			Windows Server 2000, 2003, 2008, 2012
;;			Tested with up to 16G of RAM 
;; 
;;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;;			
;;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;;			; (e.g. 0.5 instead of 512). 
;;			$MSize = 512			; Size of smallest RAM module (DIMM)
;;			
;;			$Mem = Memory()			; get reported memory
;;			$Ma  = $Mem / $MSize		; determine number of modules installed
;;			
;;			; If a fractional module is detected, add another full module
;;			; this accounts for a fractional module used for BIOS cache or video RAM
;;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;;			
;;			; $Mem now holds a value based more closely on installer rather than available RAM
;;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;;			
;; 
;
Function Memory(Optional $_System, Optional $_fGB)

  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf

  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')

  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf

  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8

  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)

    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next

  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction

;***Continue COLLECT WORKSTAION ASSET INFORMATION
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$DiskSize = WMIQuery("size","Win32_LogicalDisk")
$FreeSpace = WMIQuery("freespace","Win32_LogicalDisk")
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")
For Each $wmiObj in $wmiColl
$MonitorDescription = $wmiObj.Name
$MonHersteller = $wmiObj.MonitorManufacturer
Next
$Applications = WMIQuery("Caption","Win32_Product")
$Services = WMIQuery("Caption","Win32_Service")
endif
next

FUNCTION WMIQuery($what,$where,)
dim $strQuery, $objEnumerator, $value
$strQuery = "Select $what From $where"
$SystemSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//@WKSTA")
$objEnumerator = $SystemSet.ExecQuery($strQuery)
For Each $objInstance in $objEnumerator
If @Error = 0 and $objInstance <> ""
$=execute("$$value = $$objInstance.$what")
$WMIQuery="$value"+"|"+"$WMIQuery"
EndIf
Next
$WMIQuery=left($WMIQuery,len($WMIQuery)-1)
exit @error
ENDFUNCTION

;*** ADD RECORDS TO THE DATABASE ***
If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
$rs.addnew
EndIf
$rs.fields.item("MonHersteller").value = $MonHersteller
$rs.fields.item("MonitorDescription").value = $MonitorDescription
$rs.fields.item("IP").value = $IP
$rs.fields.item("Uhrzeit").value = $Uhrzeit
$rs.fields.item("MAC").value = $MAC
$rs.fields.item("PRIVILEGIEN").value = $Privilegien
$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("DISKSIZE").value = $DiskSize
$rs.fields.item("FREESPACE").value = $FreeSpace
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("APPLICATIONS").value = $Applications
$rs.fields.item("SERVICES").value = $Services
$rs.fields.item("USERNAME").value = $Username

$rs.update

$rs.Close 


Now i found the code posted by allen:
Link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
 Code:
 Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
            ? $Product + ': ' + $Key 
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop
  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


Got this code above running but only writing the result in txt files:

 Code:
 
break on
cls
dim $result
 
$result=setoption('explicit','on')
$result=setoption('novarsinstrings','on')
$result=setoption('nomacrosinstrings','on')
 
dim $verzeichnis, $datei, $dimm, $computer

$verzeichnis = '\\server\...\MSKeys\'
$datei = @Hostname+"_Keys.txt"
 
if not exist($verzeichnis)
? 'Kann Verzeichnis '+$verzeichnis+' nicht finden'
exit 1
endif
 
$result=RedirectOutput ($verzeichnis+$datei ,1)
if @error
? 'Error '+@error+' - '+@serror
endif

;****MS CD Keys auslesen

Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
            ? $Product + ': ' + $Key 
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)
   
  function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
  EndFunction

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop
  Exit VarType($SearchReg) = 8
EndFunction
 
Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
 EndFunction

 ;****MS CD Keys auslesen ENDE


Now i need help to get this results in my mdb database in seperate rows and not in txt files. And thats my problem. I canīt get to this point because iīm fresh in scripting.

can you help me?

Best wishes
Backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-02 12:39 PM
Re: Asset Inventory to Access Database

There are several UDFs written that can read/write/manage various databases. They are all in the UDF section of KORG, or are available as a single UDF Library that you can download from my web site. I found it tiring to always locate the individual UDF files, so simply assembled them into a library.

Once you have the DB UDFs, you can just place your data into an array and use them to write a record in the database. You'll need just a bit of SQL command experience.

Glenn


backfight
(Getting the hang of it)
2013-12-02 01:30 PM
Re: Asset Inventory to Access Database

Hi Glenn,

sorry but thats a litle to much. Donīt know how to manage that. May you can give me an example?


LonkeroAdministrator
(KiX Master Guru)
2013-12-02 04:46 PM
Re: Asset Inventory to Access Database

well, you already have an example as you already have a working script written by someone else.
all you need to do is append that.

now, if you have no slightest clue how DB's work and how to script, maybe you should start by learning something simple first.


backfight
(Getting the hang of it)
2013-12-02 05:23 PM
Re: Asset Inventory to Access Database

thanks for that. i want to learn...
but i donīt know how to intigrate. i understand the code, but get all together is hard for me. sorry if i make you angry. that wasnīt my intention.


LonkeroAdministrator
(KiX Master Guru)
2013-12-03 04:46 AM
Re: Asset Inventory to Access Database

not getting angry. but I am not seeing you trying and I am fundamentally against providing free dinners on a silver platter.

looking at the code presented, my take on it is that first you need to extend the database to even accept the new data. so it is not even a scripting issue.


backfight
(Getting the hang of it)
2013-12-03 09:09 AM
Re: Asset Inventory to Access Database

Ok, i think you mean to extend the database with adding new rows like this:

Windows Key
Office Key
Various MS Keys

Do i get you right? But thats allready done. Dim Variables and add Rows in my code is done, too.

My problem is to get the code from allen integrated, so that the result filed in the rows. My first experement was to insert the result in a txt file. that works. no i wanna go on. Iīll try to get some code together and will post it.


backfight
(Getting the hang of it)
2013-12-03 04:02 PM
Re: Asset Inventory to Access Database

Hi again,
i tested the whole day and try to understand.

my code now looks like this:

 Code:
;*** CREATE AN ACCESS DATABASE WITH A TABLE NAMED COMPUTERS****
;*** CREATE THE FOLLOWING FIELDS: COMPUTERNAME, ... etc

DIM $DBpath

;******************************** CONFIGURE DATABASE PATH********************************************************************************************

$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

BREAK ON CLS


;********************************* DECLARE VARIABLES ************************************************************************************************

DIM $CNstring, $CMDtxt, $cn, $cmd, $rs
DIM $ModifyDateTime, $computername, $username, $osname
DIM $OSType, $ServicePack
DIM $InstallDate, $LastBoottime
DIM $OSSerial, $SysManufacturer, $SysModel, $SysSerial
DIM $CPUDescription, $CPUSpeed
DIM $SysMemory
DIM $VideoCard, $VideoRes, $ptr, $NicCard, $nic, $CDKey

DIM $Privilegien, $IP, $MAC, $Uhrzeit, $MonitorDescription, $MonHersteller, $CDKey

If Exist("$DBpath") = 0
? "IT Assets Database Not Found. Aborting..."
Sleep 1
Goto end
EndIf


;***************************** CONFIGURE DATABASE CONNECTION STRING *********************************************************************************

$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)

;**************************** COLLECT WORKSTAION ASSET INFORMATION **********************************************************************************

$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
$CPUDescription = $wmiObj.Name	
Next
Sleep 5
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")

;********************************* SYSMemory UDF - Glen Barnas ******************************************************************************************

;;FUNCTION		Memory() 
;; 
;;AUTHOR		Glenn Barnas
;; 
;;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
;; 
;;SYNTAX		Memory([system]) 
;; 
;;VERSION		4.0 
;; 
;
Function Memory(Optional $_System, Optional $_fGB)

  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf

  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')

  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf

  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8

  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)

    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next

  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction

;*******************Continue COLLECT WORKSTAION ASSET INFORMATION************************************************************************************

$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")
For Each $wmiObj in $wmiColl
$MonitorDescription = $wmiObj.Name
$MonHersteller = $wmiObj.MonitorManufacturer
next

FUNCTION WMIQuery($what,$where,)
dim $strQuery, $objEnumerator, $value
$strQuery = "Select $what From $where"
$SystemSet = GetObject("winmgmts:{impersonationLevel=impersonate}!//@WKSTA")
$objEnumerator = $SystemSet.ExecQuery($strQuery)
For Each $objInstance in $objEnumerator
If @Error = 0 and $objInstance <> ""
$=execute("$$value = $$objInstance.$what")
$WMIQuery="$value"+"|"+"$WMIQuery"
EndIf
Next
$WMIQuery=left($WMIQuery,len($WMIQuery)-1)
exit @error
ENDFUNCTION
;************************************Get CD Key *****************************************************************************************************

Function GetCDKey($sDigitalProductID)
 Dim $aiKeyChars[24],$bProductKey[15],$ilByte,$i,$sCDKey,$nCur

	$aiKeyChars = Split('B,C,D,F,G,H,J,K,M,P,Q,R,T,V,W,X,Y,2,3,4,6,7,8,9',',')
	For $i = 0 To 14
		$bProductKey[$i] = Val("&"+SubStr($sDigitalProductID,$i*2+105,2))
	Next
	$sCDKey = ""
	For $ilByte = 24 To 0 Step -1
		$nCur = 0
		For $i=14 To 0 Step -1
			$nCur = $nCur * 256 | $bProductKey[$i]
			$bProductKey[$i] = Int($nCur / 24)
			$nCur = $nCur Mod 24
		Next
		$sCDKey = $aiKeyChars[$nCur] + $sCDKey
		If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
	Next
	$GetCDKey = $sCDKey
EndFunction

$CDKey = GetCDKey(1)
;********************************* ADD RECORDS TO THE DATABASE **************************************************************************************

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
$rs.addnew
EndIf
$rs.fields.item("MonHersteller").value = $MonHersteller
$rs.fields.item("MonitorDescription").value = $MonitorDescription
$rs.fields.item("IP").value = $IP
$rs.fields.item("Uhrzeit").value = $Uhrzeit
$rs.fields.item("MAC").value = $MAC
$rs.fields.item("PRIVILEGIEN").value = $Privilegien
$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("USERNAME").value = $Username
$rs.fields.item("CDKey").value = $CDKey
$rs.update

$rs.Close


i used the code you postet here:
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=193030

and got the same error as you postet in here:
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729&fpart=3

BBBBB-BBBBB-BBBBB-BBBBB-BBBBB

But itīs not only win8 it seems to be all versions. Do you know how you get this fixed?
Donīt get it why the result is BBBBB-BBBBB-BBBBB-BBBBB-BBBBB

donīt think i wanna get code on a silver platter, may you can give me a hint


AllenAdministrator
(KiX Supporter)
2013-12-03 04:30 PM
Re: Asset Inventory to Access Database

Maybe my eyes deceive me, but I think that is an old version of the UDF. The most current (without Windows 8 or Office 2013 support) is here:
http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729


LonkeroAdministrator
(KiX Master Guru)
2013-12-03 04:32 PM
Re: Asset Inventory to Access Database

the bbbb-bbbb... is not an error per say.
that's what windows gives you back with some key types. I have seen that happen specially with volume license keys.

but, if you are getting the correct key into the txt-file, there is no way the same code would result in bbbb key if written in database.


backfight
(Getting the hang of it)
2013-12-04 10:33 AM
Re: Asset Inventory to Access Database

Hi again,
thanks for your help.
i think i get a little bit closer:

 Code:
;************************************Get CD Key *****************************************************************************************************
 Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop
  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


but with this changes i only get the last key that is returned. i donīt know how to get all results in one row or seperate rows.

backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-04 11:55 AM
Re: Asset Inventory to Access Database

The code is enumerating an array. You replaced the line that displays the result with one that stores the result in a variable:
 Code:
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key
thus, at the end of the For/Next loop, the $CDKey will contain only the last product/key value pair. You either need to use the array or replace the assignmentn with a database write.

Reading back to the beginning, you started with something that was not optimally structured, and seem to have continued on that path with your changes - not good... I'll be back later with some suggestions - I'll need some time to digest this.

Glenn


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-04 01:45 PM
Re: Asset Inventory to Access Database

OK - having had a few minutes to look at this, I'd start with pencil & paper and sketch out the flow of the key tasks.. (or - Notepad and keyboard). Something like:
 Code:
Declare vars

Define initial values

Describe the key tasks and identify UDFs to accomplish them

Identify Computer (@WKSTA)

Query database
  is this computer listed?
    If so, was the last update more than 6 months ago?
      If NOT, exit - nothing to do

Need to perform an inventory

Clear/Init the NEWDATA array

Query for the following items and load the NEWDATA array with the results. 
 O/S Version
 Hardware Platform
 Installed Software
Use a UDF (such as WMYSysInfo) to query for this info. Extend the function to obtain other required parameters, such as....

For debugging, write the data to a .CSV file for viewing in Excel (CSV.kxf to convert between Array and CSV string)

Use DBLib.udf to write/update the database with the data in the NEWDATA Array

Log Errors/Results to C:\TEMP\INVENT.LOG (fMSG.kxf for timestamped logging)
Now that you have an outline of what you want to do, you can start writing code! Working without such a plan will not lead to success. I start every project with such a document. I always start with a file called BASE.TXT, which has some key info/commands that I put in every script. I copy it to whatever scriptname I'm planning to use, and then add the information above as widely spaced comments. This keeps me focused on a single goal for each section of code.

I also use a Kix development application to create almost every Kix script. You can download the Kix Development Suite from our website and use the KGEN.BAT file to help generate and validate your code. I won't explain further as it's fully documented in the KGen User Guide and installation README file. It's free to download and use and includes our entire Kixtart function library.

KGen does make the following best practices easier to use -

Create a header file (scriptname.TXT) to identify the script, author, & version info. MAINTAIN THE VERSION INFO!! Use this file to set program options (SetOption() calls), declare any global vars, and any vars used by the main program.

Create one or more script files (##_scriptname_purpose.KXF) to define specific blocks of code. For example, I have a GUI script with two tab pages. I have the following files defined:
- scriptname.txt Initialization
- 01_FormMain.kxf Primary form definitions
- 02_FormTab1.kxf First tab form definitions
- 02_FormTab2.kxf Second tab form definitions
- 05_ProgMain.kxf The code that ties the app together
- 06_ProgTab1.kxf First tab function definitions
- 06_ProgTab2.kxf Second tab function definitions
- 10_ProgFunc.kxf app-specific functions common to the entire app

So - I have 8 files in my application development folder. This keeps all of the related code together. KGen will assemble these into a complete script, including any of the external UDFs they might reference. The completed script is several thousand lines of code, but none of the files I work on are more than a few hundred. Much easier to work with, and prevents all kinds of mistakes. If you don't use KGen, write a simple script to locate the .TXT and all .KXF files in your dev folder and combine them into a single .KIX script file. You'll need to deal with the external functions by placing them into your dev folder, but this gets messy as you use them in more and more projects.

Put the functions you download into a KixtartUDFs folder.
- NEVER modify these UDFs - treat them as if they were part of Kix!
- NEVER remove the UDF headers from your scripts - they provide important information when debugging!
- If a public function give you 80-90% of what you need, DO NOT EDIT THE FUNCTION! Create a copy of the file, give it a new file and function name, add the features you need and update the header to reflect the changes you made. Use the modified UDF in your code.

Use single quotes for Kix. Kix will understand both single and double quotes.. Other languages you might call, such as a Shell to the command processor, require double quotes. Using single quotes in Kix allows you to embed the double-quotes easily into the strings used to call Shell commands, SQL statements, etc.

Be consistent! If you look at any of my code, you can find similarities between each of the files. My preferences are:
- ALL CAPS for Macros and Global vars.
- MixedCase for local vars
- Form objects always start with a lower-case 3 character class identifier; and include some type of text to identify which form page/module it is associated with. This helps clarify the CLEAR button on the menu from the buttons on tabs 1 and 2, for example.
- Indent each loop 2 spaces (enough to be visible, not so much that you need a 70" monitor to see the entire line!) ;\)

Use comments - explain what you did and why. This helps not only when others review your code, but when you have to come back in 6 months to implement a requested enhancement. My comment to code ratio in larger projects is typically 1.3:1 - 1.3 lines of comment for every line of code!

Use reasonable spacing and extra line breaks between logical blocks.

In summary, this won't directly fix the script you're using. You're starting with something that's 9+ years old, was not written following these best practices, but yet does what it was designed to do. If you want to use this in production, extract the best pieces of the original code and create a new, production-worthy app from scratch - something that will be reliable, self documented, and easy to maintain/troubleshoot/update.

Glenn

PS - here's my BASE.TXT file:
 Code:
; PROGRAM_NAME - DESCRIPTION
; Version #.# - AUTHOR - DATE
; 

Break On


; Declare variables
; ======================================================================

Dim $Rc						; Return code catcher
Dim $						; temp var

Global $DEBUG					; Debug flag
Global $VERSION					; version string
Global $MSG_LOG_, $ERR_LOG_			; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('WrapAtEOL', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')




; Define values
; ======================================================================
$DEBUG = 0
$VERSION = '0.0'



; MAIN Code
; ======================================================================


backfight
(Getting the hang of it)
2013-12-04 02:44 PM
Re: Asset Inventory to Access Database

Hi Glenn,

thanks for this nice Howto. Iīll try my best to get the best practice way and get a new clean script.

Will be back with my new code, soon

Thanks
Backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-04 03:03 PM
Re: Asset Inventory to Access Database

Cool - the original code is minimally commented and hard to debug.. starting fresh will let us better help you.

backfight
(Getting the hang of it)
2013-12-09 11:24 AM
Re: Asset Inventory to Access Database

Hi Glenn,

iīm so sorry but i donīt get your kix dev running. I read the manual pdf but i donīt get it.

So i started to write a "new" structured script with parts of the old code and get to my limit of knowledge in kix-scripting. i had fixed problem by problem, but at least i get an "Fatal exception occurred.". I wanna use your Memory UDF but this UDF runs into errors.
I wanna use the DBLib.udf but donīt understand witch parts i need and what i have to modify.
I hope the new sturctured script helps you to help me debugging. There is many code out commented, for troubleshooting.

 Code:
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;

 
DIM $DBpath

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

BREAK ON CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================

$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)

Break On

; Declare variables
; ======================================================================

DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj


Global $DEBUG				; Debug flag
Global $VERSION				; version string
Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('WrapAtEOL', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 0
$VERSION = '0.0'

; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


; MAIN Code
; ======================================================================


; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance, $objLocator 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $ = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================
 
 Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key				; Wanna get this results in diferent Rows in the MDB Database
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;;FUNCTION		Memory() 
;; 
;;AUTHOR		Glenn Barnas
;; 
;;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
;; 
;;SYNTAX		Memory([system]) 
;; 
;;VERSION		4.0 
;; 
;;DATE			v1.0 - 2004/02/04
;; 
;;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
;; 
;;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;;
;;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;;			or video adapters and this memory is not reported. This can be adjusted for using
;;			the second example below.
;; 
;;RETURNS		Integer - Available Physical RAM (in Megabytes) 
;; 
;;DEPENDENCIES		None 
;; 
;;TESTED WITH		WinXP, Vista, Win7, Win8
;;			Windows Server 2000, 2003, 2008, 2012
;;			Tested with up to 16G of RAM 
;; 
;;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;;			
;;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;;			; (e.g. 0.5 instead of 512). 
;;			$MSize = 512			; Size of smallest RAM module (DIMM)
;;			
;;			$Mem = Memory()			; get reported memory
;;			$Ma  = $Mem / $MSize		; determine number of modules installed
;;			
;;			; If a fractional module is detected, add another full module
;;			; this accounts for a fractional module used for BIOS cache or video RAM
;;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;;			
;;			; $Mem now holds a value based more closely on installer rather than available RAM
;;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;;			
;; 
;
;Function Memory(Optional $_System, Optional $_fGB)
;
;  Dim $_MemMap				; Physical Memory Map
;  Dim $_Start, $_End, $_Step		; for/next start & step increment
;  Dim $_Sum				; running sum of memory from map
;  Dim $_Idx				; temporary index var
;  Dim $_iMem				; Memory region size index
;  Dim $_Error				; Error placeholder
;
;  ; Insure $_System has "\\System\" format if it is specified 
;  If $_System <> ''
;    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
;  EndIf

;  ; Get the memory value from the registry 
;  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
;  $_MemMap = ReadValue($_Idx, '.Translated')

;  ; Check for invalid read and Return 
;  If Len($_MemMap) = 0 Or @ERROR
;    $Memory = 0				; return 0 Mbytes 
;    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
;    Exit $_Error
;  EndIf

;  ; determine system's O/S type based on architecture
;  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
;  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
;    $_Step  = 40	; Define the step size based on the O/S Architecture
;    $_Start = 33	; Offset where memory descriptor blocks start
;    $_Sum   = 0.0	; no unreported base memory to account for
;    $_iMem  = 10	; Memory size index
;  Else
;    $_Step  = 32	; Define the step size based on the O/S Architecture
;    $_Start = 41	; Offset where memory descriptor blocks start
;    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
;    $_iMem  = 2		; Memory size index
;  EndIf
;  $_End = Len($_MemMap) - 8

;  For $_Idx = $_Start to $_End Step $_Step
;    $_Block = SubStr($_MemMap, $_Idx, $_Step)

;    If SubStr($_Block, $_iMem, 1) > 3
;      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
;    Else
;      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
;    EndIf
;  Next

;  ; Sum is in Bytes - return the total as megabytes
;  $Memory = CInt($_Sum / 1048576)
;  Exit 0

;EndFunction


; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
$CPUDescription = $wmiObj.Name	
Next
Sleep 5
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
;If $SysMemory = 0
;  $SysMemory = Memory()
;EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")
For Each $wmiObj in $wmiColl
$MonitorDescription = $wmiObj.Name
$MonHersteller = $wmiObj.MonitorManufacturer
next

; ADD RECORDS TO THE DATABASE
; ======================================================================

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
$rs.addnew
EndIf
$rs.fields.item("MonHersteller").value = $MonHersteller
$rs.fields.item("MonitorDescription").value = $MonitorDescription
$rs.fields.item("IP").value = $IP
$rs.fields.item("Uhrzeit").value = $Uhrzeit
$rs.fields.item("MAC").value = $MAC
$rs.fields.item("PRIVILEGIEN").value = $Privilegien
$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
;$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
;$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("USERNAME").value = $Username
$rs.fields.item("CDKey").value = $CDKey
$rs.update

$rs.Close


I hope i get near to the best practice with my code. if i donīt, please correct me.

Thanks a lot

Backfight


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-09 01:34 PM
Re: Asset Inventory to Access Database

I changed the order of some of the code to follow the Description, Variable Declaration, Variable Definition, Main Code, Function Definition sequence. You still had some code that is intermingled with the UDFs... the code related to determining the CD Key contains Allen's example code and his UDFs. You need to review how the UDF and his example code works as right now, I think you will only get the last CD Key found added to the database.

The WMIQuery UDF is great when you need to get one or two WMI values, but is very inefficient when you need to gather a dozen or more. The UDF instantiates a new WMI connection with each call, which can take a second or more per call. Take a look at WMISysQuery(), which makes a single WMI instantiation and then fills an array with 40 of the most commonly needed system inventory values. Use that model to create a custom function if needed.

There's no need to comment-out a function (Memory). You can either simply delete it or ignore it - if you don't call it, it doesn't do anything.

I got rid of several duplicate references including "BREAK ON CLS", put the Break On at the top of the script, moved the comment describing the script into the header section.

To work with KGen, I'd suggest you install it on your workstation until you understand how it works. Create C:\DEV & C:\DEV\KixLib. Run the setup and specify C:\DEV\KixLib for the kixtart library path. You MUST run the install from a command prompt, and MUST close and re-open the command prompt for the utility to work as it changes the environment settings. These will only take effect when a new command window is opened.

Under D:\DEV, create a folder for your project (INVENTORY). Create Inventory.txt in that folder and copy the contents of the script below, from the beginning to the empty line after "Functions Follow" into it. Make sure you put any additional functions you downloaded from KORG (such as the CD Key UDF) into the KixLib folder. Then, simply run "KGEN INVENTORY" - it should generate the INVENTORY.KIX script with all needed UDFs, ready to run. Pay attention to the warnings it generates as it will identify undeclared variables, mismatched quotes and other paired objects, and similar code issues.

We offer free support for installation issues of KixDev and free and paid support for all our products through our web site. Feel free to contact us to work out your install/setup issues.
 Code:
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('WrapAtEOL', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 0
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================

$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)


; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next

Sleep 5

$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
;If $SysMemory = 0
;  $SysMemory = Memory()
;EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key
 Dim $RegArray, $RegView, $Value,$Product,$Key, $rc, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key				; Wanna get this results in diferent Rows in the MDB Database
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
 $rs.addnew
EndIf

$rs.fields.item("MonHersteller").value = $MonHersteller
$rs.fields.item("MonitorDescription").value = $MonitorDescription
$rs.fields.item("IP").value = $IP
$rs.fields.item("Uhrzeit").value = $Uhrzeit
$rs.fields.item("MAC").value = $MAC
$rs.fields.item("PRIVILEGIEN").value = $Privilegien
$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
;$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
;$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("USERNAME").value = $Username
$rs.fields.item("CDKey").value = $CDKey
$rs.update

$rs.Close

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance, $objLocator 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $ = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;;FUNCTION		Memory() 
;; 
;;AUTHOR		Glenn Barnas
;; 
;;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
;; 
;;SYNTAX		Memory([system]) 
;; 
;;VERSION		4.0 
;; 
;;DATE			v1.0 - 2004/02/04
;; 
;;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
;; 
;;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;;
;;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;;			or video adapters and this memory is not reported. This can be adjusted for using
;;			the second example below.
;; 
;;RETURNS		Integer - Available Physical RAM (in Megabytes) 
;; 
;;DEPENDENCIES		None 
;; 
;;TESTED WITH		WinXP, Vista, Win7, Win8
;;			Windows Server 2000, 2003, 2008, 2012
;;			Tested with up to 16G of RAM 
;; 
;;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;;			
;;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;;			; (e.g. 0.5 instead of 512). 
;;			$MSize = 512			; Size of smallest RAM module (DIMM)
;;			
;;			$Mem = Memory()			; get reported memory
;;			$Ma  = $Mem / $MSize		; determine number of modules installed
;;			
;;			; If a fractional module is detected, add another full module
;;			; this accounts for a fractional module used for BIOS cache or video RAM
;;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;;			
;;			; $Mem now holds a value based more closely on installer rather than available RAM
;;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;;			
;; 
;
;Function Memory(Optional $_System, Optional $_fGB)
;
;  Dim $_MemMap				; Physical Memory Map
;  Dim $_Start, $_End, $_Step		; for/next start & step increment
;  Dim $_Sum				; running sum of memory from map
;  Dim $_Idx				; temporary index var
;  Dim $_iMem				; Memory region size index
;  Dim $_Error				; Error placeholder
;
;  ; Insure $_System has "\\System\" format if it is specified 
;  If $_System <> ''
;    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
;  EndIf

;  ; Get the memory value from the registry 
;  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
;  $_MemMap = ReadValue($_Idx, '.Translated')

;  ; Check for invalid read and Return 
;  If Len($_MemMap) = 0 Or @ERROR
;    $Memory = 0				; return 0 Mbytes 
;    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
;    Exit $_Error
;  EndIf

;  ; determine system's O/S type based on architecture
;  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
;  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
;    $_Step  = 40	; Define the step size based on the O/S Architecture
;    $_Start = 33	; Offset where memory descriptor blocks start
;    $_Sum   = 0.0	; no unreported base memory to account for
;    $_iMem  = 10	; Memory size index
;  Else
;    $_Step  = 32	; Define the step size based on the O/S Architecture
;    $_Start = 41	; Offset where memory descriptor blocks start
;    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
;    $_iMem  = 2		; Memory size index
;  EndIf
;  $_End = Len($_MemMap) - 8

;  For $_Idx = $_Start to $_End Step $_Step
;    $_Block = SubStr($_MemMap, $_Idx, $_Step)

;    If SubStr($_Block, $_iMem, 1) > 3
;      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
;    Else
;      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
;                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
;    EndIf
;  Next

;  ; Sum is in Bytes - return the total as megabytes
;  $Memory = CInt($_Sum / 1048576)
;  Exit 0

;EndFunction


backfight
(Getting the hang of it)
2013-12-09 04:14 PM
Re: Asset Inventory to Access Database

Hi,

now my code i validated by kgen:

 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 0
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================

$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
$cn = CreateObject ("ADODB.Connection")
$cmd = CreateObject ("ADODB.Command")
$rs = CreateObject ("ADODB.RecordSet")

$cn.connectionstring = $CNstring
$cn.Open
$cmd.activeconnection = $cn
$rs.cursortype = 3
$rs.locktype = 3
$rs.activecommand = $cmd

$cmd.commandtext = $CMDtxt $rs.Open ($cmd)


; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next

Sleep 5

$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key
 Dim $RegArray, $RegView, $Value,$Product,$Key, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key				; Wanna get this results in diferent Rows in the MDB Database
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
 $rs.addnew
EndIf

$rs.fields.item("MonHersteller").value = $MonHersteller
$rs.fields.item("MonitorDescription").value = $MonitorDescription
$rs.fields.item("IP").value = $IP
$rs.fields.item("Uhrzeit").value = $Uhrzeit
$rs.fields.item("MAC").value = $MAC
$rs.fields.item("PRIVILEGIEN").value = $Privilegien
$rs.fields.item("COMPUTERNAME").value = $computername
$rs.fields.item("OSNAME").value = $osname
$rs.fields.item("OSTYPE").value = $OSType
$rs.fields.item("SERVICEPACK").value = $ServicePack
$rs.fields.item("INSTALLDATE").value = $InstallDate
$rs.fields.item("LASTBOOTTIME").value = $LastBoottime
$rs.fields.item("OSSERIAL").value = $OSSerial
$rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
$rs.fields.item("SYSMODEL").value = $SysModel
$rs.fields.item("SYSSERIAL").value = $SysSerial
$rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
$rs.fields.item("CPUSPEED").value = $CPUSpeed
;$rs.fields.item("SYSMEMORY").value = $SysMemory
$rs.fields.item("VIDEOCARD").value = $VideoCard
$rs.fields.item("VIDEORES").value = $VideoRes
;$rs.fields.item("NICCARD").value = $NicCard
$rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
$rs.fields.item("USERNAME").value = $Username
$rs.fields.item("CDKey").value = $CDKey
$rs.update

$rs.Close

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;FUNCTION		Memory() 
; 
;AUTHOR		Glenn Barnas
; 
;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
; 
;SYNTAX		Memory([system]) 
; 
;VERSION		4.0 
; 
;DATE			v1.0 - 2004/02/04
; 
;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
; 
;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;
;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;			or video adapters and this memory is not reported. This can be adjusted for using
;			the second example below.
; 
;RETURNS		Integer - Available Physical RAM (in Megabytes) 
; 
;DEPENDENCIES		None 
; 
;TESTED WITH		WinXP, Vista, Win7, Win8
;			Windows Server 2000, 2003, 2008, 2012
;			Tested with up to 16G of RAM 
; 
;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;			
;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;			; (e.g. 0.5 instead of 512). 
;			$MSize = 512			; Size of smallest RAM module (DIMM)
;			
;			$Mem = Memory()			; get reported memory
;			$Ma  = $Mem / $MSize		; determine number of modules installed
;			
;			; If a fractional module is detected, add another full module
;			; this accounts for a fractional module used for BIOS cache or video RAM
;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;			
;			; $Mem now holds a value based more closely on installer rather than available RAM
;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;			
; 

Function Memory(Optional $_System)

  DIM $_Block				;
  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf
  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')
  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf
  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8
  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)
    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next
  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction



But i get this error:

 Code:
KGen v2.4 - Kixtart script UDF linker
(C) 2000-2013 - Glenn Barnas / Inno-Tech Consulting

Searching for available UDFs............................
 229 UDFs located in 139 files.
No UDFs needed for this generation!
Generation of inventory.KIX is complete!

Pass 1 : 562
Pass 2 .......

Warning: Undeclared variable.
              Variable Name: $
                In function: Main
         Referenced on line: 81
         Implicit declaration as GLOBAL!
Pass 3 : 562
Pass 4 .......
Pass 5 : 561
 1 warnings generated, 562 lines processed.


what does this mean? the other errors in declaration are fixed.


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-09 04:43 PM
Re: Asset Inventory to Access Database

OK - let's look this over...

You see that KGen adds this line to the beginning of your script:
 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
This is just a reference of when the code was generated and which version of Kixtart was used. This becomes important if you tokenize your code.. KGen leaves a .GEN file in your folder that is not tokenized, so you never have to worry about losing your script source code.

The next section is the output from KGen. There are never "errors" from KGen, just "Warnings". Due to Kixtart's free-form layout, it's difficult to detect strings and commands that spread across multiple lines.

The KGen output reports finding 229 UDFs in your library and local folder in 139 separate files. (some files are libraries and contain many functions!) It also says that none are needed for the generation of your script. (you manually included the required functions.)

After KGen assembles your script, it makes 5 passes through your code using the Sanity UDF. This identifies and warns about several common issues:
Pass 1 locates and indexes all of the variables
Pass 2 reports on variables that were not declared, or declared but not used
Pass 3 indexes the paired objects
Pass 4 reports on mismatched paired objects
Pass 5 generates the reports

The warning shows that on line 81, you used a variable ($) that was not Dim'd or otherwise declared, and reminds you that it will be treated as a GLOBAL var. Review line 81
 Code:
$ = SetOption('Explicit', 'On')
and decide to either use a different, previously declared variable or define the variable that was used. The function is "Main" - your main code, but would show a function name if the warning occurred inside a function.

Sometimes, it will not be possible to eliminate all warnings. I usually investigate and confirm that it is not an issue. One of the most common is "Variable inside string", which is not recommended, but often occurs in an Execute statement. The coding workaround to avoid KGen errors usually isn't worth the effort for Execute statements. \:\)

In this case, the issue is minor and will not affect the script, but adding a
 Code:
Dim $         ; temp var
to your variable declaration section will eliminate that warning message completely. It's really up to you to

If you take the Memory and WMIQuery UDFs out of your inventory.txt file, KGen should put them back into the completed script. This makes your source file smaller and appear less complex. KGen should then report using 2 UDFs from the library.

Good work getting this organized!

Glenn


backfight
(Getting the hang of it)
2013-12-10 04:16 PM
Re: Asset Inventory to Access Database

Hi,

thanks for help. Now is my script organized, but not functional :-)

i see that there is no database connect, no writing rows and the script isnīt running into errors. Can you help me how i can detect whats wrong? how can i enable debugging to know whats wrong now.

Backfight


LonkeroAdministrator
(KiX Master Guru)
2013-12-10 05:32 PM
Re: Asset Inventory to Access Database

 Code:
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"

$cn = CreateObject ("ADODB.Connection")
if @error "issue, #" @error get $ exit @error endif
$cmd = CreateObject ("ADODB.Command")
if @error "issue, #" @error get $ exit @error endif
$rs = CreateObject ("ADODB.RecordSet")
if @error "issue, #" @error get $ exit @error endif

$cn.connectionstring = $CNstring
if @error "issue, #" @error get $ exit @error endif
$cn.Open
if @error "issue, #" @error get $ exit @error endif
$cmd.activeconnection = $cn
if @error "issue, #" @error get $ exit @error endif
$rs.cursortype = 3
if @error "issue, #" @error get $ exit @error endif
$rs.locktype = 3
if @error "issue, #" @error get $ exit @error endif
$rs.activecommand = $cmd
if @error "issue, #" @error get $ exit @error endif

$cmd.commandtext = $CMDtxt 
if @error "issue, #" @error get $ exit @error endif
$rs.Open ($cmd)
if @error "issue, #" @error get $ exit @error endif


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-10 05:36 PM
Re: Asset Inventory to Access Database

I assume you masked this line when posting.. have you defined it properly in your prod script?
 Code:
$DBpath = "\\server\...\IT-Inventar.mdb"
These lines
 Code:
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
will no longer work with the NoVarsInStrings and NoMacrosInStrings settings. Seach the core code for any variables or macros inside quotes and change them to the following format:
 Code:
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=" + $DBpath
$CMDtxt = "select * from COMPUTERS where computername = '" + @WKSTA +"'"
You will need to search the remaining code for this kind of issue and resolve it. You should not have to check the UDFs as it is a requirement of all public UDFs to properly support these options.

As for debugging, the simplest is something like:
 Code:
XXXXX - @SERROR @CRLF
where the "XXXXX" is something to identify the location in the code. It can be a line number, a function or process name (such as "OpenDbObject"). It's quick and easy to add, but you need to remove or comment them in your production code. I use the fMsg() UDF for my debugging in production scripts.. Something like this:
 Code:
$Rtn = SomeFunction()  ; need to check results..
$Msg = 'Call to SomeFunction() returned ' + $Rtn + '; ' + @SERROR
fMsg($Msg, '', 0, 4)
This will display the result returned as well as the error message produced by the function call. You must define $MSG_LOG_ with the path to the log file/name. With this format, the same message (in $Msg) will be written to the screen and the log file. the empty arg ('') allows a different message to be written to the log, usually with more detail. The third arg will suppress the CRLF, allowing multiple calls to "stack" messages. The fourth arg controls the output - a "4" outputs the mesaage only if the Global $DEBUG variable is non-zero.

Using this method and function, I can sprinkle the code with debug messages, set $DEBUG=1, and get lots of information about the progress of the script. When it's working as desired, I set $DEBUG=0 and the messages go away.

I'm not sure about any of your DB command syntax - it looks not so correct, but I'm not a wiz with DB commands. I'd comment those out and see if the command generates the data you are looking for first. Once you know the data has been correctly gathered, you can focus on writing to the DB. I'd also take a good look at the Database Library instead of manually coding the DB comands, especially if you don't have a strong comfort with OOP and writing connection strings. I found the DBlib collection easy enough for me to write a fairly sophisticated inventory system with a SQL back-end.. \:\) I just had to deal with arrays, field names, and some UDF calls.

Glenn


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-10 06:00 PM
Re: Asset Inventory to Access Database

Run this - $DEBUG is true, and I modified the code to bypass all DB commands when in debug mode. The section where the DB write was performed has been uupdated to display the collected data on the screen. You'll see that I commented out the commands from line 217-219 as they are not correct.. the WMIQuery returns an array that you are not handling.

Further, I eliminated the 5-second sleep command. I have no idea why it's there.. this code is already agonizingly slow! (See my earlier recommendation against multiple WMIQuery calls!!) It takes nearly 9 seconds to complete on a quad-core i7 system. WMYSysInfo calls are MUCH less than that - often under 1 second. Also, WMISysInfo returns a single array of values - you don't have to do any further processing.

If you continue to use WMIQuery, read the header and review the examples, then update your code accordingly to properly assign the returned value to your variable. If you can't print to the screen, you won't be able to write to the database.

Finally, the first lines that print show that the lines I referred to earlier are indeed incorrect and contain the variable and macro names rather than the contents. You won't be able to open the DB unless you update these.

Glenn
 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

Dim $
DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 1
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "\\server\...\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
'CNstring: ' $CNstring ?
'  CMDtxt: ' $CMDtxt ?

If Not $DEBUG
  $cn = CreateObject ("ADODB.Connection")
  $cmd = CreateObject ("ADODB.Command")
  $rs = CreateObject ("ADODB.RecordSet")

  $cn.connectionstring = $CNstring
  $cn.Open
  $cmd.activeconnection = $cn
  $rs.cursortype = 3
  $rs.locktype = 3
  $rs.activecommand = $cmd

  $cmd.commandtext = $CMDtxt $rs.Open ($cmd)
EndIf

; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")
$SysModel = WMIQuery("Model","Win32_ComputerSystem")
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next

; Sleep 5   ; Why?   WHY???? 

$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key
 Dim $RegArray, $RegView, $Value,$Product,$Key, $Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $CDKey = $Product + ': ' + $Key
;            ? $Product + ': ' + $Key				; Wanna get this results in diferent Rows in the MDB Database
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $DEBUG
 
  'MonHersteller: ' $MonHersteller ?
  'MonitorDescription: ' $MonitorDescription ?
  'IP: ' $IP ?
  'Uhrzeit: ' $Uhrzeit ?
  'MAC: ' $MAC ?
  'PRIVILEGIEN: ' $Privilegien ?
  'COMPUTERNAME: ' $computername ?
  'OSNAME: ' ? ; $osname ?
  'OSTYPE: ' ? ; $OSType ?
  'SERVICEPACK: ' $ServicePack ?
  'INSTALLDATE: ' $InstallDate ?
  'LASTBOOTTIME: ' $LastBoottime ?
  'OSSERIAL: ' $OSSerial ?
  'SYSMANUFACTURER: ' $SysManufacturer ?
  'SYSMODEL: ' $SysModel ?
  'SYSSERIAL: ' $SysSerial ?
  'CPUDESCRIPTION: ' $CPUDescription ?
  'CPUSPEED: ' $CPUSpeed ?
  ;'SYSMEMORY: ' $SysMemory ?
  'VIDEOCARD: ' $VideoCard ?
  'VIDEORES: ' $VideoRes ?
  ;'NICCARD: ' $NicCard ?
  'MODIFYDATETIME: ' $ModifyDateTime ?
  'USERNAME: ' $Username ?
  'CDKey: ' $CDKey ?

Else

  If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
   $rs.addnew
  EndIf

 $rs.fields.item("MonHersteller").value = $MonHersteller
 $rs.fields.item("MonitorDescription").value = $MonitorDescription
 $rs.fields.item("IP").value = $IP
 $rs.fields.item("Uhrzeit").value = $Uhrzeit
 $rs.fields.item("MAC").value = $MAC
 $rs.fields.item("PRIVILEGIEN").value = $Privilegien
 $rs.fields.item("COMPUTERNAME").value = $computername
 $rs.fields.item("OSNAME").value = $osname
 $rs.fields.item("OSTYPE").value = $OSType
 $rs.fields.item("SERVICEPACK").value = $ServicePack
 $rs.fields.item("INSTALLDATE").value = $InstallDate
 $rs.fields.item("LASTBOOTTIME").value = $LastBoottime
 $rs.fields.item("OSSERIAL").value = $OSSerial
 $rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
 $rs.fields.item("SYSMODEL").value = $SysModel
 $rs.fields.item("SYSSERIAL").value = $SysSerial
 $rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
 $rs.fields.item("CPUSPEED").value = $CPUSpeed
 ;$rs.fields.item("SYSMEMORY").value = $SysMemory
 $rs.fields.item("VIDEOCARD").value = $VideoCard
 $rs.fields.item("VIDEORES").value = $VideoRes
 ;$rs.fields.item("NICCARD").value = $NicCard
 $rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
 $rs.fields.item("USERNAME").value = $Username
 $rs.fields.item("CDKey").value = $CDKey
 $rs.update
 $rs.Close

EndIf

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;FUNCTION		Memory() 
; 
;AUTHOR		Glenn Barnas
; 
;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
; 
;SYNTAX		Memory([system]) 
; 
;VERSION		4.0 
; 
;DATE			v1.0 - 2004/02/04
; 
;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
; 
;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;
;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;			or video adapters and this memory is not reported. This can be adjusted for using
;			the second example below.
; 
;RETURNS		Integer - Available Physical RAM (in Megabytes) 
; 
;DEPENDENCIES		None 
; 
;TESTED WITH		WinXP, Vista, Win7, Win8
;			Windows Server 2000, 2003, 2008, 2012
;			Tested with up to 16G of RAM 
; 
;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;			
;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;			; (e.g. 0.5 instead of 512). 
;			$MSize = 512			; Size of smallest RAM module (DIMM)
;			
;			$Mem = Memory()			; get reported memory
;			$Ma  = $Mem / $MSize		; determine number of modules installed
;			
;			; If a fractional module is detected, add another full module
;			; this accounts for a fractional module used for BIOS cache or video RAM
;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;			
;			; $Mem now holds a value based more closely on installer rather than available RAM
;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;			
; 

Function Memory(Optional $_System)

  DIM $_Block				;
  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf
  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')
  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf
  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8
  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)
    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next
  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-10 06:35 PM
Re: Asset Inventory to Access Database

By preventing the errors from WMIQuery(), I get the following results. Since I just prevented the errors by converting the array returned to a normal (non-array) variable, I can't guarantee the data is correct, but it no longer fails. You will still need to review the values returned from the WMIQuery calls.

I uncommented the message output of the product/CD Key processing to illustrate my earlier comment that only the last product is being logged.. You will need to create an array using something like this before the process loop:
 Code:
 Dim $aProducts  ; array of product data in prod,Key format
Dim $P   ; array pointer
$P = -1
Inside the current code, replace the "$CDKey = $Product + ': ' + $Key" line with the following:
 Code:
$P = $P + 1   ; increase array pointer
ReDim Preserve $aData[$P]    ; increase the array size, preserving prior data
$aData[$P] = $Product + ',' + $Key
You will now have an array of Product,Key pairs to work with. Note that the output below lists 4 products/keys found but only the last is in your report.

I also added code to show the processing time, after removing all of the Sleep commands and excluding the screen output to give you an idea of the WMIQuery performance.
 Code:
Asset Audit Script Processing...

  DBPath: \\server\...\IT-Inventar.mdb
CNstring: Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath
  CMDtxt: select * from COMPUTERS where computername = '@WKSTA'

Found Windows 8 Pro: PPC4M-WWWWW-XXXXX-YYYYY-ZZZZZ
Found Microsoft Office Professional Plus 2013: Q29K7-WWWWW-XXXXX-YYYYY-ZZZZZ
Found Microsoft Project Professional 2013: VB7FH-WWWWW-XXXXX-YYYYY-ZZZZZ
Found Microsoft Visio Professional 2013: M7FK3-WWWWW-XXXXX-YYYYY-ZZZZZ

Processing time: 15.325 seconds

MonHersteller: Samsung
MonitorDescription: SyncMaster 245T(Digital)
IP: 172. 16. 12. 16
Uhrzeit: 12:20:50
MAC:
PRIVILEGIEN: USER
COMPUTERNAME: ICWD011
OSNAME: Microsoft Windows 8 Pro
OSTYPE: Multiprocessor Free
SERVICEPACK:
INSTALLDATE: 20130105233330.000000-300
LASTBOOTTIME: 2013/12/10
OSSERIAL: 00178-10077-75869-AA763
SYSMANUFACTURER: Hewlett-Packard
SYSMODEL: HP Compaq 8100 Elite CMT PC
SYSSERIAL: 2UA04305JS
CPUDESCRIPTION: Intel(R) Core(TM) i7 CPU         860  @ 2.80GHz
CPUSPEED: 2933
VIDEOCARD: AMD RADEON HD 6450
VIDEORES: 1920 x 1200 x 4294967296 colors
MODIFYDATETIME: 2013/12/10 12:20:51
USERNAME: gbarnas
CDKey: Microsoft Visio Professional 2013: M7FK3-WWWWW-XXXXX-YYYYY-ZZZZZ

(ICWD011) - K:\ITCG\misc>


backfight
(Getting the hang of it)
2013-12-16 11:54 AM
Re: Asset Inventory to Access Database

Hi Glenn,
thx for your big support! But how do you get these results? can you show me the code witch shows the results above?

i have changed my code with your help from the three post bevore, but i donīt get these results.


Glenn BarnasAdministrator
(KiX Supporter)
2013-12-18 01:00 AM
Re: Asset Inventory to Access Database

Honeymooning this week, so little time to post, but I will tell you that the WMIQuery returns an ARRAY, not a simple VALUE. Instead of

$Var = WMIQuery(blah-blah)

try

$Var = WMIQuery(blah-blah0)[0]

This will return the first element of the array that the function returns. It's simple, but not always accurate, as the query could return multiple values. You'll need to determine where that's appropriate.

Glenn


backfight
(Getting the hang of it)
2014-01-02 02:21 PM
Re: Asset Inventory to Access Database

Happy New Year everybody!

sorry but i get an error.
My Code:

 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

Dim $
DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath
Dim $aProducts 			 	; array of product data in prod,Key format
DIM $Product				;
Dim $P   					; array pointer
DIM $Key					; CDKeys	
DIM $aData					;


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 1
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = ".....\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
'CNstring: ' $CNstring ?
'  CMDtxt: ' $CMDtxt ?

If Not $DEBUG
  $cn = CreateObject ("ADODB.Connection")
  $cmd = CreateObject ("ADODB.Command")
  $rs = CreateObject ("ADODB.RecordSet")

  $cn.connectionstring = $CNstring
  $cn.Open
  $cmd.activeconnection = $cn
  $rs.cursortype = 3
  $rs.locktype = 3
  $rs.activecommand = $cmd

  $cmd.commandtext = $CMDtxt $rs.Open ($cmd)
EndIf

; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")[0]
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")[0]
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")[0]
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")[0]
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")[0]
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
$SysModel = WMIQuery("Model","Win32_ComputerSystem")[0]
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")[0]
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")[0]
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")[0]
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")[0]
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key
$P = -1
ReDim Preserve $aData[$P]    ; increase the array size, preserving prior data
$aData[$P] = $Product + ',' + $Key

 Dim $RegArray, $RegView, $Value,$Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $P = $P + 1  ; increase array pointer
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $DEBUG
 
  'MonHersteller: ' $MonHersteller ?
  'MonitorDescription: ' $MonitorDescription ?
  'IP: ' $IP ?
  'Uhrzeit: ' $Uhrzeit ?
  'MAC: ' $MAC ?
  'PRIVILEGIEN: ' $Privilegien ?
  'COMPUTERNAME: ' $computername ?
  'OSNAME: ' $osname ?
  'OSTYPE: ' $OSType ?
  'SERVICEPACK: ' $ServicePack ?
  'INSTALLDATE: ' $InstallDate ?
  'LASTBOOTTIME: ' $LastBoottime ?
  'OSSERIAL: ' $OSSerial ?
  'SYSMANUFACTURER: ' $SysManufacturer ?
  'SYSMODEL: ' $SysModel ?
  'SYSSERIAL: ' $SysSerial ?
  'CPUDESCRIPTION: ' $CPUDescription ?
  'CPUSPEED: ' $CPUSpeed ?
  ;'SYSMEMORY: ' $SysMemory ?
  'VIDEOCARD: ' $VideoCard ?
  'VIDEORES: ' $VideoRes ?
  ;'NICCARD: ' $NicCard ?
  'MODIFYDATETIME: ' $ModifyDateTime ?
  'USERNAME: ' $Username ?
  'CDKey: ' $CDKey ?

Else

  If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
   $rs.addnew
  EndIf

 $rs.fields.item("MonHersteller").value = $MonHersteller
 $rs.fields.item("MonitorDescription").value = $MonitorDescription
 $rs.fields.item("IP").value = $IP
 $rs.fields.item("Uhrzeit").value = $Uhrzeit
 $rs.fields.item("MAC").value = $MAC
 $rs.fields.item("PRIVILEGIEN").value = $Privilegien
 $rs.fields.item("COMPUTERNAME").value = $computername
 $rs.fields.item("OSNAME").value = $osname
 $rs.fields.item("OSTYPE").value = $OSType
 $rs.fields.item("SERVICEPACK").value = $ServicePack
 $rs.fields.item("INSTALLDATE").value = $InstallDate
 $rs.fields.item("LASTBOOTTIME").value = $LastBoottime
 $rs.fields.item("OSSERIAL").value = $OSSerial
 $rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
 $rs.fields.item("SYSMODEL").value = $SysModel
 $rs.fields.item("SYSSERIAL").value = $SysSerial
 $rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
 $rs.fields.item("CPUSPEED").value = $CPUSpeed
 ;$rs.fields.item("SYSMEMORY").value = $SysMemory
 $rs.fields.item("VIDEOCARD").value = $VideoCard
 $rs.fields.item("VIDEORES").value = $VideoRes
 ;$rs.fields.item("NICCARD").value = $NicCard
 $rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
 $rs.fields.item("USERNAME").value = $Username
 $rs.fields.item("CDKey").value = $CDKey
 $rs.update
 $rs.Close

EndIf

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;FUNCTION		Memory() 
; 
;AUTHOR		Glenn Barnas
; 
;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
; 
;SYNTAX		Memory([system]) 
; 
;VERSION		4.0 
; 
;DATE			v1.0 - 2004/02/04
; 
;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
; 
;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;
;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;			or video adapters and this memory is not reported. This can be adjusted for using
;			the second example below.
; 
;RETURNS		Integer - Available Physical RAM (in Megabytes) 
; 
;DEPENDENCIES		None 
; 
;TESTED WITH		WinXP, Vista, Win7, Win8
;			Windows Server 2000, 2003, 2008, 2012
;			Tested with up to 16G of RAM 
; 
;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;			
;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;			; (e.g. 0.5 instead of 512). 
;			$MSize = 512			; Size of smallest RAM module (DIMM)
;			
;			$Mem = Memory()			; get reported memory
;			$Ma  = $Mem / $MSize		; determine number of modules installed
;			
;			; If a fractional module is detected, add another full module
;			; this accounts for a fractional module used for BIOS cache or video RAM
;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;			
;			; $Mem now holds a value based more closely on installer rather than available RAM
;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;			
; 

Function Memory(Optional $_System)

  DIM $_Block				;
  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf
  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')
  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf
  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8
  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)
    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next
  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction


Error:
 Code:
ERROR : array reference out of bounds!
Script: C:\....\inventory.kix
Line  : 176


hope iīve modified my code as you expected.

backfight


Glenn BarnasAdministrator
(KiX Supporter)
2014-01-02 03:00 PM
Re: Asset Inventory to Access Database

This isn't valid - you're trying to define an array with no elements (different than an array with zero elements).
 Code:
; Get CD Key
$P = -1
ReDim Preserve $aData[$P]    ; increase the array size, preserving prior data
$aData[$P] = $Product + ',' + $Key
The way this type of thing works is like this:
 Code:
Dim $aData  ; declare a plain variable
Dim $P   ; declare the pointer
$P = -1  ; pointer is "empty", since the first position is "0"

; Enumerate some data
For Each $Thing in $Collection
  If InStr($Thing, 'Need')  ; does this thing contain what we're looking for?
    ; Add the object to an array of matches
    $P = $P + 1  ; increment the pointer to the next array position
    ReDim Preserve $aData[$P] ; increase the array, preserving prior contents
    $aData[$P] = $Thing
  EndIf
Next
You'll need to use this model in your code. Note that the increment of $P and ReDim of the array only occur when a match is found. This is where you need to put the array redim and assignment:
 Code:
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $P = $P + 1  ; increase array pointer
        EndIf


Glenn


backfight
(Getting the hang of it)
2014-01-02 03:27 PM
Re: Asset Inventory to Access Database

hi,

sorry but iīm a little depressed. i try and try. but i donīt get the debug results that you get.

i changed my code in this way:

 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

Dim $
DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath
Dim $aProducts 			 	; array of product data in prod,Key format
DIM $Product				;
Dim $P   					; array pointer
DIM $Key					; CDKeys	
DIM $aData					;


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 1
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = ".....\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
'CNstring: ' $CNstring ?
'  CMDtxt: ' $CMDtxt ?

If Not $DEBUG
  $cn = CreateObject ("ADODB.Connection")
  $cmd = CreateObject ("ADODB.Command")
  $rs = CreateObject ("ADODB.RecordSet")

  $cn.connectionstring = $CNstring
  $cn.Open
  $cmd.activeconnection = $cn
  $rs.cursortype = 3
  $rs.locktype = 3
  $rs.activecommand = $cmd

  $cmd.commandtext = $CMDtxt $rs.Open ($cmd)
EndIf

; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")[0]
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")[0]
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")[0]
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")[0]
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")[0]
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
$SysModel = WMIQuery("Model","Win32_ComputerSystem")[0]
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")[0]
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")[0]
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")[0]
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")[0]
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key

$P = -1  ; pointer is "empty", since the first position is "0"

 Dim $RegArray, $RegView, $Value,$Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $P = $P + 1  ; increase array pointer
		  ReDim Preserve $aData[$P] ; increase the array, preserving prior contents
			$aData[$P] = $CDKey
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $DEBUG
 
  'MonHersteller: ' $MonHersteller ?
  'MonitorDescription: ' $MonitorDescription ?
  'IP: ' $IP ?
  'Uhrzeit: ' $Uhrzeit ?
  'MAC: ' $MAC ?
  'PRIVILEGIEN: ' $Privilegien ?
  'COMPUTERNAME: ' $computername ?
  'OSNAME: ' $osname ?
  'OSTYPE: ' $OSType ?
  'SERVICEPACK: ' $ServicePack ?
  'INSTALLDATE: ' $InstallDate ?
  'LASTBOOTTIME: ' $LastBoottime ?
  'OSSERIAL: ' $OSSerial ?
  'SYSMANUFACTURER: ' $SysManufacturer ?
  'SYSMODEL: ' $SysModel ?
  'SYSSERIAL: ' $SysSerial ?
  'CPUDESCRIPTION: ' $CPUDescription ?
  'CPUSPEED: ' $CPUSpeed ?
  ;'SYSMEMORY: ' $SysMemory ?
  'VIDEOCARD: ' $VideoCard ?
  'VIDEORES: ' $VideoRes ?
  ;'NICCARD: ' $NicCard ?
  'MODIFYDATETIME: ' $ModifyDateTime ?
  'USERNAME: ' $Username ?
  'CDKey: ' $CDKey ?

Else

  If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
   $rs.addnew
  EndIf

 $rs.fields.item("MonHersteller").value = $MonHersteller
 $rs.fields.item("MonitorDescription").value = $MonitorDescription
 $rs.fields.item("IP").value = $IP
 $rs.fields.item("Uhrzeit").value = $Uhrzeit
 $rs.fields.item("MAC").value = $MAC
 $rs.fields.item("PRIVILEGIEN").value = $Privilegien
 $rs.fields.item("COMPUTERNAME").value = $computername
 $rs.fields.item("OSNAME").value = $osname
 $rs.fields.item("OSTYPE").value = $OSType
 $rs.fields.item("SERVICEPACK").value = $ServicePack
 $rs.fields.item("INSTALLDATE").value = $InstallDate
 $rs.fields.item("LASTBOOTTIME").value = $LastBoottime
 $rs.fields.item("OSSERIAL").value = $OSSerial
 $rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
 $rs.fields.item("SYSMODEL").value = $SysModel
 $rs.fields.item("SYSSERIAL").value = $SysSerial
 $rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
 $rs.fields.item("CPUSPEED").value = $CPUSpeed
 ;$rs.fields.item("SYSMEMORY").value = $SysMemory
 $rs.fields.item("VIDEOCARD").value = $VideoCard
 $rs.fields.item("VIDEORES").value = $VideoRes
 ;$rs.fields.item("NICCARD").value = $NicCard
 $rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
 $rs.fields.item("USERNAME").value = $Username
 $rs.fields.item("CDKey").value = $CDKey
 $rs.update
 $rs.Close

EndIf

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;FUNCTION		Memory() 
; 
;AUTHOR		Glenn Barnas
; 
;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
; 
;SYNTAX		Memory([system]) 
; 
;VERSION		4.0 
; 
;DATE			v1.0 - 2004/02/04
; 
;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
; 
;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;
;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;			or video adapters and this memory is not reported. This can be adjusted for using
;			the second example below.
; 
;RETURNS		Integer - Available Physical RAM (in Megabytes) 
; 
;DEPENDENCIES		None 
; 
;TESTED WITH		WinXP, Vista, Win7, Win8
;			Windows Server 2000, 2003, 2008, 2012
;			Tested with up to 16G of RAM 
; 
;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;			
;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;			; (e.g. 0.5 instead of 512). 
;			$MSize = 512			; Size of smallest RAM module (DIMM)
;			
;			$Mem = Memory()			; get reported memory
;			$Ma  = $Mem / $MSize		; determine number of modules installed
;			
;			; If a fractional module is detected, add another full module
;			; this accounts for a fractional module used for BIOS cache or video RAM
;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;			
;			; $Mem now holds a value based more closely on installer rather than available RAM
;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;			
; 

Function Memory(Optional $_System)

  DIM $_Block				;
  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf
  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')
  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf
  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8
  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)
    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next
  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction


and my result isnīt an cd key...itīs empty :-(

Results:

 Code:
CNstring: Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath
  CMDtxt: select * from COMPUTERS where computername = '@WKSTA'
MonHersteller: (Standardmonitortypen)
MonitorDescription: PnP-Monitor (Standard)
IP: ...
Uhrzeit: 15:19:38
MAC: ...
PRIVILEGIEN: ....
COMPUTERNAME: ...
OSNAME: Microsoft Windows 8 Pro
OSTYPE: Multiprocessor Free
SERVICEPACK:
INSTALLDATE: 20131118153103.000000+060
LASTBOOTTIME: 2014/01/02
OSSERIAL: 00178-10927-61599-AA949
SYSMANUFACTURER: Acer
SYSMODEL: Veriton M290
SYSSERIAL: ....
CPUDESCRIPTION: Intel(R) Pentium(R) CPU G630 @ 2.70GHz
CPUSPEED: 2700
VIDEOCARD: Intel(R) HD Graphics
VIDEORES: 1920 x 1080 x 4294967296 Farben
MODIFYDATETIME: 2014/01/02 15:19:38
USERNAME: ....
CDKey:


and i donīt get the list of keys like you get. :-/


Glenn BarnasAdministrator
(KiX Supporter)
2014-01-02 04:15 PM
Re: Asset Inventory to Access Database

Re-read the third post from the end of the prior page. The code tag was not correct and I see how the result could have been confusing. I fixed the tag so the two code sections now appear correctly.

Once you have a set of keys, you'll need to enumerate them with something like
 Code:
'CD Keys: ' ?
For Each $Key in $aData
  $Key ?
Next
You need to change the code to properly build an array of CD Keys, and then modify the output to display the keys. Here's a cool shortcut to display the contents of a small array -
 Code:
$Array = 'Reg', 'Green', 'Blue'
Join($Array, ', ') ?
This is great for debugging.

Glenn


backfight
(Getting the hang of it)
2014-01-03 08:55 AM
Re: Asset Inventory to Access Database

Hi,
now it works. Thanks!
can you help me to get "NIC" and your UDF Memory value to work?
after i have the right results in debug i wanna learn how to deal with the database and arrays

my code:
 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

Dim $
DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs					; 
DIM $cn					;

DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername				; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack				; SP
DIM $InstallDate				; Install Date
DIM $LastBoottime				; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer			; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
;DIM $NicCard				; Networkcard
;DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien				; User Privilegien
DIM $IP					; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription			; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath
Dim $aProducts 			 	; array of product data in prod,Key format
DIM $Product				;
Dim $P   					; array pointer
DIM $Key					; CDKeys	
DIM $aData					;


Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
$ = SetOption('Explicit', 'On')
$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 1
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "..........\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
'CNstring: ' $CNstring ?
'  CMDtxt: ' $CMDtxt ?

If Not $DEBUG
  $cn = CreateObject ("ADODB.Connection")
  $cmd = CreateObject ("ADODB.Command")
  $rs = CreateObject ("ADODB.RecordSet")

  $cn.connectionstring = $CNstring
  $cn.Open
  $cmd.activeconnection = $cn
  $rs.cursortype = 3
  $rs.locktype = 3
  $rs.activecommand = $cmd

  $cmd.commandtext = $CMDtxt $rs.Open ($cmd)
EndIf

; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")[0]
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")[0]
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")[0]
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")[0]
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")[0]
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
$SysModel = WMIQuery("Model","Win32_ComputerSystem")[0]
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")[0]
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")[0]
;$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration"))/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")[0]
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")[0]
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key

$P = -1  ; pointer is "empty", since the first position is "0"

 Dim $RegArray, $RegView, $Value,$Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $P = $P + 1  ; increase array pointer
		  ReDim Preserve $aData[$P] ; increase the array, preserving prior contents
			$aData[$P] = $product + ': ' + $Key 
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)



; ADD RECORDS TO THE DATABASE
; ======================================================================

If $DEBUG
 
  'MonHersteller: ' $MonHersteller ?
  'MonitorDescription: ' $MonitorDescription ?
  'IP: ' $IP ?
  'Uhrzeit: ' $Uhrzeit ?
  'MAC: ' $MAC ?
  'PRIVILEGIEN: ' $Privilegien ?
  'COMPUTERNAME: ' $computername ?
  'OSNAME: ' $osname ?
  'OSTYPE: ' $OSType ?
  'SERVICEPACK: ' $ServicePack ?
  'INSTALLDATE: ' $InstallDate ?
  'LASTBOOTTIME: ' $LastBoottime ?
  'OSSERIAL: ' $OSSerial ?
  'SYSMANUFACTURER: ' $SysManufacturer ?
  'SYSMODEL: ' $SysModel ?
  'SYSSERIAL: ' $SysSerial ?
  'CPUDESCRIPTION: ' $CPUDescription ?
  'CPUSPEED: ' $CPUSpeed ?
;  'SYSMEMORY: ' $SysMemory ?
  'VIDEOCARD: ' $VideoCard ?
  'VIDEORES: ' $VideoRes ?
;  'NICCARD: ' $NicCard ?
  'MODIFYDATETIME: ' $ModifyDateTime ?
  'USERNAME: ' $Username ?
;  'CDKey: ' $CDKey ?
	'CD Keys: ' ?
	For Each $Key in $aData
	$Key ?
	Next

Else

  If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
   $rs.addnew
  EndIf

 $rs.fields.item("MonHersteller").value = $MonHersteller
 $rs.fields.item("MonitorDescription").value = $MonitorDescription
 $rs.fields.item("IP").value = $IP
 $rs.fields.item("Uhrzeit").value = $Uhrzeit
 $rs.fields.item("MAC").value = $MAC
 $rs.fields.item("PRIVILEGIEN").value = $Privilegien
 $rs.fields.item("COMPUTERNAME").value = $computername
 $rs.fields.item("OSNAME").value = $osname
 $rs.fields.item("OSTYPE").value = $OSType
 $rs.fields.item("SERVICEPACK").value = $ServicePack
 $rs.fields.item("INSTALLDATE").value = $InstallDate
 $rs.fields.item("LASTBOOTTIME").value = $LastBoottime
 $rs.fields.item("OSSERIAL").value = $OSSerial
 $rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
 $rs.fields.item("SYSMODEL").value = $SysModel
 $rs.fields.item("SYSSERIAL").value = $SysSerial
 $rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
 $rs.fields.item("CPUSPEED").value = $CPUSpeed
 ;$rs.fields.item("SYSMEMORY").value = $SysMemory
 $rs.fields.item("VIDEOCARD").value = $VideoCard
 $rs.fields.item("VIDEORES").value = $VideoRes
 ;$rs.fields.item("NICCARD").value = $NicCard
 $rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
 $rs.fields.item("USERNAME").value = $Username
 $rs.fields.item("CDKey").value = $CDKey
 $rs.update
 $rs.Close

EndIf

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;FUNCTION		Memory() 
; 
;AUTHOR		Glenn Barnas
; 
;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
; 
;SYNTAX		Memory([system]) 
; 
;VERSION		4.0 
; 
;DATE			v1.0 - 2004/02/04
; 
;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
; 
;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;
;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;			or video adapters and this memory is not reported. This can be adjusted for using
;			the second example below.
; 
;RETURNS		Integer - Available Physical RAM (in Megabytes) 
; 
;DEPENDENCIES		None 
; 
;TESTED WITH		WinXP, Vista, Win7, Win8
;			Windows Server 2000, 2003, 2008, 2012
;			Tested with up to 16G of RAM 
; 
;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;			
;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;			; (e.g. 0.5 instead of 512). 
;			$MSize = 512			; Size of smallest RAM module (DIMM)
;			
;			$Mem = Memory()			; get reported memory
;			$Ma  = $Mem / $MSize		; determine number of modules installed
;			
;			; If a fractional module is detected, add another full module
;			; this accounts for a fractional module used for BIOS cache or video RAM
;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;			
;			; $Mem now holds a value based more closely on installer rather than available RAM
;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;			
; 

Function Memory(Optional $_System)

  DIM $_Block				;
  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf
  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')
  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf
  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8
  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)
    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next
  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction


backfight


Glenn BarnasAdministrator
(KiX Supporter)
2014-01-03 05:59 PM
Re: Asset Inventory to Access Database

Well
 Code:
;for each $nic in Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
;if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
;$NicCard = $nic
isn't complete - no Next or EndIf.

Put this in the data collection part:
 Code:
$aNICs = Split(WMIQuery("ProductName","Win32_NetworkAdapter"),"|")
Then, in the display / data write section, you use something like this:
 Code:
for each $nic In $aNICs
  ; ignore virtual and vpn adapters
  if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
    'Found network adapter ' $nic ?
  EndIf
Next
This is untested, but should be pretty darn close.

Glenn



backfight
(Getting the hang of it)
2014-01-07 01:33 PM
Re: Asset Inventory to Access Database

Hi Glenn,
i get closer to my new prod. code :-) thanks for your support.

I Only have a few problems.

my code:
 Code:
;; KixGenerated: 2013/12/09 16:08:52 / Kix32 Version 4.62
; Hardware Inventory , OS Information & MS Key Inventory - Logon Script lists all Hardware & MS CD Keys per Client
; 
; Version 0.1 - Backfight - 09.12.2013
; UDFīs: UDF WMIQuery, UDF MEMORY, (DBLib.udf)
;
; Tasks:
; Identify Computer (@WKSTA)
;
; Query database
;  is this computer listed?
;    If so, was the last update more than 6 months ago?
;      If NOT, exit - nothing to do
;
; Need to perform an inventory
;
; Clear/Init the NEWDATA array
;
; Query for the following items and load the NEWDATA array with the results. 
; O/S Version
; Hardware Platform
; Installed Software  
;


; DESCRIPTION OF THE SCRIPT
;=======================================================================
; Collect all Hardware & OS Informationen from all WKST in the Domain to get a complete Inventory + all installed Microsoft Keys


Break On


; Declare variables
; ======================================================================

Dim $
DIM $CNstring				; Database variables
DIM $CMDtxt					; 
DIM $cmd					; 
DIM $rs						; 
DIM $cn						;
DIM $ModifyDateTime			; Return ModifyDateTime 
DIM $computername			; Workstation Name
DIM $username				; Username
DIM $osname					; OS Name
DIM $ServicePack			; SP
DIM $InstallDate			; Install Date
DIM $LastBoottime			; Last Boottime
DIM $OSSerial				; OS SN
DIM $SysManufacturer		; System Manufacturer
DIM $SysModel				; System Model
DIM $SysSerial				; System SN
DIM $CPUDescription			; CPU Description
DIM $CPUSpeed				; CPU Speed
DIM $SysMemory				; System RAM
DIM $VideoCard				; Video Card Name
DIM $VideoRes				; Video Resulution
DIM $NicCard				; Networkcard
DIM $nic					; NIC Var.
DIM $CDKey					; CDKeys (OS Key, MS Office, etc)
DIM $Privilegien			; User Privilegien
DIM $IP						; IP Adress
DIM $MAC					; Mac Hardware Adress
DIM $Uhrzeit				; Time
DIM $MonitorDescription		; Monitor Description
DIM $MonHersteller			; Monitor Manufactor
DIM $OSType					; Get OSType
DIM $wmiColl
DIM $wmiObj
DIM $DBpath
Dim $aProducts 			 	; array of product data in prod,Key format
DIM $Product				;
Dim $P   					; array pointer
DIM $Key					; CDKeys	
DIM $aData					;
DIM $aNICs					;NICS

Global $DEBUG				; Debug flag
Global $VERSION				; version string
;Global $MSG_LOG_, $ERR_LOG_		; log filenames - used by fMsg()


; Set program options
; ======================================================================
;$ = SetOption('Explicit', 'On')
;$ = SetOption('NoVarsInStrings', 'On')
$ = SetOption('NoMacrosInStrings', 'On')


; Define values
; ======================================================================
$DEBUG = 0
$VERSION = '1.0'

; CONFIGURE DATABASE PATH
; ======================================================================

$DBpath = "....\IT-Inventar.mdb"

CLS
AT (1,1) "Asset Audit Script Processing..."
SLEEP 2
CLS
BREAK ON CLS

; CONFIGURE DATABASE CONNECTION STRING
; ======================================================================
$CNstring="Driver={Microsoft Access Driver (*.mdb)}; DBQ=$DBpath"
$CMDtxt = "select * from COMPUTERS where computername = '@WKSTA'"
;'CNstring: ' $CNstring ?
;'  CMDtxt: ' $CMDtxt ?

If Not $DEBUG
  $cn = CreateObject ("ADODB.Connection")
  $cmd = CreateObject ("ADODB.Command")
  $rs = CreateObject ("ADODB.RecordSet")

  $cn.connectionstring = $CNstring
  $cn.Open
  $cmd.activeconnection = $cn
  $rs.cursortype = 3
  $rs.locktype = 3
  $rs.activecommand = $cmd

  $cmd.commandtext = $CMDtxt $rs.Open ($cmd)
EndIf

; MAIN Code
; ======================================================================



; COLLECT WORKSTAION ASSET INFORMATION
; ======================================================================
$MAC = @ADDRESS
$Uhrzeit = @time
$Privilegien = @PRIV
$IP = @IPADDRESS0
$ModifyDateTime = @DATE + " " + @TIME
$computername = @WKSTA
$username = @userid
$osname = WMIQuery("Caption","Win32_OperatingSystem")[0]
$OSType = WMIQuery("BuildType","Win32_OperatingSystem")[0]
$ServicePack = WMIQuery("CSDVersion","Win32_OperatingSystem")[0]
$InstallDate = WMIQuery("InstallDate","Win32_OperatingSystem")[0]
$LastBoottime = @date
$OSSerial = WMIQuery("SerialNumber","Win32_OperatingSystem")[0]
$SysManufacturer = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
$SysModel = WMIQuery("Model","Win32_ComputerSystem")[0]
$SysSerial = WMIQuery("SerialNumber","Win32_BIOS")[0]
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_Processor ")
For Each $wmiObj in $wmiColl
  $CPUDescription = $wmiObj.Name	
Next
$CPUSpeed = WMIQuery("CurrentClockSpeed","Win32_Processor")[0]
$SysMemory = val(WMIQuery("TotalPhysicalMemory","Win32_LogicalMemoryConfiguration")[0])/1024
If $SysMemory = 0
  $SysMemory = Memory()
EndIf
$VideoCard = WMIQuery("Description","Win32_VideoController")[0]
$VideoRes = WMIQuery("VideoModeDescription","Win32_VideoController")[0]
$aNICs = Split(WMIQuery("ProductName","Win32_NetworkAdapter")[0],"|")
for each $nic In $aNICs
  ; ignore virtual and vpn adapters
  if instr($nic,"miniport")=0 and instr($nic,"RAS")=0 and instr($nic,"Parallel")=0
    $NicCard = $nic
  EndIf
Next
$wmiColl = GetObject("WinMgmts:root/cimv2").ExecQuery("Select * FROM Win32_DesktopMonitor")

For Each $wmiObj in $wmiColl
  $MonitorDescription = $wmiObj.Name
  $MonHersteller = $wmiObj.MonitorManufacturer
Next


; Get CD Key

$P = -1  ; pointer is "empty", since the first position is "0"

 Dim $RegArray, $RegView, $Value,$Array2,$guid
  $RegView=setoption("WOW64AlternateRegView","On")
  $RegArray = SearchReg("HKLM\Software\Microsoft","DigitalProductID",2)
  if @onwow64
    $Array2 = SearchReg("HKLM\Software\WOW6432NODE\Microsoft","DigitalProductID",2)
    $RegArray=ArrayAdd($RegArray,$Array2)
  endif
  If ubound($RegArray)<0
      ? 'No matching items found'
  Else
    For Each $Value In $RegArray
      If $Value
        $Product = ReadValue(Join(Split($value,'<=>DigitalProductId'),''),'ProductName')
        If $product=""
          $guid="{" + split(split($value,"{")[1],"}")[0] + "}"
          if instr($value,"WOW6432Node")
            $product=readvalue("HKLM\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          else
            $product=readvalue("HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall\" + $guid,"DisplayName")
          endif
        endif
        If $Product
          $Key = Get_Product_Key(ReadValue(Join(Split($value,'<=>DigitalProductId'),''), 'DigitalProductID'))
		  $P = $P + 1  ; increase array pointer
		  ReDim Preserve $aData[$P] ; increase the array, preserving prior contents
			$aData[$P] = $product + ': ' + $Key 
        EndIf
      EndIf
    Next
  EndIf
  $RegView=setoption("WOW64AlternateRegView",$RegView)
For each $aData[$P] in split (($aData[$P]),"|")
;	For Each $Key in $aData in split (($Key),"|")
;	Next

; ADD RECORDS TO THE DATABASE
; ======================================================================

If $DEBUG
 
  'MonHersteller: ' $MonHersteller ?
  'MonitorDescription: ' $MonitorDescription ?
  'IP: ' $IP ?
  'Uhrzeit: ' $Uhrzeit ?
  'MAC: ' $MAC ?
  'PRIVILEGIEN: ' $Privilegien ?
  'COMPUTERNAME: ' $computername ?
  'OSNAME: ' $osname ?
  'OSTYPE: ' $OSType ?
  'SERVICEPACK: ' $ServicePack ?
  'INSTALLDATE: ' $InstallDate ?
  'LASTBOOTTIME: ' $LastBoottime ?
  'OSSERIAL: ' $OSSerial ?
  'SYSMANUFACTURER: ' $SysManufacturer ?
  'SYSMODEL: ' $SysModel ?
  'SYSSERIAL: ' $SysSerial ?
  'CPUDESCRIPTION: ' $CPUDescription ?
  'CPUSPEED: ' $CPUSpeed ?
;  'SYSMEMORY: ' $SysMemory ?
  'VIDEOCARD: ' $VideoCard ?
  'VIDEORES: ' $VideoRes ?
;  'NICCARD: ' $NicCard ?
  'MODIFYDATETIME: ' $ModifyDateTime ?
  'USERNAME: ' $Username ?
;  'CDKey: ' $CDKey ?
	'CD Keys: ' ?
	For Each $Key in $aData
	$Key ?
	Next

Else

  If $rs.eof = -1 ; addnew is only needed if a record for this workstation was not found.
   $rs.addnew
  EndIf

 $rs.fields.item("MonHersteller").value = $MonHersteller
 $rs.fields.item("MonitorDescription").value = $MonitorDescription
 $rs.fields.item("IP").value = $IP
 $rs.fields.item("Uhrzeit").value = $Uhrzeit
 $rs.fields.item("MAC").value = $MAC
 $rs.fields.item("PRIVILEGIEN").value = $Privilegien
 $rs.fields.item("COMPUTERNAME").value = $computername
 $rs.fields.item("OSNAME").value = $osname
 $rs.fields.item("OSTYPE").value = $OSType
 $rs.fields.item("SERVICEPACK").value = $ServicePack
 $rs.fields.item("INSTALLDATE").value = $InstallDate
 $rs.fields.item("LASTBOOTTIME").value = $LastBoottime
 $rs.fields.item("OSSERIAL").value = $OSSerial
 $rs.fields.item("SYSMANUFACTURER").value = $SysManufacturer
 $rs.fields.item("SYSMODEL").value = $SysModel
 $rs.fields.item("SYSSERIAL").value = $SysSerial
 $rs.fields.item("CPUDESCRIPTION").value = $CPUDescription
 $rs.fields.item("CPUSPEED").value = $CPUSpeed
 $rs.fields.item("SYSMEMORY").value = $SysMemory
 $rs.fields.item("VIDEOCARD").value = $VideoCard
 $rs.fields.item("VIDEORES").value = $VideoRes
 $rs.fields.item("NICCARD").value = $NicCard
 $rs.fields.item("MODIFYDATETIME").value = $ModifyDateTime
 $rs.fields.item("USERNAME").value = $Username
 ;$rs.fields.item("CDKey").value = $CDKey
 $rs.fields.item("CDKey").value = $aData[$P]
 $rs.update
 $rs.Close

EndIf

Exit 0



; ======================================================================
; functions follow...
; ======================================================================



; UDF WMIQuery
; ======================================================================
;FUNCTION	WMIQuery
;
;ACTION		Queries WMI information from supported systems
;
;AUTHOR		Radimus
;
;CONTRIBUTORS	kdyer, Shawn, And Howard
;
;		gbarnas: altered EXECUTE function for NoVarsInStrings support
;                        Added support for pre-auth object
;			 
;
;VERSION	2.4.2
;
;DATE CREATED	12/22/2001
;
;DATE MODIFIED	04/02/2007 - GAB - added pre-authenticated object pointer support
;
;KIXTART	4.x
;
;SYNTAX		WMIQuery(what,from,[computer],[where],[where_arg],[objAuth])
;
;PARAMETERS	what
;            
;
;		from
;            	 - Win32 Collection
;
;		optional computer
;		 - defaults to local PC
;
;		optional where
;		 - addl parameter for a 'WHERE' clause. Used with $x
;
;		optional where_arg
;		 - addl parameter for a 'WHERE' clause. Used with $Where
;
;		optional objAuth
;		 - pre-authenticated token obtained from WMIAuthenticate
;
;RETURNS	Array 
;		@error 1 = Cannot create COM object on target PC
;
;REMARKS	9/2003 - This release alters the return from the function into an ARRAY, where previous versions
;		used a pipe '|' delimited string.  If you are updating to this version, check your code closely!
;		2/2004 - Added support for authentication
;
;DEPENDENCIES	kix 4.x+, WMI
;
;EXAMPLE	$make  = WMIQuery("Manufacturer","Win32_ComputerSystem")[0]
;		$modem = WMIQuery("Description","Win32_POTSModem",$remotePC,"Status","OK")[0]
;		for each $stick in WMIQuery("Capacity","Win32_PhysicalMemory")
;		  ? val($stick) / 1048576
;		next
;
;KIXTART BBS	http://www.kixtart.org/board/ultimatebb.php?ubb=get_topic;f=12;t=000117
;		http://download.microsoft.com/download/platformsdk/wmicore/1.5/W9XNT4/EN-US/wmicore.EXE 

Function WMIQuery($sWhat, $sFrom, Optional $sComputer, Optional $sWhere, Optional $x, Optional $root, Optional $pAuth)

  Dim $i, $sQuery, $objEnum, $sValue, $Tmp, $SystemSet, $objInstance 

  $sComputer = Trim(Join(Split($sComputer,'\'),''))

  If Not $sComputer Or $sComputer = @WKSTA
    $sComputer = '.'
  EndIf

  If Not $root
    $root = '\root\cimv2'
  Endif

  $sQuery = 'Select ' + $sWhat + ' From '+ $sFrom

  If $sWhere And $x
    $sQuery = $sQuery + " Where " + $sWhere + " = '" + $x + "'"
  EndIf

  If $pAuth
    $SystemSet = $pAuth
  Else
    $SystemSet = GetObject('winmgmts:{impersonationLevel=impersonate}!\\' + $sComputer + $root)
    If @ERROR Or Not $SystemSet
      Exit Val('&' + Right(DecToHex(@ERROR), 4))
    EndIf
  EndIf

  $objEnum = $SystemSet.ExecQuery($sQuery)
  If @ERROR Or Not $objEnum
    Exit Val("&" + Right(DecToHex(@ERROR), 4))
  EndIf

  For Each $objInstance in $objEnum
    $i = Execute(Chr(36) + 'sValue = ' + Chr(36) + 'objInstance.' + $sWhat)
    If VarType($sValue) & 8192
      $Tmp = $Tmp +'|' + Join($sValue,'|')
    Else
      $Tmp = $Tmp +'|' + $sValue 
    EndIf
  Next

  $WMIQuery = split(substr($Tmp,2),'|')
  Exit Val("&" + Right(DecToHex(@ERROR), 4))

EndFunction


; GET MS CD KEYS
; UDF from Allen. To be found under this link: http://www.kixtart.org/forums/ubbthreads.php?ubb=showflat&Number=201729#Post201729
; ======================================================================

function Get_Product_Key($sproductid)
  Dim $aiKeyChars[24], $ilByte, $i, $iLOffset, $iUOffset, $bProductKey[15], $c, $nCur, $sCDKey
  For Each $c In Split("B C D F G H J K M P Q R T V W X Y 2 3 4 6 7 8 9")
    $aiKeyChars[$i]=Asc($c)
    $i=$i+1
  Next
  if len($sProductID)=2544
    $iLOffset=809
    $iUOffset=823
  else
    $iLOffset=53
    $iUOffset=67
  endif
  For $i = $iLOffset*2-1 To $iUOffset*2-1 Step 2
    $bProductKey[($i-($iLOffset*2-1))/2]=Execute("Exit &"+SubStr($sProductId,$i,2))
  Next
  For $ilByte = 24 To 0 Step -1
    $nCur = 0
    For $i=14 To 0 Step -1
      $nCur = $nCur * 256 ^ $bProductKey[$i] ; NOTE THE XOR! 
      $bProductKey[$i] = Int($nCur / 24)
      $nCur = $nCur Mod 24
    Next
    $sCDKey = Chr($aiKeyChars[$nCur]) + $sCDKey
    If $ilByte Mod 5 = 0 And $ilByte <> 0 $sCDKey = "-" + $sCDKey EndIf
  Next
  $Get_Product_Key=$sCDKey
EndFunction
 

Function SearchReg($Key,$Str,$SrcIn)
  Dim $Idx,$vName,$Value,$num,$SubKey,$fArr,$mbr
  $SearchReg = ''
  $num = 0
  $Idx = 0
  $vName = EnumValue($Key,$Idx)
  Do
    $mbr = ''
    If $SrcIn & 1
    $Value = ReadValue($Key,$vName)
     If InStr($Value,$Str)
       $mbr = $Key + "<=>" + IIf($vName,$vName,'<Default>')
     EndIf
    EndIf
    If ($SrcIn & 2) And InStr($vName,$Str)
      $mbr = $Key + "<=>" + $vName
    EndIf
    If $mbr
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $mbr
      $num = $num + 1
    EndIf
    $Idx = $Idx + 1
    $vName = EnumValue($Key,$Idx)
  Until @Error
  $Idx = 0
  $SubKey = EnumKey($Key,$Idx)
  While $SubKey
    If ($SrcIn & 4) And InStr($SubKey,$Str)
      ReDim Preserve $SearchReg[$num]
      $SearchReg[$num] = $Key + '\' + $SubKey + "<=><KeyName>"
      $num = $num + 1
    EndIf
    $fArr = SearchReg($Key + "\" + $SubKey,$Str,$SrcIn)
    If @Error = 0
      For Each $mbr In $fArr
        ReDim Preserve $SearchReg[$num]
        $SearchReg[$num] = $mbr
        $num = $num + 1
      Next
    EndIf
    $Idx = $Idx + 1
    $SubKey = EnumKey($Key,$Idx)
  Loop

  Exit VarType($SearchReg) = 8
EndFunction
 

Function ArrayAdd($Array1, $Array2)
 ;Returns a new $Array1 
 Dim $n,$i
 $n = UBound($Array1) + 1
 REDIM PRESERVE $Array1[$n+UBound($Array2)]
 For $i = 0 to UBound($Array2)
   $Array1[$n+$i] = $Array2[$i]
 Next
 $ArrayAdd = $Array1
EndFunction


; UDF MEMORY
; ======================================================================
;;FUNCTION		Memory() 
;; 
;;AUTHOR		Glenn Barnas
;; 
;;ACTION		Returns the amount of Available Physical RAM in a local or remote system 
;; 
;;SYNTAX		Memory([system]) 
;; 
;;VERSION		4.0 
;; 
;;DATE			v1.0 - 2004/02/04
;; 
;;DATE REVISED		v2.0 - 2005/02/25 - updated to allow larger memory sizes (x86)
;;			v3.0 - 2007/10/05 - rewrite to support x64 systems, tighten code
;;			v4.0 - 2013/11/02 - rewrite to detect large memory blocks on post-Vista platforms
;; 
;;PARAMETERS		System - OPTIONAL - name of system to query. Default is local system
;;
;;REMARKS		Returns Physical RAM size available to the O/S using registry memory allocation map
;;			Returns @ERROR on registry read failure, or 13 / "Data is Invalid" if reg is empty
;;			DOES NOT return physical hardware ram value! Some systems allocate RAM to BIOS cache 
;;			or video adapters and this memory is not reported. This can be adjusted for using
;;			the second example below.
;; 
;;RETURNS		Integer - Available Physical RAM (in Megabytes) 
;; 
;;DEPENDENCIES		None 
;; 
;;TESTED WITH		WinXP, Vista, Win7, Win8
;;			Windows Server 2000, 2003, 2008, 2012
;;			Tested with up to 16G of RAM 
;; 
;;EXAMPLES		$RAM = Memory('ThatPC')		; Get the available RAM from a remote computer
;;			
;;			; Adjust for BIOS/Video ram to estimate total physical RAM by using the smallest
;;			; deployed DIMM module as an increment. Use "1024" for full GB increments.
;;			; If the GB flag is used, this method must be adjusted to define MSize in GB values
;;			; (e.g. 0.5 instead of 512). 
;;			$MSize = 512			; Size of smallest RAM module (DIMM)
;;			
;;			$Mem = Memory()			; get reported memory
;;			$Ma  = $Mem / $MSize		; determine number of modules installed
;;			
;;			; If a fractional module is detected, add another full module
;;			; this accounts for a fractional module used for BIOS cache or video RAM
;;			If $Mem Mod $MSize $Ma = $Ma + 1 EndIf
;;			
;;			; $Mem now holds a value based more closely on installer rather than available RAM
;;			$Mem = $Ma * $MSize		; Memory is #_modules * Mod_Size
;;			
;; 
;
Function Memory(Optional $_System, Optional $_fGB)

  Dim $_MemMap				; Physical Memory Map
  Dim $_Start, $_End, $_Step		; for/next start & step increment
  Dim $_Sum				; running sum of memory from map
  Dim $_Idx				; temporary index var
  Dim $_iMem				; Memory region size index
  Dim $_Error				; Error placeholder

  ; Insure $_System has "\\System\" format if it is specified 
  If $_System <> ''
    $_System = '\\' + Join(Split($_System, '\'), '', 3) + '\'
  EndIf

  ; Get the memory value from the registry 
  $_Idx = $_System + 'HKLM\hardware\resourcemap\system resources\physical memory'
  $_MemMap = ReadValue($_Idx, '.Translated')

  ; Check for invalid read and Return 
  If Len($_MemMap) = 0 Or @ERROR
    $Memory = 0				; return 0 Mbytes 
    $_Error = IIf(@ERROR, @ERROR, 13) 	; Return "Data is Invalid" if no error but data is blank 
    Exit $_Error
  EndIf

  ; determine system's O/S type based on architecture
  $_Idx = $_System + 'HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\Environment'
  If ReadValue($_Idx, 'PROCESSOR_ARCHITECTURE') = 'AMD64'
    $_Step  = 40	; Define the step size based on the O/S Architecture
    $_Start = 33	; Offset where memory descriptor blocks start
    $_Sum   = 0.0	; no unreported base memory to account for
    $_iMem  = 10	; Memory size index
  Else
    $_Step  = 32	; Define the step size based on the O/S Architecture
    $_Start = 41	; Offset where memory descriptor blocks start
    $_Sum   = 737280.0	; account for base memory not identified in memory map - x86 only
    $_iMem  = 2		; Memory size index
  EndIf
  $_End = Len($_MemMap) - 8

  For $_Idx = $_Start to $_End Step $_Step
    $_Block = SubStr($_MemMap, $_Idx, $_Step)

    If SubStr($_Block, $_iMem, 1) > 3
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 4294967296.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 9, 2)))
    Else
      $_Sum = $_Sum + CDbl(Val('&' + SubStr($_Block, $_Step - 1, 2))) * 16777216.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 3, 2))) * 65536.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 5, 2))) * 256.0
                    + CDbl(Val('&' + SubStr($_Block, $_Step - 7, 2)))
    EndIf
  Next

  ; Sum is in Bytes - return the total as megabytes
  $Memory = CInt($_Sum / 1048576)
  Exit 0

EndFunction


1) i donīt understand why my script only works if i uncommented the following:
 Code:
;$ = SetOption('Explicit', 'On')
;$ = SetOption('NoVarsInStrings', 'On')


2) the next problem is that i donīt get the nic. The row in DB is empty.

3) i donīt get the trick to get cd keys in one row in db but split with "|". Here are my testings
 Code:
For each $aData[$P] in split (($aData[$P]),"|")
Next

 Code:
For Each $Key in $aData in split (($Key),"|")
Next


backfight


Glenn BarnasAdministrator
(KiX Supporter)
2014-01-07 04:15 PM
Re: Asset Inventory to Access Database

1. If you are using KGen, it should report every variable that has not been declared. Look at the .RPT file that is created in the same folder where you built your script. It contains all the warnings. Post it if you need clarification of the contents.

2. This was explained above. The data query replaces the "|" delimited string with an array - you don't need to do this again. The code example provided for the display/data write can be used as-is for display and modified to write $Nic to the DB in the DB Write section. If you want a simple DB write logic, forget the For/Next and simply write a comma-delimited string to the DB record with Join($aData, ','). Put that in the command to write to the database as the Value.

3. I don't understand how you got
 Code:
For each $aData[$P] in split (($aData[$P]),"|")
Next
out of the example I posted:
 Code:
'CD Keys: ' ?
For Each $Key in $aData
  $Key ?
Next
Your code isn't valid. If you are doing a "For Each", you need two variables. One is the array of data and the other is the variable used to enumerate the array. You can't use the same var for both. For example:
 Code:
$Array = GetArray() ; function returns an array of values
For Each $Value in $Array  ; walk the array, assigning each element to "$Value" one at a time
  $Value ? ; do something with the value
Next
What you put in the For Each/Next loop will depend on your requirement. You might use this TWICE in your code, once in the debug section that displays the values, and again in the section that writes the data to the DB.

..................

I'll be honest and tell you you're falling into one of the most common development problems that young coders make - you're trying to work on a large project all at once.

When something doesn't work and can't be fixed in a few minutes, create a test script and include just what's needed for the part giving you grief - var declarations & initializations, data collection, and the data processing. So, for your NIC and CDKey issues, create two small scripts, one for each process. The code should init the vars you use, call the function to get the NIC or CDKey data, and then enumerate the results to display the values. This lets you focus on JUST what is needed for this to work with no other distractions. Then you can move the working code from the small scripts into the larger script.

In fact, this is where KGen excels..
Create Project.TXT and use it only to define the variables
Create a DataCollect.UDF file, and define ONE data collection set of function calls, maybe some WMI values.
Create a DataDisplay.UDF file, and in an If $DEBUG / EndIf block, display the value(s)collected above.
Create a DatabaseWrite.UDF file, and in an If Not $DEBUG / EndIf block, write the value(s) to the database.

Run KGen to combine these 4 files and all the required external functions. Verify that the data collection, display, and DB-Write functions work. Having a small number of similar data elements to work with will make debugging easier.

When this is working, and you've worked out any display and DB-Write issues, update the 3 UDF files to add another collect/display/write block. Focus on getting this to work, then repeat as necessary until all of the data is working. Not only does this help focus on developing specific blocks, it keeps the blocks in sequence in the collect, display, and DB-Write sections. This makes further debugging much easier.

I use KGen in this manner for all my larger projects. I actually have broken one project into many separate files:
- project.txt - the var init code
- Coll_01_xxx.UDF to Coll_07_xxx.UDF - separate files for each set of data collections
- Proc_01_xxx.UDF to Proc_07_xxx.UDF - separate files for each set of data processing
- ZZ_CommonFuncs.UDF - a set of project specific functions
KGen assembles these in alphabetical order, so I name them so all data collections come first, then all the data processing, followed by common functions and then public library functions. the "xxx" is a short description of the data being collected or processed.

Also, you would not believe the number of small script segments I have in the "Misc" folder of my dev library that have been created to test/validate the logic of some process. I keep them because I often revisit the logic for future projects, or when I find a potentially better way to do something. It's kind of like the "morgue" that artists use, just for code snippets. ;\)

Glenn


Glenn BarnasAdministrator
(KiX Supporter)
2014-01-11 06:33 PM
Re: Asset Inventory to Access Database

Please see the Script Vault post related to PC Inventory for a working example of PC Inventory processing. That post will collect a large amount of data and display it, and has examples of how to write the data to a SQL database. The SQL part of the script must be completed by the user, as it is up to the user as to which data elements are of interest and the type and structure of the database chosen.

A fully operational inventory system can be constructed in just a few hours by completing the database code portion.

Glenn


AGorman
(Fresh Scripter)
2014-02-07 05:24 AM
Re: Asset Inventory to Access Database

Really impressed with the PC Inventory script. The problem I'm having is with the WMISysInfo function. Works great on my pc with WMISysInfo(). If I try WMISysInfo($sComputer) I get "Error: unexpected command!" on whatever the next line is. I used WMIAuthentication to get credentials and tried WMISysInfo(@Host,$WMIAuth) but still got same error for the next line. If I just run WMISysInfo() it runs great. Any ideas what I'm doing wrong? I have made no changes to WMISysInfo but just in case I removed it from my script and re-copied it but still won't work. Created another script with just the WMI Authentication function and the WMISysInfo function

$Host = 'PANASONIC-PC'
$WMIAuth = WMIAuthentication($Host,'user','password')
$Up = WMISysInfo($Host,$WMIAuth)
? $Up[0]

Still no go.


Glenn BarnasAdministrator
(KiX Supporter)
2014-02-07 01:13 PM
Re: Asset Inventory to Access Database

Hmm.. I haven't used the WMISysInfo remotely since developing our helpdesk app a while ago. Let me look into this today and I'll post the updates. Thanks for the heads-up, and nice to see an attempt at centralized collection!

Glenn