アップグレードコードが次のレジストリの場所に格納されていることを発見しました。
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes
レジストリキー名はアップグレードコードであり、レジストリキー値nameは製品コードです。私は簡単にこれらの値を抽出することができますが、コードは別の形式で保存されます。赤い丸はフォーマットされたアップグレードコードを示し、青い丸はregedit.exe
で表示したときのフォーマットされた製品コードを示しています。
ハイフンはGuid
からストリッピングされた後、文字列の反転のシリーズが行われます。最初の8文字が反転され、次に4文字、次に4文字、残りの文字列が2文字のセットで反転されます。通常、文字列を反転するときは、コントロールと特殊文字が正しく処理されるように注意する必要がありますが(see Jon Skeet's aricle here)、この場合はGuid
文字列を扱うので、文字列が正しく逆転されると確信できます。
以下は、レジストリから既知の製品コードのアップグレードコードを抽出するために使用した完全なコードです。
internal static class RegistryHelper
{
private const string UpgradeCodeRegistryKey = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UpgradeCodes";
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();
}
}
のではなく、以下の提案として、レジストリを使用して、**私はこの答えで説明したように、あなたが** WMIを使用することを提案している:[**どのようにすることができますインストールされたMSIファイルのアップグレードコードを探しますか?**](https:// stackoverflow。com/questions/46637094/msiファイルがインストールされたアップグレードコードを探す方法/ 46637095#46637095)。これにより、適切なアップグレードコードが確実に取得され、変換や解釈が不要になります。 **実際のアップグレードコードを適切なフォーマットに戻します**。 –