如何在 C# 中找到已安装应用程序的升级代码? [英] How can I find the upgrade code for an installed application in C#?

查看:15
本文介绍了如何在 C# 中找到已安装应用程序的升级代码?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用来自

连字符从 Guid 中去除,然后完成一系列字符串反转.前 8 个字符被反转,然后是接下来的 4 个,然后是后面的 4 个,然后字符串的其余部分以 2 个字符为一组进行反转.通常在反转字符串时,我们需要注意确保正确处理控制和特殊字符(在这里查看 Jon Skeet 的文章) 但在这种情况下,处理 Guid 字符串,我们可以确信该字符串将是正确反转.

以下是我用来从注册表中提取已知产品代码的升级代码的完整代码.

内部静态类RegistryHelper{private const string UpgradeCodeRegistryKey = @"SOFTWAREMicrosoftWindowsCurrentVersionInstallerUpgradeCodes";私有静态只读 int[] GuidRegistryFormatPattern = new[] { 8, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2 };公共静态指导?GetUpgradeCode(Guid productCode){//将产品代码转换为在注册表中找到的格式var productCodeSearchString = ConvertToRegistryFormat(productCode);//打开升级代码注册表项var localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);var upgradeCodeRegistryRoot = localMachine.OpenSubKey(UpgradeCodeRegistryKey);if (upgradeCodeRegistryRoot == null)返回空值;//遍历每个子键foreach (var subKeyName in upgradeCodeRegistryRoot.GetSubKeyNames()){var subkey = upgradeCodeRegistryRoot.OpenSubKey(subKeyName);如果(子键 == 空)继续;//检查包含产品代码的值if (subkey.GetValueNames().Any(s => s.IndexOf(productCodeSearchString, StringComparison.OrdinalIgnoreCase) >= 0)){//从限定名中提取子键名var formattedUpgradeCode = subkey.Name.Split('\').LastOrDefault();//将其转换回 Guid返回 ConvertFromRegistryFormat(formattedUpgradeCode);}}返回空值;}私有静态字符串 ConvertToRegistryFormat(Guid productCode){返回反向(产品代码,GuidRegistryFormatPattern);}私有静态 Guid ConvertFromRegistryFormat(string upgradeCode){if (upgradeCode == null || upgradeCode.Length != 32)throw new FormatException("产品代码格式无效");upgradeCode = Reverse(upgradeCode, GuidRegistryFormatPattern);返回 Guid.Parse(upgradeCode);}私有静态字符串反向(对象值,参数 int [] 模式){//去掉连字符var inputString = value.ToString().Replace("-", "");var returnString = new StringBuilder();变量索引 = 0;//遍历反转模式foreach(模式中的var长度){//反转子字符串并附加它returnString.Append(inputString.Substring(index, length).Reverse().ToArray());//增加我们在字符串中的位置索引 += 长度;}返回 returnString.ToString();}}

I am using the C# wrapper for the Windows Installer API from the WIX Toolset. I use the ProductInstallation class to get information about the installed products such as the product code and product name.

For example

  • Product Name - "My Test Application"
  • Product Code - {F46BA620-C027-4E68-9069-5D5D4E1FF30A}
  • Product Version - 1.4.0

Internally this wrapper uses the MsiGetProductInfo function. Unfortunately this function does not return the product's upgrade code.

How can I retrieve the upgrade code for an installed application using C#?

解决方案

I have discovered the upgrade codes are stored in the following registry location.

HKEY_LOCAL_MACHINESOFTWAREMicrosoftWindowsCurrentVersionInstallerUpgradeCodes

The registry key name is the upgrade code and the registry key value name is the product code. I can easily extract these values however the codes are stored in a different format. The red circle shows the formatted upgrade code, the blue circle shows the formatted product code when viewing it in regedit.exe.

The hyphens are stripped out of the Guid and then a series of string reversals are done. The first 8 characters are reversed, then the next 4, then the following 4 and then the rest of the string is reversed in sets of 2 characters. Normally when reversing a string we need to take care in making sure control and special characters are handled correctly (see Jon Skeet's aricle here) but as we are, in this case, dealing with a Guid string we can be confident the string will be reversed correctly.

Below is the complete code I used to extract the upgrade code for a known product code from the registry.

internal static class RegistryHelper
{
    private const string UpgradeCodeRegistryKey = @"SOFTWAREMicrosoftWindowsCurrentVersionInstallerUpgradeCodes";

    private static readonly int[] GuidRegistryFormatPattern = new[] { 8, 4, 4, 2, 2, 2, 2, 2, 2, 2, 2 };

    public static Guid? GetUpgradeCode(Guid productCode)
    {
        // Convert the product code to the format found in the registry
        var productCodeSearchString = ConvertToRegistryFormat(productCode);

        // Open the upgrade code registry key
        var localMachine = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
        var upgradeCodeRegistryRoot = localMachine.OpenSubKey(UpgradeCodeRegistryKey);

        if (upgradeCodeRegistryRoot == null)
            return null;

        // Iterate over each sub-key
        foreach (var subKeyName in upgradeCodeRegistryRoot.GetSubKeyNames())
        {
            var subkey = upgradeCodeRegistryRoot.OpenSubKey(subKeyName);

            if (subkey == null)
                continue;

            // Check for a value containing the product code
            if (subkey.GetValueNames().Any(s => s.IndexOf(productCodeSearchString, StringComparison.OrdinalIgnoreCase) >= 0))
            {
                // Extract the name of the subkey from the qualified name
                var formattedUpgradeCode = subkey.Name.Split('\').LastOrDefault();

                // Convert it back to a Guid
                return ConvertFromRegistryFormat(formattedUpgradeCode);
            }
        }

        return null;
    }

    private static string ConvertToRegistryFormat(Guid productCode)
    {
        return Reverse(productCode, GuidRegistryFormatPattern);
    }

    private static Guid ConvertFromRegistryFormat(string upgradeCode)
    {
        if (upgradeCode == null || upgradeCode.Length != 32)
            throw new FormatException("Product code was in an invalid format");

        upgradeCode = Reverse(upgradeCode, GuidRegistryFormatPattern);

        return Guid.Parse(upgradeCode);
    }

    private static string Reverse(object value, params int[] pattern)
    {
        // Strip the hyphens
        var inputString = value.ToString().Replace("-", "");

        var returnString = new StringBuilder();

        var index = 0;

        // Iterate over the reversal pattern
        foreach (var length in pattern)
        {
            // Reverse the sub-string and append it
            returnString.Append(inputString.Substring(index, length).Reverse().ToArray());

            // Increment our posistion in the string
            index += length;
        }

        return returnString.ToString();
    }
}

这篇关于如何在 C# 中找到已安装应用程序的升级代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆