COM - IEnumInstalledApps Topic is solved

Get help with using AutoHotkey (v1.1 and older) and its commands and hotkeys
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

COM - IEnumInstalledApps

27 Oct 2017, 08:07

Hey all...

Found this old script by Sean (https://autohotkey.com/board/topic/3130 ... /?p=199468)
and this topic from autoit (https://www.autoitscript.com/forum/topi ... lications/)

But I cannot find anything in the windows headers about this.
Does someone translated this already into ahk_1.1?
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: COM - IEnumInstalledApps

27 Oct 2017, 08:39

Nice find jNizM, cheers. I did a search for AIM_UPDATEINFOURL in .h files in C:\Program Files (x86)\Windows Kits\8.1 and the one match was this:
C:\Program Files (x86)\Windows Kits\8.1\Include\um\shappmgr.h
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 10:31

Managed to get it working:

Code: Select all

; https://msdn.microsoft.com/en-us/library/windows/desktop/bb773192(v=vs.85).aspx

Loop 18
   MsgBox, % GetAppsInfo({mask: 0x3FFFF, offset: A_PtrSize*(A_Index - 1)})  ; mask: 0x3FFFF — 0b111111111111111111

GetAppsInfo(infoType)  {
   static CLSID_EnumInstalledApps := "{0B124F8F-91F0-11D1-B8B5-006008059382}"
        , IID_IEnumInstalledApps  := "{1BC752E1-9046-11D1-B8B3-006008059382}"
   pEIA := ComObjCreate(CLSID_EnumInstalledApps, IID_IEnumInstalledApps)
   
   while DllCall(NumGet(NumGet(pEIA+0) + A_PtrSize*3), Ptr, pEIA, PtrP, pINA) = 0  {
      VarSetCapacity(APPINFODATA, size := 4*2 + A_PtrSize*18, 0)
      NumPut(size, APPINFODATA)  
      NumPut(infoType.mask, APPINFODATA, 4)

      DllCall(NumGet(NumGet(pINA+0) + A_PtrSize*3), Ptr, pINA, Ptr, &APPINFODATA)
      ObjRelease(pINA)
      pData := NumGet(APPINFODATA, 8 + infoType.offset)
      res .= StrGet(pData, "UTF-16") . "`n"
      DllCall("Ole32\CoTaskMemFree", Ptr, pData)  ; not sure, whether it's needed
   }
   Return res
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 11:03

Nice one teadrinker :thumbup:
Maybe add

Code: Select all

if !pData
	continue
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 11:18

Yeah, thanks, for this variant it's useful for clarity (but not to making a ListView):

Code: Select all

; https://msdn.microsoft.com/en-us/library/windows/desktop/bb773192(v=vs.85).aspx

Loop 18
   MsgBox, % GetAppsInfo({mask: 0x3FFFF, offset: A_PtrSize*(A_Index - 1)})  ; mask: 0x3FFFF — 0b111111111111111111

GetAppsInfo(infoType)  {
   static CLSID_EnumInstalledApps := "{0B124F8F-91F0-11D1-B8B5-006008059382}"
        , IID_IEnumInstalledApps  := "{1BC752E1-9046-11D1-B8B3-006008059382}"
   pEIA := ComObjCreate(CLSID_EnumInstalledApps, IID_IEnumInstalledApps)
   
   while DllCall(NumGet(NumGet(pEIA+0) + A_PtrSize*3), Ptr, pEIA, PtrP, pINA) = 0  {
      VarSetCapacity(APPINFODATA, size := 4*2 + A_PtrSize*18, 0)
      NumPut(size, APPINFODATA)  
      NumPut(infoType.mask, APPINFODATA, 4)

      DllCall(NumGet(NumGet(pINA+0) + A_PtrSize*3), Ptr, pINA, Ptr, &APPINFODATA)
      ObjRelease(pINA)
      if !pData := NumGet(APPINFODATA, 8 + infoType.offset)
         continue
      res .= StrGet(pData, "UTF-16") . "`n"
      DllCall("Ole32\CoTaskMemFree", Ptr, pData)  ; not sure, whether it's needed
   }
   Return res
}
Helgef
Posts: 4709
Joined: 17 Jul 2016, 01:02
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 11:24

Code: Select all

if !pData := NumGet(APPINFODATA, 8 + infoType.offset) {
	res.= "`n"
	continue
}
:D
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 11:31

I did not complitly right specify masks, will fix.
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps

27 Oct 2017, 11:51

Code: Select all

for k, v in [ "DISPLAYNAME", "VERSION", "PUBLISHER", "PRODUCTID"
            , "REGISTEREDOWNER", "REGISTEREDCOMPANY", "LANGUAGE", "SUPPORTURL"
            , "SUPPORTTELEPHONE", "HELPLINK", "INSTALLLOCATION", "INSTALLSOURCE"
            , "INSTALLDATE", "CONTACT", "COMMENTS", "IMAGE", "UPDATEINFOURL" ]
   MsgBox, % GetAppsInfo({ mask: v, offset: A_PtrSize*(k - 1) })

GetAppsInfo(infoType)  {
   static CLSID_EnumInstalledApps := "{0B124F8F-91F0-11D1-B8B5-006008059382}"
        , IID_IEnumInstalledApps  := "{1BC752E1-9046-11D1-B8B3-006008059382}"

        , DISPLAYNAME := 0x00000001
        , VERSION := 0x00000002
        , PUBLISHER := 0x00000004
        , PRODUCTID := 0x00000008
        , REGISTEREDOWNER := 0x00000010
        , REGISTEREDCOMPANY := 0x00000020
        , LANGUAGE := 0x00000040
        , SUPPORTURL := 0x00000080
        , SUPPORTTELEPHONE := 0x00000100
        , HELPLINK := 0x00000200
        , INSTALLLOCATION := 0x00000400
        , INSTALLSOURCE := 0x00000800
        , INSTALLDATE := 0x00001000
        , CONTACT := 0x00004000
        , COMMENTS := 0x00008000
        , IMAGE := 0x00020000
        , READMEURL := 0x00040000
        , UPDATEINFOURL := 0x00080000
        
   pEIA := ComObjCreate(CLSID_EnumInstalledApps, IID_IEnumInstalledApps)
   
   while DllCall(NumGet(NumGet(pEIA+0) + A_PtrSize*3), Ptr, pEIA, PtrP, pINA) = 0  {
      VarSetCapacity(APPINFODATA, size := 4*2 + A_PtrSize*18, 0)
      NumPut(size, APPINFODATA)
      mask := infoType.mask
      NumPut(%mask%, APPINFODATA, 4)

      DllCall(NumGet(NumGet(pINA+0) + A_PtrSize*3), Ptr, pINA, Ptr, &APPINFODATA)
      ObjRelease(pINA)
      if !pData := NumGet(APPINFODATA, 8 + infoType.offset)  {
         res .=  "`n"
         continue
      }
      res .= StrGet(pData, "UTF-16") . "`n"
      DllCall("Ole32\CoTaskMemFree", Ptr, pData)  ; not sure, whether it's needed
   }
   Return mask . ": `n`n" . res
}
Last edited by teadrinker on 27 Oct 2017, 12:57, edited 2 times in total.
User avatar
Reloaded
Posts: 283
Joined: 25 Aug 2017, 08:48

Re: COM - IEnumInstalledApps

27 Oct 2017, 12:06

Guys, its a Genius Script, good Job! :thumbup:
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps  Topic is solved

27 Oct 2017, 12:29

I created ListView:

Code: Select all

#NoEnv
SetBatchLines, -1
headers := [ "DISPLAYNAME", "VERSION", "PUBLISHER", "PRODUCTID"
           , "REGISTEREDOWNER", "REGISTEREDCOMPANY", "LANGUAGE", "SUPPORTURL"
           , "SUPPORTTELEPHONE", "HELPLINK", "INSTALLLOCATION", "INSTALLSOURCE"
           , "INSTALLDATE", "CONTACT", "COMMENTS", "IMAGE", "UPDATEINFOURL" ]
data := []           
for k, v in headers  {
   columns .= (A_Index = 1 ? "" : "|") . v
   data.Push( GetAppsInfo({ mask: v, offset: A_PtrSize*(k - 1) }) )
}
Gui, +Resize -DPIScale
Gui, Margin, 0, 0
Gui, Add, ListView,, % columns
LV_ModifyCol("", "AutoHdr")
listViewArr := []
for k, v in data
   for i, j in v
      listViewArr[i, k] := j
   
for k, v in listViewArr
   LV_Add("", v*)
Gui, Show, w1400 h900
Return

GuiSize:
   GuiControl, Move, SysListView321, w%A_GuiWidth% h%A_GuiHeight%
   Return
   
GuiClose:
   ExitApp
   
GetAppsInfo(infoType)  {
   static CLSID_EnumInstalledApps := "{0B124F8F-91F0-11D1-B8B5-006008059382}"
        , IID_IEnumInstalledApps  := "{1BC752E1-9046-11D1-B8B3-006008059382}"
        
        , AIM_DISPLAYNAME       := 0x00000001
        , AIM_VERSION           := 0x00000002
        , AIM_PUBLISHER         := 0x00000004
        , AIM_PRODUCTID         := 0x00000008
        , AIM_REGISTEREDOWNER   := 0x00000010
        , AIM_REGISTEREDCOMPANY := 0x00000020
        , AIM_LANGUAGE          := 0x00000040
        , AIM_SUPPORTURL        := 0x00000080
        , AIM_SUPPORTTELEPHONE  := 0x00000100
        , AIM_HELPLINK          := 0x00000200
        , AIM_INSTALLLOCATION   := 0x00000400
        , AIM_INSTALLSOURCE     := 0x00000800
        , AIM_INSTALLDATE       := 0x00001000
        , AIM_CONTACT           := 0x00004000
        , AIM_COMMENTS          := 0x00008000
        , AIM_IMAGE             := 0x00020000
        , AIM_READMEURL         := 0x00040000
        , AIM_UPDATEINFOURL     := 0x00080000
        
   pEIA := ComObjCreate(CLSID_EnumInstalledApps, IID_IEnumInstalledApps)
   arr := []
   while DllCall(NumGet(NumGet(pEIA+0) + A_PtrSize*3), Ptr, pEIA, PtrP, pINA) = 0  {
      VarSetCapacity(APPINFODATA, size := 4*2 + A_PtrSize*18, 0)
      NumPut(size, APPINFODATA)
      mask := "AIM_" . infoType.mask
      NumPut(%mask%, APPINFODATA, 4)
      DllCall(NumGet(NumGet(pINA+0) + A_PtrSize*3), Ptr, pINA, Ptr, &APPINFODATA)
      ObjRelease(pINA)
      if !pData := NumGet(APPINFODATA, 8 + infoType.offset)  {
         arr.Push("")
         continue
      }
      arr.Push( StrGet(pData, "UTF-16") )
      DllCall("Ole32\CoTaskMemFree", Ptr, pData)  ; not sure, whether it's needed
   }
   Return arr
}
just me
Posts: 9451
Joined: 02 Oct 2013, 08:51
Location: Germany

Re: COM - IEnumInstalledApps

24 Nov 2017, 09:28

Hi teadrinker, good job! :thumbup:

I changed your function to return all information about all applications using the AIM_... names as keys:

Code: Select all

#NoEnv
SetBatchLines, -1
Header := "DISPLAYNAME|VERSION|PUBLISHER|PRODUCTID|REGISTEREDOWNER|REGISTEREDCOMPANY|LANGUAGE|"
        . "SUPPORTURL|SUPPORTTELEPHONE|HELPLINK|INSTALLLOCATION|INSTALLSOURCE|INSTALLDATE|"
        . "CONTACT|COMMENTS|IMAGE|READMEURL|UPDATEINFOURL"
Header := "DISPLAYNAME|VERSION|INSTALLDATE" ; just for testing
HeaderNames := StrSplit(Header, "|")

AppData := GetInstalledAppsInfo()

Gui, +Resize -DPIScale
Gui, Margin, 0, 0
Gui, Add, ListView, w1000 r30, %Header%
For Index, App In AppData {
   V := []
   For Each, Name In HeaderNames
      V.Push(App[Name])
   LV_Add("", V*)
}
LV_ModifyCol(1, "AutoHdr")
LV_ModifyCol(2, "AutoHdr")
Gui, Show, , % "Found " . LV_GetCount() . " installed applications"
Return

GuiSize:
   GuiControl, Move, SysListView321, w%A_GuiWidth% h%A_GuiHeight%
   Return

GuiClose:
   ExitApp

GetInstalledAppsInfo() {
   ; THX teadrinker ->  https://autohotkey.com/boards/viewtopic.php?p=178726#p178726
   Static CLSID_EnumInstalledApps := "{0B124F8F-91F0-11D1-B8B5-006008059382}"
        , IID_IEnumInstalledApps  := "{1BC752E1-9046-11D1-B8B3-006008059382}"
        , InfoNames := ["DISPLAYNAME", "VERSION", "PUBLISHER", "PRODUCTID", "REGISTEREDOWNER", "REGISTEREDCOMPANY", "LANGUAGE"
                      , "SUPPORTURL", "SUPPORTTELEPHONE", "HELPLINK", "INSTALLLOCATION", "INSTALLSOURCE", "INSTALLDATE"
                      , "CONTACT", "COMMENTS", "IMAGE", "READMEURL", "UPDATEINFOURL"]
        , MaskAll := 0x0EDFFF ; get all (currently) available information
        , SizeOfAID := 8 + (A_PtrSize * 18)
   InfoArray := []
   IEIA := ComObjCreate(CLSID_EnumInstalledApps, IID_IEnumInstalledApps)
   Next := NumGet(NumGet(IEIA + 0, "UPtr") + (A_PtrSize * 3), "UPtr")
   While !DllCall(Next, "Ptr", IEIA, "PtrP", ISA, "UInt") { ; IShellApp (ISA)
      VarSetCapacity(AID, SizeOfAID, 0)
      NumPut(SizeOfAID, AID, 0, "UInt")
      NumPut(MaskAll, AID, 4, "UInt")
      GetAppInfo := NumGet(NumGet(ISA + 0, "UPtr") + (A_PtrSize * 3), "UPtr")
      If !DllCall(GetAppInfo, "Ptr", ISA, "Ptr", &AID) {
         OffSet := 8 - A_PtrSize
         AppInfo := []
         For Each, InfoName In InfoNames
            AppInfo[InfoName] := (StrPtr := NumGet(AID, Offset += A_PtrSize, "UPtr")) ? StrGet(StrPtr, "UTF-16") : ""
         InfoArray.Push(AppInfo)
      }
      ObjRelease(ISA)
   }
   Return InfoArray
}
teadrinker
Posts: 4326
Joined: 29 Mar 2015, 09:41
Contact:

Re: COM - IEnumInstalledApps

24 Nov 2017, 11:52

READMEURL and UPDATEURL I lost for some reason. just me, cheers! :)
User avatar
jeeswg
Posts: 6902
Joined: 19 Dec 2016, 01:58
Location: UK

Re: COM - IEnumInstalledApps

03 Dec 2017, 23:31

It's always good to check the registry, to see where the information is kept. I'm getting similar results, with a lot of overlap, but not exactly the same.

Code: Select all

q:: ;get installed apps info
vCount := 0, vOutput := ""
VarSetCapacity(vOutput, 1000000*2)
vKey1 := "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall"
vKey2 := "HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
(oArray := {}).SetCapacity(10000)
Loop, 2
{
	vKey := vKey%A_Index%
	Loop, Reg, % vKey, K
	{
		RegRead, vDisplayName, % vKey "\" A_LoopRegName, DisplayName
		RegRead, vDisplayVersion, % vKey "\" A_LoopRegName, DisplayVersion
		RegRead, vInstallDate, % vKey "\" A_LoopRegName, InstallDate
		if !(vDisplayName = "")
			;vCount += 1, oArray.Push(A_LoopRegName "`t" vDisplayName "`t" vDisplayVersion "`t" vInstallDate)
			vCount += 1, oArray.Push(vDisplayName "`t" vDisplayVersion "`t" vInstallDate)
	}
}
Loop, % vIndex := oArray.Length()
	vOutput .= oArray[vIndex--] "`r`n"
Clipboard := vCount "`r`n" vOutput
MsgBox, % vCount "`r`n" vOutput
oArray := ""
return
homepage | tutorials | wish list | fun threads | donate
WARNING: copy your posts/messages before hitting Submit as you may lose them due to CAPTCHA
User avatar
jNizM
Posts: 3183
Joined: 30 Sep 2013, 01:33
Contact:

Re: COM - IEnumInstalledApps

04 Jan 2018, 02:24

Thanks so far for all your helps.
I found out, that if i run this script as U32 it shows just the x86 applications and no x64 applications.
[AHK] v2.0.5 | [WIN] 11 Pro (Version 22H2) | [GitHub] Profile

Return to “Ask for Help (v1)”

Who is online

Users browsing this forum: No registered users and 294 guests