可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Trying to use WMI to obtain a list of installed programs for Windows XP. Using wmic, I tried:
wmic /output:c:\ProgramList.txt product get name,version
and I get a listing of many of the installed programs, but after scrubbing this list against what "Add/Remove Programs" displays, I see many more programs listed in the GUI of Add/Remove Programs than with the WMI query. Is there another WMI query I need to use to get the rest of the programs installed? Or is there some other place I need to look for the rest?
Also, there are two installed programs that are listed in the WMI query that aren't in Add/Remove programs. Any idea why?
回答1:
I believe your syntax is using the Win32_Product Class in WMI. One cause is that this class only displays products installed using Windows Installer (See Here). The uninstall registry key is your best bet. Here is some code to monitor the registry key.
UPDATE FOR COMMENTS:
The Uninstall Registry Key is the standard place to list what is installed and what isn't installed. It is the location that the Add/Remove Programs list will use to populate the list of applications. I'm sure that there are applications that don't list themselves in this location. In that case you'd have to resort to another cruder method such as searching the Program Files directory or looking in the Start Menu Programs List. Both of those ways are definitely not ideal.
In my opinion, looking at the registry key is the best method.
回答2:
All that Add/Remove Programs is really doing is reading this Registry key:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
回答3:
Besides the most commonly known registry key for installed programs:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
wmic command and the add/remove programs also query another registry key:
HKEY_CLASSES_ROOT\Installer\Products
Software name shown in the list is read from the Value of a Data entry within this key called: ProductName
Removing the registry key for a certain product from both of the above locations will keep it from showing in the add/remove programs list. This is not a method to uninstall programs, it will just remove the entry from what's known to windows as installed software.
Since, by using this method you would lose the chance of using the Remove button from the add/remove list to cleanly remove the software from your system; it's recommended to export registry keys to a file before you delete them. In future, if you decided to bring that item back to the list, you would simply run the registry file you stored.
回答4:
I have been using Inno Setup for an installer. I'm using 64-bit Windows 7 only. I'm finding that registry entries are being written to
HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall
I haven't yet figured out how to get this list to be reported by WMI (although the program is listed as installed in Programs and Features). If I figure it out, I'll try to remember to report back here.
UPDATE:
Entries for 32-bit programs installed on a 64-bit machine go in that registry location. There's more written here:
http://mdb-blog.blogspot.com/2010/09/c-check-if-programapplication-is.html
See my comment that describes 32-bit vs 64-bit behavior in that same post here:
http://mdb-blog.blogspot.com/2010/09/c-check-if-programapplication-is.html?showComment=1300402090679#c861009270784046894
Unfortunately, there doesn't seem to be a way to get WMI to list all programs from the add/remove programs list (aka Programs and Features in Windows 7, not sure about Vista). My current code has dropped WMI in favor of using the registry. The code itself to interrogate the registry is even easier than using WMI. Sample code is in the above link.
回答5:
Not the best, but whether it is practical method:
Use HijackThis.
Run hijack this, click the "Open the Misc Tools section" button
click "Open Uninstall Manager"
click save list (*.txt), yes to the prompts, notepad will open with your add/remove programs list.
Source
回答6:
Installed products consist of installed software elements and features so it's worth checking wmic alias's for PRODUCT as well as checking SOFTWAREELEMENT and SOFTWAREFEATURE:
wmic product get name,version
wmic softwareelement get name,version
wmic softwarefeature get name,version
回答7:
You can use the script from http://technet.microsoft.com/en-us/library/ee692772.aspx#EBAA to access the registry and list applications using WMI.
回答8:
In order to build a more-or-less reliable list of applications that appear in the "Programs and Feautres" in the Control Panel, you have to consider that not all applications were installed using MSI. WMI only provides the ones installed with MSI.
Here is a short summary of what I've found out:
MSI applications always have a Product Code (GUID) subkey under HKLM\...\Uninstall
and/or under HKLM\...\Installer\UserData\S-1-5-18\Products
. In addition, they may have a key that looks like HKLM\...\Uninstall\NotAGuid
.
Non-MSI applications do not have a product code, and therefore have keys like HKLM\...\Uninstall\NotAGuid
or HKCU\...\Uninstall\NotAGuid
.
回答9:
Add/Remove Programs also has to look into this registry key to find installations for the current user:
HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Uninstall
Applications like Google Chrome, Dropbox, or shortcuts installed through JavaWS (web start) JNLPs can be found only here.
回答10:
I adapted the MS-Technet VBScript for my needs. It dumps Wow6432Node as well as standard entries into "programms.txt"
Use it at your own risk, no warranty!
Save as dump.vbs
From command line type: wscript dump.vbs
Const HKLM = &H80000002
Set objReg = GetObject("winmgmts://" & "." & "/root/default:StdRegProv")
Set objFSO = CreateObject("Scripting.FileSystemObject")
outFile="programms.txt"
Set objFile = objFSO.CreateTextFile(outFile,True)
writeList "SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\", objReg, objFile
writeList "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\", objReg, objFile
objFile.Close
Function writeList(strBaseKey, objReg, objFile)
objReg.EnumKey HKLM, strBaseKey, arrSubKeys
For Each strSubKey In arrSubKeys
intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, "DisplayName", strValue)
If intRet <> 0 Then
intRet = objReg.GetStringValue(HKLM, strBaseKey & strSubKey, "QuietDisplayName", strValue)
End If
objReg.GetStringValue HKLM, strBaseKey & strSubKey, "DisplayVersion", version
objReg.GetStringValue HKLM, strBaseKey & strSubKey, "InstallDate", insDate
If (strValue <> "") and (intRet = 0) Then
objFile.Write strValue & "," & version & "," & insDate & vbCrLf
End If
Next
End Function
回答11:
You can get it in one line with powershell and batch file :
@echo off
Powershell /command "Get-ItemProperty HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\* | Select-Object DisplayName, DisplayVersion, Publisher, InstallDate | Format-List"
Pause
回答12:
Hope this helps somebody: I've been using the registry-based enumeration in my scripts (as suggested by some of the answers above), but have found that it does not properly enumerate 64-bit software when run on Windows 10 x64 via SCCM (which uses a 32-bit client). Found something like this to be the most straightforward solution in my particular case:
Function Get-Programs($Bits) {
$Result = @()
$Output = (reg query HKLM\Software\Microsoft\Windows\CurrentVersion\Uninstall /reg:$Bits /s)
Foreach ($Line in $Output) {
If ($Line -match '^\s+DisplayName\s+REG_SZ\s+(.+?)$') {
$Result += New-Object PSObject -Property @{
DisplayName = $matches[1];
Bits = "$($Bits)-bit";
}
}
}
$Result
}
$Software = Get-Programs 32
$Software += Get-Programs 64
Realize this is a little too Perl-ish in a bad way, but all other alternatives I've seen involved insanity with wrapper scripts and similar clever-clever solutions, and this seems a little more human.
P.S. Trying really hard to refrain from dumping a ton of salt on Microsoft here for making an absolutely trivial thing next to impossible. I.e., enumerating all MS Office versions in use on a network is a task to make a grown man weep.