使用 DllImport 从 C# 调用 Win API 时发生访问冲突

发布于 2024-12-22 21:03:38 字数 883 浏览 0 评论 0原文

任务是确定注册表项的最后写入时间。由于标准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);

此时我得到“访问冲突”异常。我做错了什么? 我认为参数传递有问题,但是如何正确处理呢?

谢谢。

The task is to determine the last write time for the registry key. As standard RegistryKey class doesn't provide this feature, I have to use WinAPI function "RegQueryInfoKey". To get the key handle I open it by "RegOpenKeyEx".

This is the WinAPI prototype of the function (taken from MSDN):

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

I use the following declaration:

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

Then I call it in the following way:

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

At this point I get "Access violation" exception. What am I doing wrong?
I think something is wrong with parameters passing, but how to do it right?

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

薯片软お妹 2024-12-29 21:03:38

本机函数的原型中有 5 个参数,而 P/Invoke 签名中只有 4 个参数。

特别是,您缺少DWORD ulOptions。根据 MSDN 文档,该参数是“保留的且必须为零”,但仍必须在函数调用中传递。

另外,您不需要设置 < code>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 签名几乎总是导致“访问冲突”错误。当您看到其中之一时,请务必仔细检查两次!

There are 5 parameters in the native function's prototype, and only 4 in your P/Invoke signature.

In particular, you're missing DWORD ulOptions. This parameter is "reserved and must be zero" according to the MSDN documentation, but it must still be passed in the function call.

Also, you don't need to set the SetLastError field because the RegOpenKeyEx function returns its error code; you don't have to retrieve it by calling GetLastError. Consequently, you don't need the marshaler to save that value for you automatically. Just check the return value for the error code.

Change your P/Invoke signature to look like this:

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

The wrong P/Invoke signature is almost always the cause of "access violation" errors. When you see one of those, make sure you double-check it twice!

情深已缘浅 2024-12-29 21:03:38

您的 P/Invoke 签名中缺少 ulOptions

You've missed ulOptions from your P/Invoke signature.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文