问题描述
我正在使用来自
连字符从 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# 中找到已安装应用程序的升级代码?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!