Управление ArcView 3.2 с помощью Avenue комманд из .NET (C#) кода по протоколу DDE (Dynamic Data Exchange)

by Dmitry [dimaka] Pavlov 21. July 2010 03:12

Описание задачи

Я работаю над проектом, часть которого заключается в обеспечении взаимодействия между ГИС (ГеоИнформационная Система) приложением ArcView 3.2 и .NET приложением (WinForms, C#). Необходимо иметь возможность получать сведения о состоянии проекта ArcView (например, «ловить» события, когда пользователь включает и выключает видимость слоев карты в ArcView). Кроме того, нужно иметь возможность эти действия (включить/выключить) совершать программно – скажем, с помощью CheckBox-а в .NET приложении.

В качестве исходного материала у меня имеется старое приложение, написанное на Delphi, которое использует механизм DDE (Dynamic Data Exchange) для связи с ArcView проектом. Через этот канал связи Delphi приложение вызывает Avenue скрипты внутри ArcView проекта, которые совершают необходимые действия внутри ГИС.

Проблемы

После изучения вопроса стало известно, что ГИС система ArcView версии 3.2:

  • Не поддерживает работу из .NET через ArcObjects (который позволяет работать в более новыми версиями ГИС от компании ESRI из управляемого C# кода)
  • Автоматизируется только с помощью встроенного скриптового языка Avenue.
  • Единственный способ связаться с ним снаружи программно – DDE (не считая конечно систем-«кнопконажимателей» типа AutoIt, которые, впрочем, не подходят, поскольку не могут принимать события обратно от ГИС приожения)
  • Портировать сам ГИС проект (карту) под новую версию ArcView (AcrMap, ArcGIS) недопустимо для заказчика.
  • Протокол DDE (появившийся еще в Windows 3.0) не изменялся примерно 90х годов и в настоящее время не поддерживается в .NET.
  • Исходный код Delphi приложения мало чем может помочь.
  • Личного опыта работы с используемыми технологиями – Delphi, Avenue, DDE нет.

Пути решения

После анализа ситуации я сделал следующие выводы относительно пути решения:

  • Исходный код старого Delphi проекта не нужен, поскольку в новом проекте приложение управляющее ГИС системой полностью реализовано на .NET и отличается от исходного – то есть переделано с нуля.
  • Логика Avenue скриптов (внутри ГИС проекта) не меняется и мне необходимо только найти способ их вызвать. Разбираться с языком Avenue не нужно и писать на нем что-то – тоже.
  • Мне придется использовать DDE протокол.  Для чего нужно понять, как устроена эта технология и найти способ работать с ним в среде .NET.

.NET и DDE (Dynamic Data Exchange)

Историческая справка (источник):

«Dynamic Data Exchange (DDE) была одной из первых технологий, которая позволяет обмениваться информацией между приложениями в Visual Basic 3.0. В последующих версиях Visual Basic протокол DDE был заменен OLE-автоматизацией, но продолжал поддерживаться для обратной совместимости до версии Visual Basic 6.0. С появлением Visual Basic. NET, DDE больше не поддерживается.» 

Протокол DDE подразумевает клиент-серверную архитектуру. В моем случае ArcView 3.2 – это сервер, а клиентом является .NET приложение. DDE использует иерархию из трех имен – SERVICE, TOPIC и ITEM. DDE CONVERSATION (взаимодействие) устанавливается с помощью указания названий SERVICE и TOPIC в виде пары, которая определяет нак называемый CHANNEL. ITEM используется для передачи конкретных данных или команд, запрашиваемых клиентом после установки взаимодействия. Подробнее рассказывается в Dynamic Data Exchange (DDE) and NetDDE FAQ.

Обмен данными между приложениями происходит посредством транзакций, и управляется этот процесс специальным расширением Windows - динамической библиотекой DDEML, которая представляет собой 32-разрядную библиотеку платформы Win32.  Функции платформы Win32 не могут быть вызваны непосредственно из приложения .NET. Доступ к таким функциям в .NET осуществялется с помощью атрибута DllImportAttribute. Пример обращения к функции Win32 для вызова системного диалога MessageBox:

// Use DllImport to import the Win32 MessageBox function.
[DllImport("user32.dll", CharSet = CharSet.Unicode)]
public static extern int MessageBox(IntPtr hWnd, String text, String caption, uint type);

Для автоматического создания подобной «заглушки» в среде Visual Studio (2003, 2005 и 2008) можно использовать бесплатный плагин PInvoke Visual Studio Add-in от компании Red Gate, который поможет найти готовую заглушку в хранилище – http://www.pinvoke.net/.

Нетрудно догадаться, что попытки «обернуть» нативную динамическую Win 32 библиотеку DDEML уже предпринимались и имеются наработки, среди которых – open source проект NDde (скачать) в сообществе CodePlex. Активной разработки на проекте в настоящее время уже не ведется, поскольку он по сути завершен. Имеется документация по NDde в виде файла NDde.xml, в котором имеется описание классов, методов и некоторые примеры использования. Посмотреть ее в более удобном виде можно с помощью XML Documentation Comment Viewer.

Итак для работы с ArcView 3.2 по протоколу DDE необходимо подключить к проекту в Visual Studio библиотеку NDde (файл NDde.dll). Для подключения к DDE серверу (ArcView) нам нужен класс NDde.Client.DdeClient. Вот пример кода запускающий ArcView:

DdeClient ddeClient = new DdeClient("ArcView", "System", _synchronizingObject);
ddeClient.Connect();

С помощью упомянутого XML Documentation Comment Viewer можно посмотреть пример управления DDE клиента всеми доступными способами (синхронно и асинхронно):

  • Synchronous Execute Operation
  • Synchronous Poke Operation
  • Syncronous Request Operation
  • Asynchronous Execute Operation
  • Asynchronous Poke Operation
  • Asynchronous Request Operation
  • Advise Loop

.NET(C#) – Avenue / DDE – ArcView 3.2

Для моих целей было достаточно синхронных вызовов методов Execute (для отправки Avenue команды в ArcView):

ddeClient.Execute(command, RequestTimeout);

и Request (для запроса данных из ArcView опять же спомощью команды Avenue):

byte[] data = ddeClient.Request(command, 1, RequestTimeout);
string result = Encoding.Default.GetString(data).TrimEnd('\0');

Основная проблема приработе с DDE заключается в ограничении возможного размера передаваемой команды в ArcView и возращаемого значения из него.

NOTE: Максимальная длина текста сообщения или ответа – 255 символов.

Это ограничение заставляет избегать длинных Avenue скриптов при отправке команды, заменяя их на несколько последовательных команд. Например для получения списка объектов Doc допустимо использовать следующий способ, получив сначала количество документов, а затем в цикле получив имя каждого документа:

List<string> docNames = new List<string>();
int count = int.Parse(ddeClient.Request("av.GetProject.GetDocs.Count.AsString"), 1, 1000);
for (int i = 0; i < count; i++)
{
  string command = string.Format("av.GetProject.GetDocs.Get({0}).AsString", i);
  docNames.Add(ddeClient.Request(command, 1, 1000));
}

Подробная документация по объектной модели ArcView 3.2 и языку Avenue доступна во встроенной справочной системе этой ГИС, а также в этом документе – Programming in ArcView 3.x GIS using Avenue [PDF]

Ссылки по теме:

Tags:

.NET | Coding | GIS | Tips | Tricks | по-русски

Comments

Add comment




  Country flag

biuquote
  • Comment
  • Preview
Loading



Calendar

<<  September 2010  >>
MoTuWeThFrSaSu
303112345
6789101112
13141516171819
20212223242526
27282930123
45678910

View posts in large calendar