Опубликован: 11.09.2006 | Уровень: специалист | Доступ: платный
Лекция 5:

Использование библиотек кода в windows-формах

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >
Аннотация: Службы Platform Invoke. Службы COM Interoperability. Работа службы Platform Invoke. Запуск функций WinAPI. Получение имени пользователя. Библиотека secur32.dll. Диалоговые окна. Библиотека user32.dll. Динамик компьютера. Библиотека Kernel32.dll. Анимация формы. Завершение работы Windows. Класс String Builder. Библиотеки user32.dll и GDI32. Вызов COM компонентов из управляемого кода. Генерирование сборок взаимодействия. Утилита tlbimp.exe

Для работы с данной лекцией используйте примеры.

Взаимодействие управляемого и неуправляемого кода

При создании приложений, использующих платформу Microsoft .NET, возникает задача применения в собственных проектах уже готовых библиотек кода, написанных на других языках. Сжатые сроки разработки и уже имеющиеся программные блоки не позволяют отказаться от готовых решений, поэтому их приходится использовать, встраивая в структуру собственных проектов.

Код, выполняющийся под управлением среды выполнения (в случае платформы .NET — среды Common Language Runtime), называется управляемым. Напротив, код, запускаемый не под управлением среды, называется неуправляемым. Примером неуправляемого кода могут служить COM-компоненты, Microsoft ActiveX интерфейсы и функции API Win32.

Microsoft .NET Framework позволяет взаимодействовать с COM-компонентами, COM+-службами, внешними типами библиотек и разными службами операционной системы. Перехват исключений различается в управляемом и неуправляемом коде. Платформа .NET Framework предлагает две службы взаимодействия управляемого кода с неуправляемым — Platform Invoke и COM interoperability, которые используют реальные возможности проекта.

Службы Platform Invoke

Службы Platform Invoke позволяют управляемому коду запускать функции неуправляемого кода, которые находятся в файлах библиотек динамической компоновки (DLL). Эти службы предоставляют механизмы обнаружения и запуска неуправляемых функций и преобразование типов данных входящих и исходящих аргументов функции. Когда управляемый код запускает функцию неуправляемого кода, локализованную в DLL-файле, службы Platform Invoke находят этот DLL файл, загружают его в оперативную память и находят адрес функции в памяти. После этого службы передают входящие аргументы функции в стек, преобразовывают данные, которые необходимо перевести, эмулируют сборку мусора и передают управление по адресу неуправляемой функции в памяти.

Службы COM Interoperability

Объектная модель COM (Common Object Model) компонентов имеет некоторые существенные отличия от объектной модели компонентов .NET Framework.

  • Управление жизненным циклом объектов. Клиенты СОМ-объектов сами управляют этим циклом, среда CLR платформы .NET берет эту задачу на себя.
  • Обращение к службам и объектам. Клиенты COM-объектов узнают о функциональности службы путем опроса ее интерфейса, клиенты .NET-объектов могут получить описание функциональности, используя пространство имен Reflection.
  • Среда CLR перемещает объекты в памяти для улучшения производительности, обновляя ссылки этих объектов. Клиенты COM имеют постоянную ссылку на ячейки памяти, не изменяющуюся в течение всей жизни объекта.

Для преодоления этих различий CLR предлагает классы-оболочки, которые позволяют управляемым и неуправляемым клиентам думать, что они работают с объектами той же среды, что и они сами. Когда управляемый клиент вызывает неуправляемый метод, CLR создает временную оболочку RCW (Runtime Callable Wrapper). RCW абстрагирует различия между управляемым и неуправляемым кодом. CLR также создает оболочку CCW (COM Callable Wrapper) для обращения процесса, которая позволяет COM-объектам запускать методы .NET-объектов.

Обзор механизма преобразования

Механизм преобразования определяет, какие типы данных должны быть переданы в метод и возвращены методом из управляемого в неуправляемый код и наоборот. Большинство типов данных имеют свои аналоги как в управляемом, так и в неуправляемом коде. Они не нуждаются в конвертировании при передаче из одной среды в другую. В пространстве имен System такими типами данных являются следующие:

  • System.Byte
  • System.SByte
  • System.Int16
  • System.UInt16
  • System.Int32
  • System.UInt32
  • System.Int64
  • System.IntPtr
  • System.UintPtr

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

Таблица 5.1. Конвертирование типов данных
Тип данных Тип при конвертировании
System.Array C-style или SAFEARRAY
System.Boolean 1-, 2- или 4-битовое значение со значением true как 1 или –1
System.Char Символ кодировки ANSI или Unicode
System.Class Интерфейс class
System.Object Различные интерфейсы
System.Mdarray C-style или SAFEARRAY
System.String Строка с завершающим нулем (null-terminated string) или BSTR
System.Valuetype Структура
System.Szarray C-style или SAFEARRAY

В большинстве случаев стандартные RCW и CCW, сгенерированные средой выполнения, предоставляют соответствующее преобразование типов между компонентами COM и .NET Framework. Используя атрибуты, вы можете настроить перевод из одного типа в другой.

Работа службы Platform Invoke. Запуск функций WinAPI

Наиболее часто служба Platform Invoke применяется для запуска функций WinAPI, находящихся в файлах dll. Когда служба вызывает функцию, совершаются следующие операции:

  • обнаружение необходимой библиотеки;
  • загрузка найденной библиотеки в оперативную память;
  • обнаружение адреса библиотеки в памяти и передача аргументов функции, с их преобразованием при необходимости;
  • после этого Platform Invoke передает управление неуправляемой функции и ждет завершения.

Для подключения функции необходимо представить адрес библиотеки и данные о функции: название, входящие и исходящие аргументы.

Windows API — это набор функций, входящий в состав семейства операционной системы Microsoft Windows. Преимуществом использования этих функций является то, что они уже полностью готовы и не приходится тратить время на реализацию подобной функциональности. Однако с ними тяжело работать — в частности, довольно сложно отлавливать исключения, возникающие в работе приложения.

Первым шагом в запуске неуправляемой функции является объявление функции. Функция должна быть статической (static) и внешней (extern). Далее следует импорт библиотеки, содержащей эту функцию. Импортировать библиотеку нужно, используя атрибут DllImport, который находится в пространстве имен System.Runtime.InteropServices. Атрибут DllImport нуждается в названии библиотеки и может принимать один из параметров, указанных в таблице 5.2:

Таблица 5.2. Некоторые параметры атрибута DllImport
Аргумент Описание
EntryPoint Указывает название функции. Если название метода совпадает с названием неуправляемой функции, то этот аргумент ставить необязательно
CharSet Указывает кодировку строковых значений. Значением по умолчанию является ANSI
ExactSpelling Предотвращает изменение точки входа (entry point) при изменении кодировки. Если значение аргумента CharSet установлено в Auto, то значение по умолчанию — true, в противном случае — false
CallingConvention Указывает тип конвертирования аргументов, передаваемых в функцию. Значением по умолчанию является WinAPI
PreserveSig Указывает, что сигнатура управляемого метода не должна трансформироваться в сигнатуру неуправляемого метода, который возвращает значение типа HRESULT и может иметь дополнительные аргументы в качестве возвращаемых значений Значением по умолчанию является true (сигнатура не должна трансформироваться).
SetLastError Указывает возможность использования метода GetLastError для обработки ошибок при выполнении неуправляемого метода. Значением по умолчанию является false

Аргументы, которые принадлежат к простым типам данных, такие как byte или int, Platform Invoke автоматически преобразовывает в соответствующие типы в неуправляемой платформе. В таблице 5.3 приводится соответствие типов данных в функциях WinAPI и библиотеки .NET Framework.

Таблица 5.3.
Тип данных в неуправляемом коде Тип данных в .NET Framework (C#)
HANDLE Int
BYTE Byte
SHORT Short
WORD Ushort
INT Int
UINT Uint
LONG Int
ULONG Uint
BOOLEAN Int
CHAR Char
LPSTR (и большинство строковых типов данных) String для входящих аргументов, StringBuilder для двусторонних аргументов
FLOAT Float
DOUBLE double

При указании библиотеки не нужно указывать путь до нее. CLR ищет библиотеку в каталоге приложения, затем в подкаталогах, в папке Windows и папке Window\System32. При указании адреса библиотеки могут возникнуть исключения — CLR проверяет только его. Например, если был указан адрес "C:\Windos\system32\someDll.dl", а у пользователя операционная система располагается на диске D — приложение работать не будет. При использовании функций WinAPI сами файлы библиотек не нужно включать в проект.

< Лекция 4 || Лекция 5: 123456 || Лекция 6 >
Елена Дьяконова
Елена Дьяконова

При нажатии на Сумма в примере ArbitraryMethod из Лекция 7, VS 2013 выдается ошибка: 

Необработанное исключение типа "System.InvalidOperationException" в System.Windows.Forms.dll

Дополнительные сведения: Недопустимая операция в нескольких потоках: попытка доступа к элементу управления "lblResult" не из того потока, в котором он был создан.

Затем:

Необработанное исключение типа "System.InvalidOperationException" в mscorlib.dll

Дополнительные сведения: Для каждой асинхронной операции метод EndInvoke может вызываться только один раз.

Александр Сороколет
Александр Сороколет

Свойство WindowState формы blank Maximized. Не открывается почемуто на всё окно, а вот если последующую форму бланк открыть уже на макс открывается :-/

Анатолий Федоров
Анатолий Федоров
Россия, Москва, Московский государственный университет им. М. В. Ломоносова, 1989