Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

how to get installed software list

Status
Not open for further replies.

newtofoxpro

Programmer
Sep 16, 2007
301
0
0
IN
In winxp I go start>setting>control Panel>Add or remove programs. And and got Currently installed programs. Is it possible to get this currently installed programs list in VFP8 ?

 
Taken, adapted and shortened from
Code:
loWMIService = GetObject("winmgmts:\\.\root\cimv2")
loSoftwareCollection = loWMIService.ExecQuery("SELECT * FROM Win32_Product")
For Each loSoftware In loSoftwareCollection
  ? loSoftware.Caption
  ? loSoftware.Name
  ? loSoftware.Vendor
  ? loSoftware.Version
  ? loSoftware.InstallLocation
  ? loSoftware.InstallState
Next

It will take as long, as the windows control pnael to load the list. And like Windows it will only list the "officially" installed software, eg not including all the EXE deploayed without any installation as standalone exe or only depending on C runtime or -net frameworks being preinstalled anyway.

In short, WMI only lists what has been registered via Windows Installer Service, but that's what you wanted, as that also is, what the control panel shows via Add/remove programs.

Bye, Olaf.
 
Thank you Olaf, Your code is pretty small & works best. But it does not detect 1) my foxpro application installed by "Inno setup 5" 2) PDF complete.

My plan is.... if "PDF complete" is not installed in user computer my foxpro application should detect and install it.

Best Regards.
 
Similarly, I am using some fonts like barcode etc., which is get installed by Inno setup. If my user reinstall OS for any reason. And he tries to copy all files and run application without running SETUP, barcode may not work properly so my_application should detect and show message "Please run setup"
 
Another thing you could check out is the registry. HKEY_LOCAL_MACHINE\SOFTWARE

You know there is registry.prg in the VFP Installation and samples how to read registry keys.

Besides that you could ADIR recursivley from the root GetEnv("ProgramFiles") directory, but installations could also be outside of that folder.

It Seems innosetup does not by default put an installed software into the list of installed software, even though it is an installer product.

For the demand you really have it would perhaps be best to check out, what executable is associted with the PDF file extension instead of checking for "PDF complete" installations. Or simply put whatever you do via PDF Complete in a TRY CATCH block to test it's working and if not install it.

Typically an installer checks for a product already installed, and installing a software depending on some third party product does simply include a setup of that product or at least redistributable parts of it, so this is something you shoudl try to incorporate into your applications installation rather than checking from within your application.

Bye, Olaf.

 
If my user reinstall OS for any reason"

Then he/she will need to setup your application again, too. Or how do you think your installation will survive an OS reinstallation? Or do you mean an OS repair run? That won't reset fonts. The risc rather would be the user manually fiddling with fonts. But that's out of the scope of your responsibility, I'd say.

What you can always do is errorhandling and reporting missing components. Simply test during development what errors you get, if the components are missing (whatever components are, applications, fonts, etc.)

In regard of fonts AFONT() could help, in regard of printer drivers APRINTER(). ADIR() for checking dependencies of files. TRY CATCH helps an awful lot with CREATEOBJECT() and missing OLE Classes.

Bye, Olaf.
 
Olaf,

You say Inno "does not by default put an installed software into the list of installed software, even though it is an installer product."

It's always done that for me, and as far as I know, I have not taken any special action to force it to do that. There are several flags you can set to tell exactly what to uninstall, but it always seems to add the application to the list.

Mike


__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
Well Mike,

I said "It seems". As I don't use Inno, I don't know. And it being an installer product makes me wonder, why that would be so.

Perhaps also WMI is a bit pickier about what to list as Win32_Product or in the end newtofoxpro didn't thoroughly check the list output by WMI.

Mike, you could perhaps try my WMI script for an installation of one of your products to check out if in general inno setup does not fill in some required information to be enumerated as Win32_Product.

Nevertheless, checking for a certain single product being installed, as in case of PDF Complete, I wouldn't use that script at all. It's much too slow to check all software. It might be possible to extend the query SELECT * FROM Win32_Product Where Name = "PDF Complete", but I'd say the software list always takes some minmum time, I'd not be willing to wait.

If PDF complete offers an OLE Class or an executable you can run with command line switches, then I'd simply try to execute or instanciate whatever and report an error it's missing, if that fails.

Bye, Olaf.
 
Perhaps also WMI is a bit pickier about what to list as Win32_Product or in the end newtofoxpro didn't thoroughly check the list output by WMI. "

I modify code as under. I found some programs missing..

CREATE CURSOR tmpcomp (mCaption c(50), mName c(50), mVendor c(50), mVersion c(50), mInstallLocation c(50), mInstallState n(10))
loWMIService = GetObject("winmgmts:\\.\root\cimv2")
loSoftwareCollection = loWMIService.ExecQuery("SELECT * FROM Win32_Product")
For Each loSoftware In loSoftwareCollection
INSERT INTO tmpcomp (mCaption,mName,mVendor,mVersion,mInstallState) VALUES ;
(loSoftware.Caption,loSoftware.Name,loSoftware.Vendor,loSoftware.Version,loSoftware.InstallState)
NEXT
brow

 
In regard of fonts AFONT() could help, in regard of printer drivers APRINTER(). ADIR() for checking dependencies of files"

It is good alternate method.
 
To compare against the alphabetically sorted list the control panel shows, perhaps set an index on Name. But I also initially said: It will only list the "officially" installed software, eg not including all the EXE deployed without any installation as standalone exe.

Also I don't know if Control Panel is making use of WMI to list software installed. There might also be some other WMI classes besides Win32_Product, eg for Updates and Service Packs Control Panel lists, if you make it show those, too.

I wouldn't dig further into that direction, it's quiter fruitless.

Bye, Olaf.
 
Olaf,

I just did a minimum install of an application using Inno Setup. As expected, it showed up in Control Panel's Add/Remove Programs.

But when I ran your WMI script, it didn't show up at all. I'm not sure why.

I just did this out or curiosity. It's not an issue for me.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
According to Microsoft, Win32_Product class

The Win32_ProductWMI class represents products as they are installed by Windows Installer. A product generally correlates to one installation package.
I do not think Inno uses Windows Installer, but it populates the registry below. I was able to get a list by looping through all these keys and getting the Display Name.

HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall

I found this article, it may help as well:
 
For your fonts question, I do the following to install fonts on the fly;

Code:
                *!* Find the Font folder location...
		objShell = CREATEOBJECT("WScript.Shell")
		lcFontsFolder = objShell.SpecialFolders.Item("Fonts")
		
                *!* Create a Windows Shell object to install Fonts with...
		objShell = CREATEOBJECT("Shell.Application")
		objFolder = objShell.Namespace(lcFontsFolder)

                *!* Get a list of fonts to check for...   
		=ADIR(laFonts, lcHomeFolder + 'Updates\fonts\*.*')
		
                *!* Loop through the list of fonts to check for...
		FOR I = 1 TO ALEN(laFonts, 1)
			STORE ADDBS(lcFontsFolder) + laFonts[I, 1] TO lcFontFile
                        *!* If not found, install it...
			IF !FILE(lcFontFile)
				objFolder.CopyHere(lcHomeFolder + 'Updates\fonts\' + laFonts[I, 1], 1024) &&& + 16 + 4
			ENDIF	&&& !FILE(lcFontFile)
			
		ENDFOR	&&& I = 1 TO ALEN(laFonts, 1)
		
		STORE .NULL. TO objShell, objFolder
 
I do not think Inno uses Windows Installer, but it populates the registry below

That's my understanding as well.

Referring back to my minimum Inno install (see my previous message), the application does appear as expected in HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall.

Mike

__________________________________
Mike Lewis (Edinburgh, Scotland)

Visual FoxPro articles, tips, training, consultancy
 
My understanding of Windows Installer is, it's a service not only used by MSI packages, but every software has to register with it. Obviously third party products find a way around it, still appearing in the control panel.

It's kind of bitter, that there is no standard everything must apply to, but on the other side it's often practical things work outside of some specifications.

Bye, Olaf.
 
Thanks to news2news. Learn and Build/Altered to fit my needs. This code works.

CREATE CURSOR TmpCur (mVar c(250))
#DEFINE ERROR_SUCCESS 0
#DEFINE KEY_ALL_ACCESS 0xF003F
#DEFINE HKEY_LOCAL_MACHINE 0x80000002
DECLARE INTEGER RegEnumKey IN advapi32 INTEGER hKey, INTEGER dwIndex, STRING @lpName, INTEGER cchName
DECLARE INTEGER RegCloseKey IN advapi32 INTEGER hKey
LOCAL oReg
oReg = CreateObject("Tregister", HKEY_LOCAL_MACHINE, "Software\Microsoft\Windows\CurrentVersion\Uninstall")
BROWSE
* END

DEFINE CLASS Tregister As Custom
oXml=.F.
PROCEDURE Init(hParentKey, cSubkey)
LOCAL hKey, oXml, oKey
hKey = 0
IF RegOpenKeyEx(hParentKey, cSubkey, 0, KEY_ALL_ACCESS, @hKey) <> ERROR_SUCCESS
RETURN .F.
ENDIF
THIS.oXml = CreateObject("Microsoft.XMLDOM")
THIS.oXml.LoadXML(CHR(60) + "Registry" + CHR(47) + CHR(62))
oKey = CreateObject("Tkey", THIS.oXml, THIS.oXml.documentElement(), hKey)
ENDDEFINE

DEFINE CLASS Tkey As Custom
oXml=.F.
parentnode=.F.
hKey=0
PROCEDURE Init(oXml, oParentNode, hKey)
THIS.oXml = oXml
THIS.parentnode = oParentNode
THIS.hKey = hKey
THIS.EnumSubKeys
= RegCloseKey(THIS.hKey)
PROCEDURE EnumSubKeys
LOCAL nIndex, cBuffer, nResult, hKey, objSubnode, oKey
nIndex = 0
DO WHILE .T.
cBuffer = Repli(Chr(0), 512)
nResult = RegEnumKey(THIS.hKey, nIndex, @cBuffer, Len(cBuffer))
IF nResult <> ERROR_SUCCESS
EXIT
ENDIF
cBuffer = SUBSTR(cBuffer, 1, AT(Chr(0),cBuffer)-1)
INSERT INTO TmpCur (mVar) VALUES (cBuffer)
hKey = 0
nIndex = nIndex + 1
ENDDO
ENDDEFINE
 
It would be nicer of you to link to the page of news2news where you got that from. And also not to paste this here, if it was one of the samples you need to pay for. IF.

Bye, Olaf.

 
Thanks.

I also found which also starts from HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall and lists all sub keys. This also confirms it's the official way to determine a list of installed software.

I assume some software, even though installed in an official way, don't have uninstall entries, but I can't tell for sure. The consequence of that would be, you would determine some product not being installed and reinstall it, even though it would be available.

I'd still go and recommend the route of trial & error and only signal the missing component to the user, if usage fails. You could put such a test at program start to not disappoint users at the end of a lengthy workflow or waiting time they may need to repeat.

Bye, Olaf.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top