Como posso enumerar / lista todos os aplicativos instalados no Windows XP?
-
03-07-2019 - |
Pergunta
Quando eu digo "aplicativo instalado", eu basicamente significa qualquer aplicação visível no [Painel de Controle] -> [Adicionar / Remover Programas].
Eu preferiria fazê-lo em Python, mas C ou C ++ também é bom.
Solução
Se você quer dizer a lista de aplicativos instalados que é mostrado em Adicionar \ remover programas no painel de controle, você pode encontrá-lo na chave de registo:
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Uninstall
mais informações sobre como a árvore de registro é estruturado pode ser encontrada aqui .
Você precisa usar o winreg API em python para ler os valores de o registro.
Outras dicas
Confira o Win32_Product WMI (Windows Management Instrumentation) classe. Aqui está um tutorial sobre o uso WMI em Python.
Painel de Controle utiliza Win32 COM API, que é o método oficial (ver Google Groups, Win32)
Nunca confie em registro.
The Script Repository Microsoft tem um script para listar todos os softwares instalados.
import win32com.client
strComputer = "."
objWMIService = win32com.client.Dispatch("WbemScripting.SWbemLocator")
objSWbemServices = objWMIService.ConnectServer(strComputer,"root\cimv2")
colItems = objSWbemServices.ExecQuery("Select * from Win32_Product")
for objItem in colItems:
print "Caption: ", objItem.Caption
print "Description: ", objItem.Description
print "Identifying Number: ", objItem.IdentifyingNumber
print "Install Date: ", objItem.InstallDate
print "Install Date 2: ", objItem.InstallDate2
print "Install Location: ", objItem.InstallLocation
print "Install State: ", objItem.InstallState
print "Name: ", objItem.Name
print "Package Cache: ", objItem.PackageCache
print "SKU Number: ", objItem.SKUNumber
print "Vendor: ", objItem.Vendor
print "Version: ", objItem.Version
A melhor implementação baseada em registro que eu tenho visto é aquele escrito por Chris Wright (chris128) publicadas em http://www.vbforums.com/showthread.php?t=598355 . Ele usa várias chaves de registro e é muito mais complexa do que qualquer uma das respostas actualmente publicados aqui. Ele parece produzir resultados idênticos para o Adicionar / Remover aplicativo programas e, como o aplicativo ARP também fornece uma opção para incluir atualizações.
Embora seja implementado em VB.NET, ele deve ser fácil para converter a outras linguagens .NET como C # ou IronPython. Imagino que a conversão para IronPython primeiro deve torná-lo bastante fácil para a porta para Python regular, se é isso que você quer, mas eu só converteu-o para C # mesmo e, em seguida, limpar o código um pouco.
Apenas um pequeno bug em apontar: não GetUserInstallerKeyPrograms () não adicionar a versão para programas do usuário à lista, mesmo que ele extrai-lo. Isso é fácil de correção embora.
C # .NET código para obter a lista de software instalado usando WMI no XP e Win7 (WMI é a única maneira em win7)
WqlObjectQuery wqlQuery =
new WqlObjectQuery("SELECT * FROM Win32_Product");
ManagementObjectSearcher searcher =
new ManagementObjectSearcher(wqlQuery);
foreach (ManagementObject software in searcher.Get()) {
Console.WriteLine(software["Caption"]);
}
Eu sei que esta questão é velho, o OP mencionado XP e também mencionou Python, C ou C ++, mas eu achei que um monte de informações na rede sobre este tema está incompleto ou incorreto. Um exemplo do último é a sugestão de se usar o WMI - especificamente, a classe Win32_Product
; no entanto, como é observado em outros lugares, esse método é lento , em parte porque, acredite ou não, cada MSI encontrado na verdade é executado a sua reparação. Eu chamo isso de solução incorreta por causa de como dolorosamente lento que é e por causa de seu efeito colateral desagradável. Por exemplo, você já optou por desativar o serviço Windows de um programa, mas select * from Win32_Product
chamando, como parte da garantia de que o MSI reparação corridas, aparentemente vai reativar o serviço.
Por que vale a pena, a seguir é o que eu considero ser o exemplo mais completo até à data, ainda que em C # (I compilado contra Framework 4.6.1 mas as versões mais baixas podem funcionar também.) Ele lista 32-bit e 64 bit programas instalados; que dispõe chaves do registro que ele usa e ele é executado em menos de um segundo, pelo menos depois cache chutes. Se você pode oferecer melhorias, por favor, sugerem-los em vez de apenas downvoting, e eu vou atualizar o código.
Uma coisa que é ainda está faltando é algumas atualizações. Por exemplo, quando eu executá-lo no meu sistema Windows 10 e compará-lo com o Painel de Controle | Programas e Recursos | Atualizações instaladas, noto que ele não mostra Security Update for Adobe Flash Player
por algum motivo.
Eu não tenho nenhuma boa razão para o método anônimo, é apenas como eu estava pensando no momento -. Uma espécie de solução método-dentro-do-método
using System;
using System.Collections.Generic;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.RegularExpressions;
using Microsoft.Win32;
class Program
{
static void Main(string[] args)
{
var result = InstalledProgram.GetAllInstalledPrograms();
result.Sort((a, b) => a.DisplayName.CompareTo(b.DisplayName));
foreach(var program in result)
{
if(!program.IsSystemComponent && !program.IsKB) Console.WriteLine(program.Dump());
}
}
}
public enum PlatformTypes
{
x86,
amd64
}
public class InstalledProgram
{
[DllImport("advapi32.dll")]
extern public static int RegQueryInfoKey(
Microsoft.Win32.SafeHandles.SafeRegistryHandle hkey,
StringBuilder lpClass,
ref uint lpcbClass,
IntPtr lpReserved,
IntPtr lpcSubKeys,
IntPtr lpcbMaxSubKeyLen,
IntPtr lpcbMaxClassLen,
IntPtr lpcValues,
IntPtr lpcbMaxValueNameLen,
IntPtr lpcbMaxValueLen,
IntPtr lpcbSecurityDescriptor,
out long lpftLastWriteTime
);
public string DisplayName { get; private set; }
public string UninstallString { get; private set; }
public string KBNumber { get; private set; }
public string DisplayIcon { get; private set; }
public string Version { get; private set; }
public DateTime InstallDate { get; private set; }
public PlatformTypes Platform { get; private set; }
public bool IsSystemComponent { get; private set; }
public bool IsKB { get { return !string.IsNullOrWhiteSpace(KBNumber); } }
public static List<InstalledProgram> GetAllInstalledPrograms()
{
var result = new List<InstalledProgram>();
Action<PlatformTypes, RegistryKey, string> getRegKeysForRegPath = (platform, regBase, path) =>
{
using(var baseKey = regBase.OpenSubKey(path))
{
if(baseKey != null)
{
string[] subKeyNames = baseKey.GetSubKeyNames();
foreach(string subkeyName in subKeyNames)
{
using(var subKey = baseKey.OpenSubKey(subkeyName))
{
object o;
o = subKey.GetValue("DisplayName");
string displayName = o != null ? o.ToString() : "";
o = subKey.GetValue("UninstallString");
string uninstallString = o != null ? o.ToString() : "";
o = subKey.GetValue("KBNumber");
string kbNumber = o != null ? o.ToString() : "";
o = subKey.GetValue("DisplayIcon");
string displayIcon = o != null ? o.ToString() : "";
o = subKey.GetValue("DisplayVersion");
string version = o != null ? o.ToString() : "";
o = subKey.GetValue("InstallDate");
DateTime installDate = o != null ? parseInstallDate(o.ToString()) : default(DateTime);
o = subKey.GetValue("SystemComponent");
bool isSystemComponent = o != null ? o.ToString() == "1" : false;
// Sometimes, you need to get the KB number another way.
if(kbNumber == "")
{
var match = Regex.Match(displayName, @".*?\((KB\d+?)\).*");
if(match.Success) kbNumber = match.Groups[1].ToString();
}
// Sometimes, the only way you can get install date is from the last write
// time on the registry key.
if(installDate == default(DateTime))
{
string keyFull = baseKey + "\\" + subkeyName + "\\DisplayVersion";
var sb = new StringBuilder(64);
uint sbLen = 65;
RegQueryInfoKey(
subKey.Handle
, sb
, ref sbLen
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, IntPtr.Zero
, out long lastWriteTime);
installDate = DateTime.FromFileTime(lastWriteTime);
}
if(displayName != "" && uninstallString != "")
{
result.Add(new InstalledProgram
{
DisplayName = displayName,
UninstallString = uninstallString,
KBNumber = kbNumber,
DisplayIcon = displayIcon,
Version = version,
InstallDate = installDate,
Platform = platform,
IsSystemComponent = isSystemComponent
});
}
}
}
}
}
};
getRegKeysForRegPath(PlatformTypes.amd64, Registry.LocalMachine, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
getRegKeysForRegPath(PlatformTypes.amd64, Registry.CurrentUser, @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall");
if(Environment.Is64BitOperatingSystem)
{
getRegKeysForRegPath(PlatformTypes.x86, Registry.LocalMachine, @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
getRegKeysForRegPath(PlatformTypes.x86, Registry.CurrentUser, @"SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall");
}
return result;
}
public string Dump()
{
return Platform + "\t" + DisplayName + "\t" + InstallDate + "\t" + DisplayIcon + "\t" + Version + "\t" + KBNumber + "\t" + UninstallString;
}
private static DateTime parseInstallDate(string installDateStr)
{
DateTime.TryParseExact(
installDateStr
, format: "yyyyMMdd"
, provider: new System.Globalization.CultureInfo("en-US")
, style: System.Globalization.DateTimeStyles.None
, result: out DateTime result);
return result;
}
public override string ToString()
{
return DisplayName;
}
}
[Suspiro] e então viu I @ resposta de PolyTekPatrick. Como eu perdi isso? LOL