Zinthose Posted May 1, 2008 Posted May 1, 2008 Add & Remove ProgramsIf you open this little control panel applet you will find that Microsoft tracks some interesting data. What kind? Well, Locate AutoIt in the list and I'll show you. (I'm assuming you DO have it installed) Once you select a software package from the list, you are presented with the following additional information.SizeUsedLast Used OnI don't know about you but to be able to query this data to see how much a workstation uses an application seems pretty useful to me. But were? How, dose windows track this?Documentation on this subject is sparse at best but I was able to dig up enough crumbs to make a cookie. Well, the data is stored in the registry at 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache'. This directory is a mirror image of the Uninstall directory at 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'. That is except for the data in which we seek. Look in 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache\AutoItv3' and you will find 'SlowInfoCache'. 'SlowInfoCache' is a REG_Binary value of 552 bytes in length. There is no Microsoft documentation on this so don't bother looking.Here is my code I through together to parse this data. If I did something that you feel is inefficient or or otherwise easily done another better way, please let me know. I'm still learning the syntax. =)expandcollapse popup;App Management #include <String.au3> #Include <Memory.au3> #include <Date.au3> Dim $Example $Example = _SlowInfoCache('AutoItv3') #region ### MAIN ### Func _SlowInfoCache($Uninstall_Title = '*') ;Return Local Const $HKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache" Local Const $VName = "SlowInfoCache" Local $j = 0 Local $i = 0 Local $Temp #region tyedef struct SIZE_INT64 $Size_Struct = 'int64' $Size_INT64 = DllStructCreate($Size_Struct) #endregion #region tyedef struct SIZE_CHAR $Size_Struct = 'char Size[8]' $Size_CHAR = DllStructCreate($Size_Struct) #endregion #region typedef struct FILETIME $LastUsed_Struc = "uint dwLowDateTime;" $LastUsed_Struc &= "uint dwHighDateTime" $LastUsed = DllStructCreate($LastUsed_Struc) #endregion ;~ #region typedef struct SYSTEMTIME ;~ $SystemTime_Struc = 'short wYear;' ;~ $SystemTime_Struc &= 'short wMonth;' ;~ $SystemTime_Struc &= 'short wDayOfWeek;' ;~ $SystemTime_Struc &= 'short wDay;' ;~ $SystemTime_Struc &= 'short wHour;' ;~ $SystemTime_Struc &= 'short wMinute;' ;~ $SystemTime_Struc &= 'short wSecond;' ;~ $SystemTime_Struc &= 'short wMilliseconds' ;~ ;~ $SystemTime = DllStructCreate($SystemTime_Struc) ;~ #endregion ;~ #region typedef struct SlowInfoCache [DLL] ;~ $SlowInfoCache_Struc = "uint cLen;" ; size of the SlowInfoCache (552 bytes) ;~ $SlowInfoCache_Struc &= "uint Flag;" ; unknown ;~ $SlowInfoCache_Struc &= "uint64 Size;" ; program size in bytes ;~ $SlowInfoCache_Struc &= "uint64 LastUsed;" ; API-style FILETIME ;~ $SlowInfoCache_Struc &= "uint Frequency;" ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently ;~ $SlowInfoCache_Struc &= "char Path[524]" ; remaining 524 bytes (max path of 260 + null) in unicode ;~ #endregion ;~ #region typedef struct SlowInfoCache Local $SlowInfoCache_cLen ;As DWORD ; size of the SlowInfoCache (552 bytes) Local $SlowInfoCache_HasName ;As LongBool ; unknown Local $SlowInfoCache_Size ;As Int64 ; program size in bytes Local $SlowInfoCache_LastUsed ;As TFileTime ; API-style FILETIME Local $SlowInfoCache_Frequency ;As Integer ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently Local $SlowInfoCache_Path ;As String ; remaining 524 bytes (max path of 260 + null) in unicode #endregion #region If a uninstall title in undefined, we enumerate all the applications If $Uninstall_Title = '*' Then While True $i += 1 $Uninstall_Title = RegEnumKey($HKey, $i) If @error <> 0 then ExitLoop $Temp[$i] = _SlowInfoCache($Uninstall_Title) WEnd Return $Temp EndIf #endregion $RawData = RegRead($HKey & '\' & $Uninstall_Title, $VName) #region Extract DataSets $SlowInfoCache_cLen = StringMid($RawData, 1, 8) $SlowInfoCache_Flag = StringMid($RawData, 9, 8) $SlowInfoCache_Size = StringMid($RawData, 17, 16) $SlowInfoCache_LastUsed = StringMid($RawData, 33, 16) $SlowInfoCache_Frequency = StringMid($RawData, 49, 8) $SlowInfoCache_Path = StringMid($RawData, 57) #endregion #region Correct the Bit-Order $SlowInfoCache_cLen = FixBitOrder($SlowInfoCache_cLen) $SlowInfoCache_Flag = FixBitOrder($SlowInfoCache_Flag) $SlowInfoCache_LastUsed = FixBitOrder($SlowInfoCache_LastUsed, 8) $SlowInfoCache_Frequency = FixBitOrder($SlowInfoCache_Frequency) $SlowInfoCache_Path = FixBitOrder($SlowInfoCache_Path, 4) #endregion #region Convert Size hex string to int64 ;** Things get tricky here.. ;** Basically the $SlowInfoCache_Size value is a int64 value trapped in a hex string value and we need to fix that. ;** The only method that I have reliably got to work is a windows API memory move operation (AKA: Mystical Stuff). ;** Pump the string value into a DLL Struc to prep for conversion For $i = 1 to StringLen($SlowInfoCache_Size) Step 2 $Temp = StringMid($SlowInfoCache_Size, $i, 2) ;** Step 1: Get a Byte with of hex data. $Temp = Dec($Temp) ;** Step 2: Convert the Hex value to a Decimal $Temp = Chr($Temp) ;** Step 3: Convert the Decimal Value into an Ascii character. $j += 1 DllStructSetData($Size_CHAR, 1, $Temp, $j) ;** Step 4: Add Ascii character to the type Structure we will use to convert the data Next ;** Magically transform the charactor array of $SlowInfoCache_Size into an int64 value. (P.S. 'Dec' function fails due to a 32bit limitations) _MemMoveMemory(DllStructGetPtr($Size_CHAR), DllStructGetPtr($Size_INT64), 8) ; POOOOF!!! ;** Sometimes magic backfires If @error Then MsgBox(0, "", 'Magic spell "_MemMoveMemory", backfired!! : ' & @error) Exit 0x0F00 EndIf ;** It worked!! /Cheer Magic $SlowInfoCache_Size = DllStructGetData($Size_INT64, 1) #region CleanUp $Size_INT64 = 0 $Size_CHAR = 0 $Temp = 0 #endregion #endregion #region Create LastUsed FILETIME Structure DllStructSetData($LastUsed, 1, Dec(StringMid($SlowInfoCache_LastUsed, 1, 8))) DllStructSetData($LastUsed, 2, Dec(StringMid($SlowInfoCache_LastUsed, 9, 8))) $SlowInfoCache_LastUsed = _Date_Time_FileTimeToStr($LastUsed) #endregion #region Convert to human readable $SlowInfoCache_cLen = Dec($SlowInfoCache_cLen) $SlowInfoCache_Flag = Dec($SlowInfoCache_Flag) $SlowInfoCache_Frequency = Dec($SlowInfoCache_Frequency) $SlowInfoCache_Path = HexToUnicode($SlowInfoCache_Path) #endregion #region Return Array of data Dim $SlowInfoCache[7] $SlowInfoCache[0] = $Uninstall_Title $SlowInfoCache[1] = $SlowInfoCache_cLen $SlowInfoCache[2] = $SlowInfoCache_Flag $SlowInfoCache[3] = $SlowInfoCache_Size $SlowInfoCache[4] = $SlowInfoCache_LastUsed $SlowInfoCache[5] = $SlowInfoCache_Frequency $SlowInfoCache[6] = $SlowInfoCache_Path Return $SlowInfoCache #endregion EndFunc #endregion #region Support Functions Func Debug($Message, $Title = '!NOT DEFINED : ') If Not @Compiled Then ConsoleWrite('!' & $Title & $Message & @CRLF) EndFunc Func Err($Code, $Description = 'NOT_DEFINED', $Fatal = False) Local $XML_Output ;** Print Error Data to error IO Stream ;** <ERROR Fatal="True"> If $Fatal Then $XML_Output = '<ERROR Fatal="True">' Else $XML_Output = '<ERROR>' EndIf #cs** <ReturnCode>$Code</ReturnCode> <Description>$Descriptiomn</Description> <Fatal>$Fatal</Fatal> </ERROR> #ce $XML_Output &= @CRLF & @TAB & '<ReturnCode>' & $Code & '</ReturnCode>' & @CRLF & @TAB & '<Description>' & $Description & '</Description>' & @CRLF & '</ERROR>' & @CRLF ;** Print XML data to Error IO Stream ConsoleWriteError($XML_Output) ;** If this is a fatal error then we terminate the script If $Fatal Then Exit $Code EndIf ;** Return the Error Code so the calling procedure can take the appropriate action Return $Code EndFunc Func HexToUnicode($Data) Local $Unicode = "" For $i = 1 to StringLen($Data) Step 4 $Value = Dec(StringMid($Data, $i, 4)) If $Value = 0 Then Return $Unicode $Unicode &= ChrW($Value) Next Return $Unicode EndFunc Func FixBitOrder($Data, $Bits = -1) Local $Shifted = "" Local $Temp If $Bits = -1 Then $Bits = StringLen($Data) For $i = 1 to StringLen($Data) Step $Bits $Temp = "" For $j = 0 to $Bits -1 Step 2 $Temp = StringMid($Data,$j + $i, 2) & $Temp Next $Shifted &= $Temp Next Return $Shifted EndFunc #endregionIt's a kinda work in progress. Enjoy!! --- TTFN
Zinthose Posted May 1, 2008 Author Posted May 1, 2008 Added Example... expandcollapse popup;App Management #include <String.au3> #Include <Memory.au3> #include <Date.au3> Dim $Example Dim $Message $Example = _SlowInfoCache('AutoItv3') $Message = 'Uninstall Name:' & @TAB & $Example[0] & @CRLF $Message &= ' Len:' & @TAB & $Example[1] & @CRLF $Message &= ' Has Name:' & @TAB & $Example[2] & @CRLF $Message &= ' Size in Bytes:' & @TAB & $Example[3] & @CRLF $Message &= ' Last Used:' & @TAB & $Example[4] & @CRLF $Message &= ' Frequency:' & @TAB & $Example[5] & @CRLF $Message &= ' Path:' & @TAB & $Example[6] & @CRLF MsgBox(0, "SlowInfoCache - Example", $Message) #region ### MAIN ### Func _SlowInfoCache($Uninstall_Title = '*') ;Return Local Const $HKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache" Local Const $VName = "SlowInfoCache" Local $j = 0 Local $i = 0 Local $Temp #region tyedef struct SIZE_INT64 $Size_Struct = 'int64' $Size_INT64 = DllStructCreate($Size_Struct) #endregion #region tyedef struct SIZE_CHAR $Size_Struct = 'char Size[8]' $Size_CHAR = DllStructCreate($Size_Struct) #endregion #region typedef struct FILETIME $LastUsed_Struc = "uint dwLowDateTime;" $LastUsed_Struc &= "uint dwHighDateTime" $LastUsed = DllStructCreate($LastUsed_Struc) #endregion ;~ #region typedef struct SYSTEMTIME ;~ $SystemTime_Struc = 'short wYear;' ;~ $SystemTime_Struc &= 'short wMonth;' ;~ $SystemTime_Struc &= 'short wDayOfWeek;' ;~ $SystemTime_Struc &= 'short wDay;' ;~ $SystemTime_Struc &= 'short wHour;' ;~ $SystemTime_Struc &= 'short wMinute;' ;~ $SystemTime_Struc &= 'short wSecond;' ;~ $SystemTime_Struc &= 'short wMilliseconds' ;~ ;~ $SystemTime = DllStructCreate($SystemTime_Struc) ;~ #endregion ;~ #region typedef struct SlowInfoCache [DLL] ;~ $SlowInfoCache_Struc = "uint cLen;" ; size of the SlowInfoCache (552 bytes) ;~ $SlowInfoCache_Struc &= "uint Flag;" ; unknown ;~ $SlowInfoCache_Struc &= "uint64 Size;" ; program size in bytes ;~ $SlowInfoCache_Struc &= "uint64 LastUsed;" ; API-style FILETIME ;~ $SlowInfoCache_Struc &= "uint Frequency;" ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently ;~ $SlowInfoCache_Struc &= "char Path[524]" ; remaining 524 bytes (max path of 260 + null) in unicode ;~ #endregion ;~ #region typedef struct SlowInfoCache Local $SlowInfoCache_cLen ;As DWORD ; size of the SlowInfoCache (552 bytes) Local $SlowInfoCache_HasName ;As LongBool ; unknown Local $SlowInfoCache_Size ;As Int64 ; program size in bytes Local $SlowInfoCache_LastUsed ;As TFileTime ; API-style FILETIME Local $SlowInfoCache_Frequency ;As Integer ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently Local $SlowInfoCache_Path ;As String ; remaining 524 bytes (max path of 260 + null) in unicode #endregion #region If a uninstall title in undefined, we enumerate all the applications If $Uninstall_Title = '*' Then While True $i += 1 $Uninstall_Title = RegEnumKey($HKey, $i) If @error <> 0 then ExitLoop $Temp[$i] = _SlowInfoCache($Uninstall_Title) WEnd Return $Temp EndIf #endregion $RawData = RegRead($HKey & '\' & $Uninstall_Title, $VName) #region Extract DataSets $SlowInfoCache_cLen = StringMid($RawData, 1, 8) $SlowInfoCache_Flag = StringMid($RawData, 9, 8) $SlowInfoCache_Size = StringMid($RawData, 17, 16) $SlowInfoCache_LastUsed = StringMid($RawData, 33, 16) $SlowInfoCache_Frequency = StringMid($RawData, 49, 8) $SlowInfoCache_Path = StringMid($RawData, 57) #endregion #region Correct the Bit-Order $SlowInfoCache_cLen = FixBitOrder($SlowInfoCache_cLen) $SlowInfoCache_Flag = FixBitOrder($SlowInfoCache_Flag) $SlowInfoCache_LastUsed = FixBitOrder($SlowInfoCache_LastUsed, 8) $SlowInfoCache_Frequency = FixBitOrder($SlowInfoCache_Frequency) $SlowInfoCache_Path = FixBitOrder($SlowInfoCache_Path, 4) #endregion #region Convert Size hex string to int64 ;** Things get tricky here.. ;** Basically the $SlowInfoCache_Size value is a int64 value trapped in a hex string value and we need to fix that. ;** The only method that I have reliably got to work is a windows API memory move operation (AKA: Mystical Stuff). ;** Pump the string value into a DLL Struc to prep for conversion For $i = 1 to StringLen($SlowInfoCache_Size) Step 2 $Temp = StringMid($SlowInfoCache_Size, $i, 2) ;** Step 1: Get a Byte with of hex data. $Temp = Dec($Temp) ;** Step 2: Convert the Hex value to a Decimal $Temp = Chr($Temp) ;** Step 3: Convert the Decimal Value into an Ascii character. $j += 1 DllStructSetData($Size_CHAR, 1, $Temp, $j) ;** Step 4: Add Ascii character to the type Structure we will use to convert the data Next ;** Magically transform the charactor array of $SlowInfoCache_Size into an int64 value. (P.S. 'Dec' function fails due to a 32bit limitations) _MemMoveMemory(DllStructGetPtr($Size_CHAR), DllStructGetPtr($Size_INT64), 8) ; POOOOF!!! ;** Sometimes magic backfires If @error Then MsgBox(0, "", 'Magic spell "_MemMoveMemory", backfired!! : ' & @error) Exit 0x0F00 EndIf ;** It worked!! /Cheer Magic $SlowInfoCache_Size = DllStructGetData($Size_INT64, 1) #region CleanUp $Size_INT64 = 0 $Size_CHAR = 0 $Temp = 0 #endregion #endregion #region Create LastUsed FILETIME Structure DllStructSetData($LastUsed, 1, Dec(StringMid($SlowInfoCache_LastUsed, 1, 8))) DllStructSetData($LastUsed, 2, Dec(StringMid($SlowInfoCache_LastUsed, 9, 8))) $SlowInfoCache_LastUsed = _Date_Time_FileTimeToStr($LastUsed) #endregion #region Convert to human readable $SlowInfoCache_cLen = Dec($SlowInfoCache_cLen) $SlowInfoCache_Flag = Dec($SlowInfoCache_Flag) $SlowInfoCache_Frequency = Dec($SlowInfoCache_Frequency) $SlowInfoCache_Path = HexToUnicode($SlowInfoCache_Path) #endregion #region Return Array of data Dim $SlowInfoCache[7] $SlowInfoCache[0] = $Uninstall_Title $SlowInfoCache[1] = $SlowInfoCache_cLen $SlowInfoCache[2] = $SlowInfoCache_Flag $SlowInfoCache[3] = $SlowInfoCache_Size $SlowInfoCache[4] = $SlowInfoCache_LastUsed $SlowInfoCache[5] = $SlowInfoCache_Frequency $SlowInfoCache[6] = $SlowInfoCache_Path Return $SlowInfoCache #endregion EndFunc #endregion #region Support Functions Func Debug($Message, $Title = '!NOT DEFINED : ') If Not @Compiled Then ConsoleWrite('!' & $Title & $Message & @CRLF) EndFunc Func Err($Code, $Description = 'NOT_DEFINED', $Fatal = False) Local $XML_Output ;** Print Error Data to error IO Stream ;** <ERROR Fatal="True"> If $Fatal Then $XML_Output = '<ERROR Fatal="True">' Else $XML_Output = '<ERROR>' EndIf #cs** <ReturnCode>$Code</ReturnCode> <Description>$Descriptiomn</Description> <Fatal>$Fatal</Fatal> </ERROR> #ce $XML_Output &= @CRLF & @TAB & '<ReturnCode>' & $Code & '</ReturnCode>' & @CRLF & @TAB & '<Description>' & $Description & '</Description>' & @CRLF & '</ERROR>' & @CRLF ;** Print XML data to Error IO Stream ConsoleWriteError($XML_Output) ;** If this is a fatal error then we terminate the script If $Fatal Then Exit $Code EndIf ;** Return the Error Code so the calling procedure can take the appropriate action Return $Code EndFunc Func HexToUnicode($Data) Local $Unicode = "" For $i = 1 to StringLen($Data) Step 4 $Value = Dec(StringMid($Data, $i, 4)) If $Value = 0 Then Return $Unicode $Unicode &= ChrW($Value) Next Return $Unicode EndFunc Func FixBitOrder($Data, $Bits = -1) Local $Shifted = "" Local $Temp If $Bits = -1 Then $Bits = StringLen($Data) For $i = 1 to StringLen($Data) Step $Bits $Temp = "" For $j = 0 to $Bits -1 Step 2 $Temp = StringMid($Data,$j + $i, 2) & $Temp Next $Shifted &= $Temp Next Return $Shifted EndFunc #endregion --- TTFN
martin Posted May 1, 2008 Posted May 1, 2008 Add & Remove Programs If you open this little control panel applet you will find that Microsoft tracks some interesting data. What kind? Well, Locate AutoIt in the list and I'll show you. (I'm assuming you DO have it installed) Once you select a software package from the list, you are presented with the following additional information. SizeUsedLast Used OnI don't know about you but to be able to query this data to see how much a workstation uses an application seems pretty useful to me. But were? How, dose windows track this? Documentation on this subject is sparse at best but I was able to dig up enough crumbs to make a cookie. Well, the data is stored in the registry at 'HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache'. This directory is a mirror image of the Uninstall directory at 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall'. That is except for the data in which we seek. Look in 'HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache\AutoItv3' and you will find 'SlowInfoCache'. 'SlowInfoCache' is a REG_Binary value of 552 bytes in length. There is no Microsoft documentation on this so don't bother looking. Here is my code I through together to parse this data. If I did something that you feel is inefficient or or otherwise easily done another better way, please let me know. I'm still learning the syntax. =) expandcollapse popup;App Management #include <String.au3> #Include <Memory.au3> #include <Date.au3> Dim $Example $Example = _SlowInfoCache('AutoItv3') #region ### MAIN ### Func _SlowInfoCache($Uninstall_Title = '*') ;Return Local Const $HKey = "HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\App Management\ARPCache" Local Const $VName = "SlowInfoCache" Local $j = 0 Local $i = 0 Local $Temp #region tyedef struct SIZE_INT64 $Size_Struct = 'int64' $Size_INT64 = DllStructCreate($Size_Struct) #endregion #region tyedef struct SIZE_CHAR $Size_Struct = 'char Size[8]' $Size_CHAR = DllStructCreate($Size_Struct) #endregion #region typedef struct FILETIME $LastUsed_Struc = "uint dwLowDateTime;" $LastUsed_Struc &= "uint dwHighDateTime" $LastUsed = DllStructCreate($LastUsed_Struc) #endregion ;~ #region typedef struct SYSTEMTIME ;~ $SystemTime_Struc = 'short wYear;' ;~ $SystemTime_Struc &= 'short wMonth;' ;~ $SystemTime_Struc &= 'short wDayOfWeek;' ;~ $SystemTime_Struc &= 'short wDay;' ;~ $SystemTime_Struc &= 'short wHour;' ;~ $SystemTime_Struc &= 'short wMinute;' ;~ $SystemTime_Struc &= 'short wSecond;' ;~ $SystemTime_Struc &= 'short wMilliseconds' ;~ ;~ $SystemTime = DllStructCreate($SystemTime_Struc) ;~ #endregion ;~ #region typedef struct SlowInfoCache [DLL] ;~ $SlowInfoCache_Struc = "uint cLen;" ; size of the SlowInfoCache (552 bytes) ;~ $SlowInfoCache_Struc &= "uint Flag;" ; unknown ;~ $SlowInfoCache_Struc &= "uint64 Size;" ; program size in bytes ;~ $SlowInfoCache_Struc &= "uint64 LastUsed;" ; API-style FILETIME ;~ $SlowInfoCache_Struc &= "uint Frequency;" ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently ;~ $SlowInfoCache_Struc &= "char Path[524]" ; remaining 524 bytes (max path of 260 + null) in unicode ;~ #endregion ;~ #region typedef struct SlowInfoCache Local $SlowInfoCache_cLen ;As DWORD ; size of the SlowInfoCache (552 bytes) Local $SlowInfoCache_HasName ;As LongBool ; unknown Local $SlowInfoCache_Size ;As Int64 ; program size in bytes Local $SlowInfoCache_LastUsed ;As TFileTime ; API-style FILETIME Local $SlowInfoCache_Frequency ;As Integer ; 0-2 = rarely; 3-9 = occassionaly; 10+ = frequently Local $SlowInfoCache_Path ;As String ; remaining 524 bytes (max path of 260 + null) in unicode #endregion #region If a uninstall title in undefined, we enumerate all the applications If $Uninstall_Title = '*' Then While True $i += 1 $Uninstall_Title = RegEnumKey($HKey, $i) If @error <> 0 then ExitLoop $Temp[$i] = _SlowInfoCache($Uninstall_Title) WEnd Return $Temp EndIf #endregion $RawData = RegRead($HKey & '\' & $Uninstall_Title, $VName) #region Extract DataSets $SlowInfoCache_cLen = StringMid($RawData, 1, 8) $SlowInfoCache_Flag = StringMid($RawData, 9, 8) $SlowInfoCache_Size = StringMid($RawData, 17, 16) $SlowInfoCache_LastUsed = StringMid($RawData, 33, 16) $SlowInfoCache_Frequency = StringMid($RawData, 49, 8) $SlowInfoCache_Path = StringMid($RawData, 57) #endregion #region Correct the Bit-Order $SlowInfoCache_cLen = FixBitOrder($SlowInfoCache_cLen) $SlowInfoCache_Flag = FixBitOrder($SlowInfoCache_Flag) $SlowInfoCache_LastUsed = FixBitOrder($SlowInfoCache_LastUsed, 8) $SlowInfoCache_Frequency = FixBitOrder($SlowInfoCache_Frequency) $SlowInfoCache_Path = FixBitOrder($SlowInfoCache_Path, 4) #endregion #region Convert Size hex string to int64 ;** Things get tricky here.. ;** Basically the $SlowInfoCache_Size value is a int64 value trapped in a hex string value and we need to fix that. ;** The only method that I have reliably got to work is a windows API memory move operation (AKA: Mystical Stuff). ;** Pump the string value into a DLL Struc to prep for conversion For $i = 1 to StringLen($SlowInfoCache_Size) Step 2 $Temp = StringMid($SlowInfoCache_Size, $i, 2) ;** Step 1: Get a Byte with of hex data. $Temp = Dec($Temp) ;** Step 2: Convert the Hex value to a Decimal $Temp = Chr($Temp) ;** Step 3: Convert the Decimal Value into an Ascii character. $j += 1 DllStructSetData($Size_CHAR, 1, $Temp, $j) ;** Step 4: Add Ascii character to the type Structure we will use to convert the data Next ;** Magically transform the charactor array of $SlowInfoCache_Size into an int64 value. (P.S. 'Dec' function fails due to a 32bit limitations) _MemMoveMemory(DllStructGetPtr($Size_CHAR), DllStructGetPtr($Size_INT64), 8) ; POOOOF!!! ;** Sometimes magic backfires If @error Then MsgBox(0, "", 'Magic spell "_MemMoveMemory", backfired!! : ' & @error) Exit 0x0F00 EndIf ;** It worked!! /Cheer Magic $SlowInfoCache_Size = DllStructGetData($Size_INT64, 1) #region CleanUp $Size_INT64 = 0 $Size_CHAR = 0 $Temp = 0 #endregion #endregion #region Create LastUsed FILETIME Structure DllStructSetData($LastUsed, 1, Dec(StringMid($SlowInfoCache_LastUsed, 1, 8))) DllStructSetData($LastUsed, 2, Dec(StringMid($SlowInfoCache_LastUsed, 9, 8))) $SlowInfoCache_LastUsed = _Date_Time_FileTimeToStr($LastUsed) #endregion #region Convert to human readable $SlowInfoCache_cLen = Dec($SlowInfoCache_cLen) $SlowInfoCache_Flag = Dec($SlowInfoCache_Flag) $SlowInfoCache_Frequency = Dec($SlowInfoCache_Frequency) $SlowInfoCache_Path = HexToUnicode($SlowInfoCache_Path) #endregion #region Return Array of data Dim $SlowInfoCache[7] $SlowInfoCache[0] = $Uninstall_Title $SlowInfoCache[1] = $SlowInfoCache_cLen $SlowInfoCache[2] = $SlowInfoCache_Flag $SlowInfoCache[3] = $SlowInfoCache_Size $SlowInfoCache[4] = $SlowInfoCache_LastUsed $SlowInfoCache[5] = $SlowInfoCache_Frequency $SlowInfoCache[6] = $SlowInfoCache_Path Return $SlowInfoCache #endregion EndFunc #endregion #region Support Functions Func Debug($Message, $Title = '!NOT DEFINED : ') If Not @Compiled Then ConsoleWrite('!' & $Title & $Message & @CRLF) EndFunc Func Err($Code, $Description = 'NOT_DEFINED', $Fatal = False) Local $XML_Output ;** Print Error Data to error IO Stream ;** <ERROR Fatal="True"> If $Fatal Then $XML_Output = '<ERROR Fatal="True">' Else $XML_Output = '<ERROR>' EndIf #cs** <ReturnCode>$Code</ReturnCode> <Description>$Descriptiomn</Description> <Fatal>$Fatal</Fatal> </ERROR> #ce $XML_Output &= @CRLF & @TAB & '<ReturnCode>' & $Code & '</ReturnCode>' & @CRLF & @TAB & '<Description>' & $Description & '</Description>' & @CRLF & '</ERROR>' & @CRLF ;** Print XML data to Error IO Stream ConsoleWriteError($XML_Output) ;** If this is a fatal error then we terminate the script If $Fatal Then Exit $Code EndIf ;** Return the Error Code so the calling procedure can take the appropriate action Return $Code EndFunc Func HexToUnicode($Data) Local $Unicode = "" For $i = 1 to StringLen($Data) Step 4 $Value = Dec(StringMid($Data, $i, 4)) If $Value = 0 Then Return $Unicode $Unicode &= ChrW($Value) Next Return $Unicode EndFunc Func FixBitOrder($Data, $Bits = -1) Local $Shifted = "" Local $Temp If $Bits = -1 Then $Bits = StringLen($Data) For $i = 1 to StringLen($Data) Step $Bits $Temp = "" For $j = 0 to $Bits -1 Step 2 $Temp = StringMid($Data,$j + $i, 2) & $Temp Next $Shifted &= $Temp Next Return $Shifted EndFunc #endregion It's a kinda work in progress. Enjoy!! Welcome to the AutoIt Forums. Very nice script. It looks like "LastUsed" is actually "Installed". What do you think? Serial port communications UDF Includes functions for binary transmission and reception.printing UDF Useful for graphs, forms, labels, reports etc.Add User Call Tips to SciTE for functions in UDFs not included with AutoIt and for your own scripts.Functions with parameters in OnEvent mode and for Hot Keys One function replaces GuiSetOnEvent, GuiCtrlSetOnEvent and HotKeySet.UDF IsConnected2 for notification of status of connected state of many urls or IPs, without slowing the script.
Zinthose Posted May 2, 2008 Author Posted May 2, 2008 Welcome to the AutoIt Forums.Very nice script.It looks like "LastUsed" is actually "Installed". What do you think?Actually Last Used is the last time you executed the application. Microsoft dose allot of guessing and it isn't 100% accurate. I verified it dose indeed change when I close and reopen the application when the clock is set for a different day. --- TTFN
JamesDover Posted May 2, 2008 Posted May 2, 2008 Excellent Program very interesting how it works. Do you know how it rates programs like Office for ARPCache frequency of use. Like does it rate it by time used or the amount of times opened.
Zinthose Posted May 3, 2008 Author Posted May 3, 2008 (edited) Excellent Program very interesting how it works. Do you know how it rates programs like Office for ARPCache frequency of use. Like does it rate it by time used or the amount of times opened. There is still some mystery involved but here is what I know. Only Applications listed in the [HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall] registry are monitoredPositive detections are triggered when a shortcut from that application is executed from the start menu / programs / desktop (this is still a mystery)The count is tracked for 30 days. (The location of the 30 day timer is not yet know) If you needed to track a particular program that is not listed in the uninstall path. You can manually create an entry and windows will start tracking it. Edited June 10, 2008 by Zinthose --- TTFN
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now