Все, кто использовал P/Invoke Windows API, знают длинный список объявлений статических функций с атрибутами как
[DllImport ("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
Объявление структур, скопированных с заголовков Windows как WinNT.h или с веб-сайтов как www.pinvoke.net, занимает также много места в наших программах.
Почему все мы должны провести наше время для этого? Почему Microsoft не дает нам простой способ включать строку как в старые неуправляемые программы
#include
и мы были бы, имеют доступ к статическому классу Native
со всеми или большинством функций Windows и структур внутри?
ОБНОВЛЕННЫЙ на основе некоторых ответов:
Это Вы будете честны с собой, какая часть Ваших программ.NET запускающий не находится под Windows? 5%? 1%? Если Вы используете WMI, Процесс, Реестр или ServiceProcess. Классы ServiceBase и т.д. в.NET являются Вашей программой, таким образом “независимой от платформы” и более “совместимой” не при использовании встроенного API? Имеет Thread.ApartmentState
везде смысл из Windows?
Использование SafeHandle
или try {…} finally
имеет требуемую причину. Я был бы рад иметь стандартное определение Встроенного API в любой из этих форм.
Я знаю что некоторые структуры в windows.h
имейте различные версии 32/64 или XP/Vista и т.д. Я думаю, что было бы достаточно иметь также другую версию Собственных структур как MIB_IPADDRROW_XP
и MIB_IPADDRROW_W2K
или IMAGE_NT_HEADERS32
и IMAGE_NT_HEADERS64
(см. те же имена в заголовках окон).
Каждый должен управляемых классов и методов.NET использования причины, если существует, существуют. Жаль, но к реализации некоторых, из которых наиболее мощные функции Windows прибывают в управляемую.NET слишком поздно и много из, там получают доступ до настоящего времени только в неуправляемом мире. 10-летний назад на одной из первой конференции Microsoft о.NET я спросил о своей пользе Файлы С отображенной памятью. Только.NET 4 имеет теперь MemoryMappedFile
класс реализовал (см. http://blogs.msdn.com/salvapatuel/archive/2009/06/08/working-with-memory-mapped-files-in-net-4.aspx). Те же проблемы существуют постоянно, если Вы пишете утилиты для административной цели. Например, вводный файл с CreateFile
и Флаг FILE_FLAG_BACKUP_SEMANTICS
или RegCreateKeyEx
с REG_OPTION_BACKUP_RESTORE
или REG_OPTION_CREATE_LINK
. Жесткие ссылки и Соединения (см. http://msdn.microsoft.com/en-us/library/aa365006 (v=VS.85) .aspx) являются следующими примерами. Еще один пример: работа с Объектами Задания вместо Процесса (см. http://msdn.microsoft.com/en-us/library/ms684161 (По сравнению с 85) .aspx и http://www.microsoft.com/msj/0399/jobkernelobj/jobkernelobj.aspx). Если Вы хотите запустить процесс и ожидать только в этом процессе, но также и недо всего, что это - дочерние процессы, заканчиваются, задание очень полезно. Можно использовать CreateJobObject
и AssignProcessToJobObject
и затем используйте TerminateJobObject
или WaitHandle
как версия.NET (WaitForSingleObject
).
Только в.NET 4.0 System.IntPtr
und System.UIntPtr
поддержки классов Add
и Subtract
методы.
Я могу продолжить примеры, но я надеюсь, что Вы понимаете то, что я имею в виду. Таким образом, я хочу записать программу в.NET из-за большого количества преимуществ, но я могу сделать это не всегда без использования встроенного API. Кроме того, иногда существует требование клиента на язык реализации программного обеспечения, и я выбираю необходимый путь.
ОБНОВЛЕННЫЙ 2: Microsoft улучшила совместимость с COM в.NET 4.0, но не с подобным C Windows API. Я вижу, что некоторые пути к делают работу с P/Invoke легче. Какой способ сделать это Вы видите? Я предлагаю три направления, которые я вижу:
Я уверен, что существуют больше способов сделать легче для разработчика использование собственного Windows API. Другие предложения приветствуются.
Одна из то тос мнений заключается в том, что PInvoke является костылью совместимости. Вы должны использовать 100% библиотеки и функции .Net, а не «устаревшие» вызовы Win32.
Я не знаю, почему MSFT приняла такое решение, но вот несколько причин, по которым я считаю это решение правильным:
Заголовочные файлы Windows SDK (windows.h
и др.) широко используют условную компиляцию, основанную на таких вещах, как целевая версия Windows и архитектура, чтобы определить, какие функции будут объявлены и как будут размещены структуры данных. Все это невозможно ни в одном из языков .NET, поскольку они ориентированы не на версии Windows, а на версии фреймворка, и получаемые двоичные файлы могут работать на 32- и 64-битных архитектурах во многих версиях и редакциях Windows
Многие вызовы API Windows и структуры данных не могут быть полностью выражены через P/Invoke. Один из них сразу приходит на ум - DeviceIoControl
. Другим примером являются многочисленные так называемые структуры "переменной длины", содержащие массивы с неизвестным (на момент компиляции) количеством элементов
P/Invoke эволюционировал с течением времени, особенно в способе представления хэндлов (IntPtr
в ранних версиях фреймворка; SafeHandle
классы позже); Если бы MSFT поддерживала один статический класс с большинством или всеми функциями Win32 API, они также были бы обязаны поддерживать совместимость с предыдущими версиями этого класса, привязываясь к тому, как P/Invoke был реализован изначально
Даже сама MSFT не поддерживает ни одного Native
класса во внутренностях фреймворка. Теперь, когда исходный код .NET Framework 3.5 доступен, вы можете сами убедиться в том, насколько несистемно используется P/Invoke, даже в рамках той самой среды, которую мы должны использовать вместо P/Invoke. Например, System.Net и System.IO имеют свои собственные отдельные декларации P/Invoke.
Фреймворк .NET Framework и управляемый код с самого начала разрабатывались как новый способ создания программного обеспечения для Windows. Насколько глупо было бы предоставлять этот новый способ и в то же время требовать использования старого способа для многих задач?
Я говорю это как человек, который широко использует P/Invoke для таких вещей, как IOCTLs и операции ввода/вывода на уровне тома. Чем больше я использую P/Invoke, тем больше я его ненавижу. С ним трудно работать, он склонен к ошибкам и медлителен. Каждый раз, когда я использую P/Invoke, это происходит потому, что я исчерпал все другие варианты. Если вы столкнулись с проблемой, решение которой требует большого количества прямых вызовов Windows API, то, скорее всего:
a) Вам не хватает какой-то функции в Framework, которая сделает то, что вы хотите
b) Вы используете неправильный подход к решению проблемы, особенно если вы привыкли к родному Windows API и все еще мыслите в этих терминах
c) Вам следует писать низкоуровневый код на C++/CLI и предоставлять громоздкие интерфейсы более высокого уровня для потребления вашим .NET-кодом
.Я уверен, что эта мысль приходила вам в голову, но я думаю, что должен быть проект с открытым исходным кодом, который сделал бы это. Вместо того, чтобы ждать, пока Microsoft сделает это, мы можем собрать всю информацию, которую имеют люди, которые фактически использовали P / Invoke изо дня в день, чтобы другим не пришлось изобретать велосипед.
Продолжайте собирать API по мере того, как люди используют их, они нуждаются в них.
Есть добровольцы? :)
pinvoke.net не в счет - его нелегко подключить к вашему решению.