"P/Invoke入口点应该存在",正确的入口点应该是什么。

3

我正在使用Visual Studio 2012的代码分析工具时遇到了这个警告。代码如下:

using System;
using System.Runtime.InteropServices;

namespace MyProgramNamespace
{
    class NativeMethods
    {
        [DllImport("user32.dll", EntryPoint = "GetWindowLongPtr")]
        public static extern IntPtr GetWindowLongPtr(IntPtr handle, int flag);

        [DllImport("user32.dll", EntryPoint = "SetWindowLongPtr")]
        public static extern IntPtr SetWindowLongPtr(IntPtr handle, int flag, IntPtr ownerHandle);
    }
}

我只编译x64,所以我不关心使用旧的GetWindowLong和SetWindowLong。就我所知,这些入口点名称是正确的。
编辑:已解决。 原来问题是Visual Studio本身(因此Code Analysis工具)是32位的。当代码分析工具检查user32.dll以查看这些函数是否存在时,它会检查32位版本的user32.dll (在C:/Windows/SysWOW64/中),而不是程序实际使用的版本(64位版本在C:/Windows/System32中),而且这些函数仅存在于64位版本中(32位版本使用GetWindowLong/SetWindowLong代替GetWindowLongPtr/SetWindowLongPtr(请注意PTR部分))。

2
这只是猜测,但也许代码分析工具只检查了user32.dll的32位版本。Get/SetWindowLongPtr在user32.dll的32位版本中不存在。如果代码分析工具本身是32位的,那可能就是原因。 - shf301
此外,如果我注释掉底部的两行代码(用于SetWindowLongPtr),所有警告都会消失。但是如果取消注释这些行,无论是Get方法还是Set方法都会出现警告。如果我只注释掉顶部的两行代码(Get),那么Set仍然会出现警告。 - Steve Niles
1
@Jargon 我会将解决方案发布为答案并标记它,因为没有一个给出的答案是正确的(包括我的)。 - Tergiver
3个回答

1

它们不起作用的原因是在DllImport属性中指定EntryPoint =时,您正在告诉Marshaller:“这是我要调用的确切函数”。

user32.dll中没有名为GetWindowLongPtr的函数。有GetWindowLongPtrA和GetWindowLongPtrW。

如果省略EntryPoint =,则Marshaller将根据运行的操作系统调用其中一个。

因此,要么省略它,要么指定A或W版本。如果指定A或W,则还需要为A版本指定CharSet = CharSet.Ansi,或者为W版本指定CharSet = CharSet.Unicode。


尝试移除EntryPoint,但没有解决问题,也尝试添加CharSet(使用Ansi的A和Unicode的W都尝试过),但都无法消除警告。 - Steve Niles
@行话警告?这个警告是从哪里来的?肯定不是编译器。你在使用某种代码检查工具吗? - Tergiver
@Jargon 然后我在谷歌上搜索了一下 (http://msdn.microsoft.com/en-us/library/ms182208.aspx)。这是来自 FxCop 的。只需禁用警告并测试调用是否在运行时成功即可。 - Tergiver
1
是的,我在帖子的第一行提到了它是Visual Studio 2012中的Code Analysis工具(在旧版本中曾经是FxCop)。虽然我可以抑制这个警告,但我更想知道是什么导致了它,以确保我正确地执行了Interop。 - Steve Niles
根据我提供的链接,这是由于检查工具无法找到DLL引起的。为什么它找不到系统DLL,我不知道,但它确实说它只在可执行文件所在的同一目录中查找。 - Tergiver
1
就是这样。我将 user32.dll 从 System32 文件夹中复制,警告消失了。如果我从 SysWOW64(32位版本)复制 user32.dll,则警告仍然存在。我想这就是在 x86 IDE 中编写 x64 代码的后果。 - Steve Niles

1

原来问题在于Visual Studio本身(因此Code Analysis工具)是32位的。当代码分析工具检查user32.dll是否存在这些函数时,它会检查32位版本的user32.dll(位于C:/Windows/SysWOW64/),而不是程序实际使用的版本(64位版本位于C:/Windows/System32),而这些函数仅存在于64位版本中(32位版本使用GetWindowLong/SetWindowLong代替GetWindowLongPtr/SetWindowLongPtr(注意PTR部分))。


0

请尝试以下方法:

    [DllImport("user32.dll", EntryPoint = "GetWindowLongPtrW")]
    public static extern IntPtr GetWindowLongPtr(IntPtr handle, int flag);

    [DllImport("user32.dll", EntryPoint = "SetWindowLongPtrW")]
    public static extern IntPtr SetWindowLongPtr(IntPtr handle, int flag, IntPtr ownerHandle);

1
我尝试过用W和A键(在某个地方看到过)。都不起作用:S - Steve Niles
是的,ExactSpelling 似乎没有任何影响。 - Steve Niles
我的错误,如果指定了 EntryPoint,则不需要 ExactSpelling...我认为这个 警告 是正常的,因为当我编译 x64 程序集时会出现类似的警告(它会警告 _参考程序集_)。 - Jigsore

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接