0

C#でレジストリキーをバックアップする必要があります。私はRegSaveKeyをP/Invokeしようとしても無駄になりました。グループポリシーの設定をオフにできないため、「Reg.exe」を使用してレジストリをバックアップできません。

すべてのコードは次のとおりです。

private static UIntPtr GetKey(string registryPath)
{
  UIntPtr hKey = UIntPtr.Zero;

  if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, registryPath, 0, KEY_READ, out hKey) != 0)
  {
     throw new Exception("Error getting key!");
  }

  return hKey;
}

private static void ExportRegistry(string registryPath)
{
  UIntPtr key = UIntPtr.Zero;
  try
  {
    key = GetKey(registryPath);
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex.Message);
    return;
  }

  if (key == UIntPtr.Zero)
  {
    Console.WriteLine("Not key to export!");
    return;
  }

  try
  {
    RegSaveKey(key, "c:\\temp\\test.reg", IntPtr.Zero);
  }
  catch (Exception ex)
  {
    Console.WriteLine(ex);
  }

  if (key != UIntPtr.Zero)
  {
    RegCloseKey(key);
  }
}

private static int KEY_READ = 131097;
private static UIntPtr HKEY_LOCAL_MACHINE = new UIntPtr(0x80000002u);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegCloseKey(UIntPtr hKey);

[DllImport("advapi32.dll", SetLastError = true)]
private static extern int RegOpenKeyEx(UIntPtr hKey, string subKey, int ulOptions, int samDesired, out UIntPtr hkResult);

[DllImport("advapi32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
public static extern uint RegSaveKey(UIntPtr hKey, string lpFile, IntPtr lpSecurityAttributes);
4

2 に答える 2

2

RegOpenKeyExまたはRegSaveKeyのいずれかの戻り値でエラーをチェックしていないようです。ERROR_PRIVILEGE_NOT_HELDの戻り値を取得していると思われます。レジストリ関数はSetLastErrorを使用せず、直接返します。また、事実上すべてのWin32 API呼び出しと同様に、戻り値をチェックする必要があります。

RegSaveKeyでは、ACLアクセスレベルに関係なく、SE_BACKUP_NAME権限を有効にする必要があります。したがって、RegSaveKeyを呼び出す前にこの特権を有効にし、呼び出しが完了した後に無効にするコードを追加する必要があります。

詳細については別の質問がありますが、他にもあると思います。

于 2013-02-01T18:26:43.107 に答える
1

まず第一に、あなたの質問はいくつかの非常に重要な詳細を見逃しているとコメントしたいと思います。つまり、コードがどのように失敗しているかについて、実際には何の情報も提供しません。あなたが言うのは:

私はRegSaveKeyをP/Invokeしようとしても無駄になりました。

このような質問はすべて詳細に関するものです。正確で詳細なエラー診断を確認する必要があります。画面が表示されないことに注意してください。

API呼び出しからの戻り値にもっと注意を払う必要があります。の戻り値をRegOpenKeyExゼロに対してチェックしていますが、それだけです。によって返される値をキャプチャして検査する必要がありますRegOpenKeyEx。これはエラーコードです。Win32Exceptionエラーコードがゼロに等しくない場合は、をスローできます。

int err = RegOpenKeyEx(...);
if (err != 0)
    throw new Win32Exception(err);

スローするようにコードを変更するWin32Exceptionと、エラーが発生したときに少なくともいくつかの有益なテキストが表示されます。したがって、RegOpenKeyExが失敗した場合は、少なくともその理由がわかります。

また、他のAPI呼び出しはまったくチェックしていません。彼らに同じ治療をしてください。

への呼び出しの失敗モードは実際にはほとんどありませんRegOpenKeyEx。私が考え出すことができる唯一のもっともらしい説明は、レジストリキーが存在しないということです。すでにチェックされていると思います。ただし、レジストリリダイレクタには注意してください。プロセスが64ビットOSで実行されている32ビットプロセスである場合、リダイレクタはWOW6432Nodeレジストリのセクションである32ビットビューに移動します。おそらく、「役に立たない」とは、情報がファイルに保存されているという意味ですが、それは間違った情報です。それはあなたを混乱させるレジストリリダイレクタと一致するでしょう。

それが噛み付いている場合は、KEY_WOW64_64KEYを呼び出すときにフラグを含めますRegOpenKeyEx。または、x64をターゲットにします。

RegistryKeyキーを開くのに使用する方がはるかに簡単です。すぐに電話をかけることはできないRegSaveKeyので、それをp/invokeする必要があることを理解しています。ただし、に渡すことができるプロパティをRegistryKey公開します。これには1つの但し書きがあります。フラグを使用する必要がある場合は、.net4と。が必要です。HandleRegSaveKeyKEY_WOW64_64KEYRegistryView

に関してはRegSaveKey、私はスティーブンが彼の答えで与えた情報に従います。

于 2013-02-01T19:08:55.263 に答える