Точки входа P/Invoke должны существовать с указанными правильными точками входа.

Я получаю это предупреждение от инструмента анализа кода в 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 (и, следовательно, инструмент анализа кода) являются 32-битными. Когда инструмент анализа кода проверяет user32.dll на наличие этих функций, он проверяет 32-разрядную версию user32.dll (в C:/Windows/SysWOW64/) вместо той, которую программа фактически будет использовать (64-разрядная версия). в C:/Windows/System32), и эти функции существуют только в 64-битной версии (32-битная версия использует GetWindowLong/SetWindowLong вместо GetWindowLongPtr/SetWindowLongPtr (обратите внимание на часть PTR)).


person Steve Niles    schedule 30.10.2012    source источник
comment
Это предположение, но, возможно, инструмент анализа кода проверяет только 32-разрядную версию user32.dll. Get/SetWindowLongPtr не существует в 32-разрядной версии user32.dll. Если инструмент анализа кода сам по себе 32-битный, это может быть причиной.   -  person shf301    schedule 31.10.2012
comment
Кроме того, если я закомментирую две нижние строки (для SetWindowLongPtr), все предупреждения исчезнут. Тем не менее, когда эти строки не закомментированы, оба метода Get и Set выдают предупреждение. Если я закомментирую только две верхние строки (Get), Set все равно выдаст предупреждение   -  person Steve Niles    schedule 31.10.2012
comment
@Jargon Я бы опубликовал решение как ответ и отметил его, так как ни один из ответов не был правильным (включая мой).   -  person Tergiver    schedule 31.10.2012


Ответы (3)


Причина, по которой они не работают, заключается в том, что, указав EntryPoint = в атрибуте DllImport, вы сообщаете Marshaller: «Это именно та функция, которую я хочу, чтобы вы вызывали».

В user32.dll нет функции с именем GetWindowLongPtr. Есть GetWindowLongPtrA и GetWindowLongPtrW.

Если вы пропустите EntryPoint=, Marshaller будет вызывать один или другой в зависимости от работающей ОС.

Так что либо оставьте это, либо укажите версии A или W. Если вы укажете A или W, вы также захотите указать CharSet=CharSet.Ansi для версии A или CharSet=CharSet.Unicode для версии W.

person Tergiver    schedule 30.10.2012
comment
Пытался удалить EntryPoint, не исправляет, а также пытался добавить CharSet (пробовал A с Ansi и W с Unicode), предупреждение не исчезло. - person Steve Niles; 31.10.2012
comment
@ Жаргон Предупреждение? Откуда это предупреждение? Точно не компилятор. Вы используете какой-то инструмент для проверки кода? - person Tergiver; 31.10.2012
comment
@Jargon Затем я погуглил (msdn.microsoft.com/en-us/library /ms182208.aspx). Это от FxCop. Просто отключите предупреждение и проверьте, успешно ли выполняется вызов во время выполнения. - person Tergiver; 31.10.2012
comment
Да, я упомянул в первой строке своего поста, что это инструмент анализа кода в Visual Studio 2012 (который в более старых версиях назывался FxCop). Я мог бы подавить предупреждение, но я бы предпочел знать, что вызывает его, чтобы убедиться, что я правильно выполняю взаимодействие. - person Steve Niles; 31.10.2012
comment
@Jargon Согласно ссылке, которую я дал, это вызвано тем, что инструмент проверки не может найти DLL. Почему он не может найти системную DLL, я не знаю, но он говорит, что ищет только в том же каталоге, что и исполняемый файл. - person Tergiver; 31.10.2012
comment
Это должно быть так. Я скопировал user32.dll из папки System32, и предупреждения исчезли. Если я скопирую user32.dll из SysWOW64 (32-битная версия), предупреждения останутся. Я думаю, это то, что я получаю за написание кода x64 в x86 IDE. - person Steve Niles; 31.10.2012

(Этот ответ также опубликован в редактировании внизу исходного вопроса, чтобы помочь людям найти его быстро и легко)

Оказывается, проблема в том, что сама Visual Studio (и, следовательно, инструмент анализа кода) являются 32-битными. Когда инструмент анализа кода проверяет user32.dll на наличие этих функций, он проверяет 32-разрядную версию user32.dll (в C:/Windows/SysWOW64/) вместо той, которую программа фактически будет использовать (64-разрядная версия). в C:/Windows/System32), и эти функции существуют только в 64-битной версии (32-битная версия использует GetWindowLong/SetWindowLong вместо GetWindowLongPtr/SetWindowLongPtr (обратите внимание на часть PTR)).

person Steve Niles    schedule 21.11.2012

Попробуйте следующее:

    [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);
person Jigsore    schedule 30.10.2012
comment
Пробовал и с W, и с A (где-то видел). Ни то, ни другое не работает :С - person Steve Niles; 31.10.2012
comment
Да, ExactSpelling, кажется, не имеет значения - person Steve Niles; 31.10.2012
comment
Моя ошибка, ExactSpelling не нужно, если указано EntryPoint... Я думаю, что это предупреждение нормально, потому что подобные предупреждения появляются при компиляции сборок x64 (предупреждает о Reference Assemblies ) - person Jigsore; 31.10.2012