13

MachineGuidライセンスシステムのOSとのある程度のバインディングを作成するために、レジストリからフェッチしようとしています。私が使用できるドキュメントから

string key = "HKEY_LOCAL_MACHINE\\SOFTWARE\\Microsoft\\Cryptography";
string r = (string)Registry.GetValue(key, "MachineGuid", (object)"default");

それを得るために。また、ドキュメント"default"には、名前が見つからないnull場合、またはキーが存在しない場合に取得することが示されています。アクセスできない場合は、セキュリティ例外が発生するはずです。

上記のコードは私"default"に、名前が見つからないことを意味します。ただし、RegEditを使用してレジストリを調べると、そこにあります。MachineGuid管理者権限のないアプリケーションから値を取得するにはどうすればよいですか?

更新:使用時reg.exeに値を取得するのに問題はありません。

更新:タイトルを更新したので、Windowsのインストールを決定する独自の方法を探している人もここにアクセスします。

4

3 に答える 3

21

これがおそらく、異なるバージョンの Windows 間で確実に動作しない理由です。

いいえ、それは理由ではありません。この問題は、EXE プロジェクトのプラットフォーム ターゲットの選択が原因で発生します。プロジェクト + プロパティ、ビルド タブ、プラットフォーム ターゲット コンボボックス。AnyCPU ではなく x86 に設定しています。VS2012 では、「32 ビットを優先」チェックボックスが重要です。この設定により、プログラムは 64 ビット バージョンの Windows で 32 ビット モードで実行されます。これには多くの副作用があります。ここで重要なのは、レジストリ キーへのアクセスがリダイレクトされることです。プログラムは実際に HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Cryptography\MachineGuid の値を読み取っています。これは存在しません。

x86 の選択は VS2010 以降のデフォルトであり、以前は AnyCPU がデフォルトでした。Microsoft は x86 を好み、Visual Studio は 32 ビット モードのプロセスでより適切に動作します。特にデバッグ時には、VS 自体が 32 ビット プロセスであるため、プログラムを 64 ビット モードで実行する場合はリモート デバッガが必要です。混合モードのデバッグがサポートされていないなど、いくつかの制限があります。また、エディット コンティニュ機能は 32 ビット コードでのみ機能します。ただし、Windows に組み込まれているファイル システムやレジストリ リダイレクト appcompat 機能に影響されないなど、AnyCPU に設定すると、プログラム自体は「より良く」動作します。

通常、更新できない 32 ビット ネイティブ コードに依存しているために x86 モードで本当に行き詰まっている場合、次の回避策は .NET 4+ RegistryKey.OpenBaseKey() メソッドを使用することです。これにより、RegistryView.Registry64 を渡すことができ、リダイレクトされていないキーを確実に読み取ることができます。

確かに、WMI を使用することは回避策です。Win32_OperatingSystem.SerialNumber を使用する場合、同じ情報を読み取っていないことに注意してください。そのキーが異なるマシンでどの程度確実にランダムであるかは、私には明確ではありません。この値は、製品のライセンス料を支払うことにあまり関心がない種類のユーザーにとって非常に魅力的なターゲットであるとだけ言っておきましょう。

最後になりましたが、Windows にまったく依存しない独自の一意の ID を生成するのは非常に簡単であることを考慮してください。顧客が自分のマシンで Windows を更新するときに顧客を怒らせないというかなりの利点があります。Guid.NewGuid() を 1 回使用して、値をファイルに保存するだけです。ドライブが故障すると失われますが、通常は製品も失われます。

于 2013-01-08T13:45:36.797 に答える
20

他の人がすでに指摘しているように、その値をレジストリから直接取得することは想定されていません (これがおそらく、異なるバージョンの Windows 間で確実に機能しない理由です)。

少し調べてみると、WMI クラスにたどり着きました。このクラスを使用すると、実際に Windows のシリアル番号を取得できます。それを正しく理解するには、検索と実験が必要でしたが、これが C# での使用方法です。Win32_OperatingSystem

System.Management.dllプロジェクトに参照があることを確認してください。

using System.Management;

...

ManagementObject os = new ManagementObject("Win32_OperatingSystem=@");
string serial = (string)os["SerialNumber"];

演算子を使用する[]と、クラス内の任意のプロパティを取得できます。

于 2013-01-08T11:30:34.897 に答える
11

私の謙虚な意見では、質問を満足させる答えはありません。レジストリから MachineGuid を読み取る方法を尋ねるのは非常に簡単です...だからここに私の答えがあります:「Microsoft.Win32」への参照を追加する必要があります。このコードはデモンストレーション用に作成されたものであり、それに応じて変更する必要があります。

編集: x64 コードは役に立たないと誰かが間違って述べました。
正しいキーが見つかる64ビットOSでは。

したがって、この回答は、質問を満たす唯一の回答です。

private void buttonGetMachineGuid_Click(object sender, RoutedEventArgs e)
{
  try
  {
    string x64Result = string.Empty;
    string x86Result = string.Empty;
    RegistryKey keyBaseX64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
    RegistryKey keyBaseX86 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry32);
    RegistryKey keyX64 = keyBaseX64.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography", RegistryKeyPermissionCheck.ReadSubTree);
    RegistryKey keyX86 = keyBaseX86.OpenSubKey(@"SOFTWARE\Microsoft\Cryptography", RegistryKeyPermissionCheck.ReadSubTree);
    object resultObjX64 = keyX64.GetValue("MachineGuid", (object)"default");
    object resultObjX86 = keyX86.GetValue("MachineGuid", (object)"default");
    keyX64.Close();
    keyX86.Close();
    keyBaseX64.Close();
    keyBaseX86.Close();
    keyX64.Dispose();
    keyX86.Dispose();
    keyBaseX64.Dispose();
    keyBaseX86.Dispose();
    keyX64 = null;
    keyX86 = null;
    keyBaseX64 = null;
    keyBaseX86 = null;
    if(resultObjX64 != null && resultObjX64.ToString() != "default")
    {
      MessageBox.Show(resultObjX64.ToString());
    }
    if(resultObjX86 != null && resultObjX86.ToString() != "default")
    {
      MessageBox.Show(resultObjX86.ToString());
    }
  }
  catch(Exception)
  {
  }
}

これが誰かに役立つことを願っています。

于 2013-12-01T18:25:37.270 に答える