如何在C#中借助Windows Installer而非WMI通过产品名获取产品版本?
C#快速获取已安装程序的ProductVersion(替代WMI方法)
背景需求
之前用VBS通过Windows Installer可快速获取已安装程序的版本信息,但WMI方法速度极慢。现在需要在C#(基于Avalonia UI框架)中实现相同功能,且没有目标程序的MSI或EXE文件路径,因此GetFileVersion或Wix DTF方法无法使用。
对应的VBS实现代码:
Set objInstaller = CreateObject("WindowsInstaller.Installer") Set colProducts = objInstaller.Products For Each objProduct In colProducts strProductName = objInstaller.ProductInfo(objProduct, "ProductName") If strProductName = "MyProductName1" Then var1 = objInstaller.ProductInfo(objProduct, "VersionString") End If If strProductName = "MyProductName2" Then var2 = objInstaller.ProductInfo(objProduct, "VersionString") End If Next
尝试过程
Edit1:首次编写注册表查询代码
最初尝试通过32位注册表路径查询,但存在逻辑问题(break未加括号导致提前退出),且查询的注册表项错误:
public class Program { public static string getInstalledVersion(string findByName) { string info = null; string registryKey = @"SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"; RegistryKey key32 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32); RegistryKey key = key32.OpenSubKey(registryKey); if (key != null) { foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName))) { string displayName = subkey.GetValue("DisplayName") as string; if (displayName != null && displayName.Contains(findByName)) info = subkey.GetValue("Version").ToString(); break; else info = "Not found"; } key.Close(); } return info; } }
调用方式:
public string MyVar => Program.getInstalledVersion("Microsoft Edge");
Edit2:修复逻辑后仍存在问题,尝试ProductInstallation方法
添加break的括号后能找到Microsoft Edge,但无法识别其他程序;尝试使用ProductInstallation方法也未生效:
public class ProgramX { public static string getPVersion(string findByName) { string info = null; foreach (var p in ProductInstallation.AllProducts) { if (p.ProductName == findByName) { info = p.ProductVersion.ToString(); break; } else info = "Not Found"; } return info; } }
调用方式:
public string MyProgram => ProgramX.getPVersion("Microsoft Edge");
Edit3:最终解决方案
问题根源在于:
- 注册表中存储版本信息的键是
DisplayVersion而非Version - 需要查询64位注册表路径(无需额外指定WOW6432Node,通过
RegistryView.Registry64自动处理)
最终代码:
public class ProgramI { public static string getInstalledVersion(string findByName) { string info = null; string registryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"; RegistryKey key64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64); RegistryKey key = key64.OpenSubKey(registryKey); if (key != null) { foreach (RegistryKey subkey in key.GetSubKeyNames().Select(keyName => key.OpenSubKey(keyName))) { string displayName = subkey.GetValue("DisplayName") as string; if (displayName != null && displayName.Contains(findByName)) { info = subkey.GetValue("DisplayVersion").ToString(); break; } else info = "Not found"; } key.Close(); } return info; } }
内容的提问来源于stack exchange,提问作者Lodes
相关产品推荐
相关产品推荐

