Отладка DDEML-приложений
Библиотека DDEML позволяет создавать приложения, предназначенные для отладки DDEML-приложений. В частности, такие приложения могут перехватывать вызовы функций обратного вызова DDEML (как для сервера, так и для клиента), следить за использованием идентификаторов строк и данных, за регистрацией сервиса и так далее. Из-за ограниченного объема книги мы не сможем рассказать вам о том, как создавать такие приложения, однако вся необходимая информация есть в документации, которая входит в состав Microsoft SDK for Windows 3.1.
Тем не менее, мы научим вас пользоваться готовым приложением DDESpy, которое поставляется в составе SDK и специально предназначено для отладки DDEML-приложений.
Запустите приложение DDESpy и раскройте меню "Output" (рис. 3.10).
Рис. 3.10. Меню "Output" приложения DDESpy
С помощью этого меню вы можете направить поток отладочной информации в файл (строка "File..."), на отладочный терминал (строка "Debug Terminal" или в окно приложения DDESpy (строка "Screen"). Кроме того, с помощью строки "Clear Screen" вы можете очистить содержимое окна приложения DDESpy от отладочной информации (если она там есть).
В меню "Output" вам надо выбрать строку "File..." и с помощью появившейся на экране диалоговой панели задать путь к файлу, в который будет записана отладочная информация.
Затем раскройте меню "Monitor" (рис. 3.11).
Рис. 3.11. Меню "Monitor" приложения DDESpy
С помощью этого меню вы можете определить состав отладочной информации, отображаемой в окне приложения и сохраняемой в только что указанном вами файле. Отметьте все строки, как на рис. 3.11. Теперь вы сможете получить полную отладочную информацию.
Затем раскройте меню "Track" (рис. 3.12).
Рис. 3.12. Меню "Track" приложения DDESpy
С помощью этого меню вы сможете задать информацию о системе DDEML, отображаемую в отдельных окнах.
Отметьте все строки в меню "Track".
При этом в нижней части экрана монитора появится несколько новых пиктограмм, соответствующих отдельным окнам.
Теперь все готово к отладке.
Запустите приложение DDEMLSR, описанное нами раньше. В главном окне приложения DDESpy появятся текстовые строки описания происходящих событий. Эти строки одновременно записываются в файл, указанный нами ранее. Мы к ним еще вернемся, а пока давайте раскроем пиктограмму "Registered Service". Появится окно, в котором вы сможете увидеть имя сервиса "BMPServer", а также название и идентификатор копии приложения (рис. 3.13).
Рис. 3.13. Список серверов DDEML
Раскройте окно "Active Conversation", в котором отображается информация об активных каналах связи.
В этот момент времени ни один канал связи еще не создан, поэтому окно пустое. Запустите приложение DDEMLCL, предназначенное для совместной работы с приложением DDEMLSR. Оно создаст канал связи, используя сервис "BMPServer" и раздел "BMPFile". Теперь в окне "Active Conversation" есть информация о сервисе, разделе и идентификаторах копий приложений клиента и сервера, создавшего канал связи (рис. 3.14).
Рис. 3.14. Список активных каналов
Итак, канал связи установлен. Раскройте окно "String Handles", отображающее список созданных идентификаторов строк (рис. 3.15).
Рис. 3.15. Список идентификаторов строк
И сервер, и клиент создали каждый по три идентификатора, соответствующих строкам "BMPService, "BMPFile" и "DDEData". В столбце "Count" отображается счетчик использования идентификаторов. В нашем случае он равен 2, так как каждая строка была использована по 2 раза - сервером и клиентом. Для одинаковых строк не создается отдельных идентификаторов, а просто увеличивается счетчик использования.
Сделайте активным окно клиента DDEMLCL и выполните пересылку данных, выбрав из меню "Action" строки "Send Filename" и затем "Get Server Version". Будет выполнена передача данных по каналу связи, причем информация о результате будет записана в отладочный файл.
Закройте приложение DDEMLCL и сделайте активным окно "String Handles". Теперь счетчик использования всех трех идентификаторов строк будет равен 1, так как клиент освободил эти идентификаторы. Однако сервер продолжает их использовать, поэтому идентификаторы не уничтожаются.
Окно "Active Conversation" очистится, так как теперь в системе нет активных каналов связи (если только их не создали какие-либо другие приложения).
Теперь завершите приложение DDEMLSR. Окна "String Handles" и "Registered Service" теперь тоже очистятся, так как все строки уничтожены, а сервис больше не доступен.
Завершите приложение DDESpy и загрузите в любой текстовый редактор файл, содержащий протокол отладки. Мы приведем фрагменты такого файла, полученного в результате выполнения описанных выше манипуляций с приложениями DDEMLSR и DDEMLCL.
Первые три строки появились в результате запуска сервера DDEMLSR. Они содержат сведения о том, что были созданы три идентификатора строк для копии приложения с идентификатором 0x458f. Указано время события (от момента запуска Windows), идентификаторы созданных строк (c0d0, c0d5, c2d8) и содержимое строк.
Task:0x458f,Time:7766779,String Handle Created:c0d0(BMPServer) Task:0x458f,Time:7766779,String Handle Created:c0d5(BMPFile) Task:0x458f,Time:7766834,String Handle Created:c2d8(DDEData)
Далее идут строки, описывающие вызов функции обратного вызова сервера:
Task:0x458f Time:7766834 Callback: Type=Register, fmt=0x0("?"), hConv=0x0, hsz1=0xc0d0("BMPServer") hsz2=0x5c40c0d0("BMPServer:(5c40)"), hData=0x0, dwData1=0x0, dwData2=0x0 return=0x0
Здесь функция обратного вызова была вызвана для выполнения регистрации сервиса "BMPServer". Вы можете определить содержимое всех параметров функции на момент вызова.
В следующем фрагмента отражен факт посылки данных серверу:
Task:0x458f Time:7769470 hwndTo=0x5f24 Message(Posted)=Poke: hwndFrom=0x5e44, lParam=0xc2d82aaf status=2000(fRelease ) fmt=0x1("CF_TEXT") Data= "c:\nicebmp\sky.bmp" Item=0xc2d8("DDEData")
Следом идет обращение к функции обратного вызова:
Task:0x458f Time:7770624 Callback: Type=Poke, fmt=0x1("CF_TEXT"), hConv=0x75f24, hsz1=0xc0d5("BMPFile") hsz2=0xc2d8("DDEData"), hData=0x4537232c, dwData1=0x0, dwData2=0x0 return=0x8000 Input data= "c:\nicebmp\sky.bmp"
А вот запрос данных от сервера:
Task:0x458f Time:7772052 hwndTo=0x5f24 Message(Posted)=Request: hwndFrom=0x5e44, lParam=0xc2d80001 fmt=0x1("CF_TEXT") Item=0xc2d8("DDEData") Task:0x458f Time:7772052 Callback: Type=Request, fmt=0x1("CF_TEXT"), hConv=0x75f24, hsz1=0xc0d5("BMPFile") hsz2=0xc2d8("DDEData"), hData=0x0, dwData1=0x0, dwData2=0x0 return=0x2daf02fc Output data= "DDEML Server v.1.0, (C) Frolov A.V."
В следующем фрагменте листинга выполняется запрос на уничтожение канала связи, после чего управление получает функция обратного вызова:
Task:0x458f Time:7774578 hwndTo=0x5f24 Message(Posted)=Terminate: hwndFrom=0x5e44, lParam=0x0 dFrom=0x5e44, lParam=0x0 Task:0x458f Time:7774688 Callback: Type=Disconnect, fmt=0x0("?"), hConv=0x75f24, hsz1=0x0("") hsz2=0x0(""), hData=0x0, dwData1=0x0, dwData2=0x0 return=0x0
Перед завершением работы сервер должен сообщить системе DDEML, что обеспечиваемый им сервис больше не доступен. Следующий фрагмент листинга отражает процедуру "изъятия" сервиса :
Task:0x458f Time:7776281 Callback: Type=Unregister, fmt=0x0("?"), hConv=0x0, hsz1=0xc0d0("BMPServer") hsz2=0x5c40c0d0("BMPServer:(5c40)"), hData=0x0, dwData1=0x0, dwData2=0x0 return=0x0
Анализируя содержимое протокола отладки, вы можете проследить за тем, чтобы при завершении сервера освобождались все занимаемые им ресурсы, такие как идентификаторы строк и сервис. Вы можете проверить значения параметров функции обратного вызова для всех или отдельных транзакций, проследить формат передаваемых данных и многое другое.