Нарушение доступа при вызове Win API из C # с использованием DllImport - PullRequest
4 голосов
/ 24 декабря 2011

Задача - определить время последней записи для раздела реестра. Поскольку стандартный класс RegistryKey не предоставляет эту функцию, я должен использовать функцию WinAPI RegQueryInfoKey Чтобы получить ручку ключа, я открываю его с помощью «RegOpenKeyEx».

Это прототип функции WinAPI (взят из MSDN):

LONG WINAPI RegOpenKeyEx(
  __in          HKEY hKey,
  __in          LPCTSTR lpSubKey,
                DWORD ulOptions,
  __in          REGSAM samDesired,
  __out         PHKEY phkResult
);

Я использую следующую декларацию:

[DllImport("advapi32.dll", CharSet = CharSet.Auto, SetLastError = true)]
public static extern int RegOpenKeyEx(UIntPtr hkey, string lpSubKey, uint samDesired, ref UIntPtr phkResult);

Тогда я называю это следующим образом:

UIntPtr hKey = UIntPtr.Zero;
string myKeyName = "blablabla";
UIntPtr HKEY_USERS = (UIntPtr)0x80000003; 
uint KEY_READ = 0x20019;
RegOpenKeyEx(HKEY_USERS, myKeyName, KEY_READ, ref hKey);

В этот момент я получаю исключение "Нарушение прав доступа". Что я делаю неправильно? Я думаю, что что-то не так с передачей параметров, но как это сделать правильно?

Спасибо.

Ответы [ 2 ]

4 голосов
/ 24 декабря 2011

В прототипе нативной функции есть 5 параметров и только 4 в вашей подписи P / Invoke.

В частности, вам не хватает DWORD ulOptions.Этот параметр «зарезервирован и должен быть нулевым» в соответствии с документацией MSDN, но он все равно должен передаваться при вызове функции.

Также вам не нужно устанавливать поле SetLastError потому что функция RegOpenKeyEx возвращает свой код ошибки;вам не нужно извлекать его, позвонив по номеру GetLastError.Следовательно, вам не нужен маршалер для автоматического сохранения этого значения для вас.Просто проверьте возвращаемое значение для кода ошибки.

Измените свою подпись P / Invoke, чтобы она выглядела следующим образом:

[DllImport("advapi32.dll", CharSet = CharSet.Auto)]
public static extern int RegOpenKeyEx(UIntPtr hkey, string lpSubKey,
                                      uint ulOptions, uint samDesired,
                                      out UIntPtr phkResult);

Неправильная подпись P / Invoke почти всегда является причиной "доступа"нарушение "ошибки.Когда вы увидите один из них, проверьте его дважды!

4 голосов
/ 24 декабря 2011

Вы пропустили ulOptions из своей подписи P / Invoke.

...