Программирование в среде браузера
- В среде WIN,
- В среде WEB-сервера - ASP.NET2,
- В среде SQL-сервера,
- В среде Офиса,
- В среде Браузера,
- В среде Инсталлера,
- В среде прочих специализированных программ - например программирование плагинов к вот такой моей проге.
- На языке SQL,
- На языке JavaScript в клиентской среде браузера,
- На XSLT/XPATH,
- В среде Integration Services (поддерживается только VB),
- Прочее специализированное программирование, например в дизайнерах отчетных систем.
Прежде всего с браузером можно работать, загрузив браузер ВО ВНУТРЬ своей проги. Примеров такой техники у меня на сайте лежит множество, в том числе SiteChecker - утилита с открытым исходным кодом. В сущности для такого доступа к браузеру надо просто установить ссылку на библиотеку Interop.SHDocVw и поместить на свою форму контрол WebBrowser.
Однако, примерно по аналогии с офисом, можно сделать и НАОБОРОТ - подключить свою собственную прогу ВО ВНУТРЬ работающего браузера. Это можно сделать многими способами способами:
- Adding Toolbar Buttons
- Adding Entries to the Standard Context Menu
- Adding Explorer Bars
- Adding Menu Items
- Назначить свой обработчик MIME-типа - Handling MIME Types in Internet Explorer
- Создать свой собственный протокол и назначить свою прогу обработчиком его - Creating and Using URL Monikers
- Назначить свою прогу обработчиком языка JavaScript или VbScript или создать свой язык и вызывать его со странички.
- Есть миллион прочих способов, например подключение своей проги для определения возможности отображения всплывающих окон.
Разумеется, тут речь идет о подключении своей проги во-внутрь работающего браузера, и о работе подключенной проги КАК WIN-приложения а не о работе в клиентской среде браузера на скриптовом языке. Кстати, со страниц тоже возможно работать в среде WIN-приложений по крайней мере двумя способами:
- Запустив HTA-приложение - HTML Applications
- Запустив на странице свой OBJECT.
В практическом плане в браузере как правило подключены десятки сторонних программ:
Прежде всего надо понимать, что наша кнопка будет непосредственно взаимодействать с внутренними обьектами браузера. Если этого не надо, а надо просто выхвать стронний EXE-файл, то это делается совершенно иначе - оснасткой GPEDIT.MSC.
Но мы сделаем свою NET-прогу, которая будет работать именно внутри среды браузера, имея доступ ко всем его обьектам - тулбару, документу и проч. Для начала нас ждет неожиданность - стандартные размеры иконок не подходят. Однако, я уже подготовил иконки специальных размеров, сгрузить которые можно ОТСЮДА.
В MSDN описано, как именно это сделать. Вот собственно это скудное описание:
Вся сложность в том, что нам придется заниматься COM-программированием в среде NET. Вообще эта задача не раз освещена у меня на сайте, но тут мы посмотрим все это в конкретике браузера. Итак, создадим COM-объект, который будет вызываться нашей кнопкой:
- Создаем простой DLL-проект - который мы сделаем COM-обьектом.
- Указываем студии, чтобы она сама прогоняла RegSrv32 и регистрировала наш COM-обьект.
- Опеределим для нашего COM-объекта новый номер.
- Чтобы получить доступ к документу внутри браузера - как указано в MSDN - нам АБСОЛЮТНО ДОСТАТОЧНО в своей проге переопределить интерфейс IObjectWithSite::SetSite.
- Находим номер этого интерфейса в системе и его описание.
- Все что нам необходимо - это импортировать в свою прогу описание этого интерфейса:
- Как видите, по интерфейсу {FC4801A3-2BA9-11CF-A229-00AA003D7352} никаких сложных объектов не передается, поэтому все просто. Хотя у VS2005 крыша сьехала полностью и подсвечивать этот текст она стала красным цветом почему-то. А вот если мы захотим получить ПОЛНЫЙ доступ ко всем средствам браузера, то тогда нас ждут настоящие сложности. Ибо в интерфейсе IOleCommandTarget - {B722BCCB-4E68-101B-A2BC-00AA00404770} (который позволяет получить доступ к тулбару браузера) - все гораздо сложнее. Там передается два сложных обьекта и потребуется виртуозное знание C++, чтобы описание этих обьектов составить в NET.
- Теперь, когда определения этих COM-интерфейсов уже есть в нашей NET-проге, нам достаточно начать свой класс, указав, что он реализует эти интерфейсы и тут VS2005 отрабатывает на удивление безошибочно. Тыкнув ENTER после имени класса - мы получим его полное определение.
- Теперь собственно готовим наш класс либо в самом простом виде, либо уже в более сложном виде - ведь чтобы вытянуть документ из оьекта браузера, котрый нам передается по интерфейсу IObjectWithSite нам потребуется ссылка на NET-обертку с определением браузера. Если ссылка на Враппер браузера уже есть, то мы уже сможем работать напрямую с обьектами браузера, но чтобы работать с HTML, нам потребуется еще ссылка на Враппер к MSHTML-библиотеке. Но само по себе приведение типов тут нетривиально и требует низкоуровневого обращения к встроенному интерфейсу, обеспечивающего работу COM - QueryService. Все это вы можете увидеть в том тексте, который мне удалось родить...
- Итак, компилируем наш объект, не забываем его записать в GAC и проверяем наш созданный COM-объект и как он зарегестрировался.
- Теперь регистрируем наш COM-обьект в качестве внутренней части браузера - его расширения. Сделать это можно просто прогоняя скрипт регистрации или добавив его прямо в проект студии. Обратите внимание, что тут необходимо правильно указать пути к иконкам. Кстати, как видите, первые прогоны этой проги я делал на виртуальной машине. Так рекуомендуется поступать всегда - когда точно неизвестно что будет после встраивания вашей проги в виндузню...
Собственно текст регистрации (с моими путями иконок выглядит вот так):
Windows Registry Editor Version 5.00 [HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\Extensions\{E755B4B7-F72C-4946-A84D-87ACF80934B0}] "Default Visible"="Yes" "ButtonText"="MyButton1" "CLSID"="{1FBA04EE-3024-11d2-8F1F-0000F87ABD16}" "ClsidExtension"="{6245A388-C461-4116-BC59-24F5F0C036A4}" "Icon"="F:\\Visual Studio 2005\\Projects\\IE7TollbarButton\\IE7TollbarButton\\Resources\\3c.ico" "HotIcon"="F:\\Visual Studio 2005\\Projects\\IE7TollbarButton\\IE7TollbarButton\\Resources\\3g.ico"
А текст нашей проги, о которой мы так долго говорим - так:
00001: <ComClass("6245A388-C461-4116-BC59-24F5F0C036A4")> _ 00002: Public Class Button1 00003: Implements IOleCommandTarget, IObjectWithSite 00004: 00005: Public Sub Exec(ByRef pguidCmdGroup As System.Guid, ByVal nCmdId As UInteger, ByVal nCmdExecOpt As UInteger, ByRef pvaIn As Object, ByRef pvaOut As Object) Implements IOleCommandTarget.Exec 00006: My.Computer.Clipboard.SetText("Exec") 00007: End Sub 00008: 00009: Public Sub QueryStatus(ByRef pguidCmdGroup As System.Guid, ByVal cCmds As UInteger, ByVal prgCmds() As OLECMD, ByRef pCmdText As OLECMDTEXT) Implements IOleCommandTarget.QueryStatus 00010: My.Computer.Clipboard.SetText("QueryStatus") 00011: End Sub 00012: 00013: Public Sub SetSite(ByVal pUnkSite As Object) Implements IObjectWithSite.SetSite 00014: Try 00015: My.Computer.Clipboard.SetText(pUnkSite.ToString) 00016: Dim X As IInputObjectSite = TryCast(pUnkSite, IInputObjectSite) 00017: Dim Y As _IServiceProvider = TryCast(X, _IServiceProvider) 00018: Dim IE7 As Object 00019: Y.QueryService(New Guid("{0002DF05-0000-0000-C000-000000000046}"), _ 00020: New Guid("{00000000-0000-0000-C000-000000000046}"), IE7) 00021: Dim HTMLDocument As mshtml.HTMLDocumentClass 00022: HTMLDocument = TryCast(IE7, SHDocVw.WebBrowser).Document 00023: My.Computer.Clipboard.SetText(HTMLDocument.documentElement.outerHTML) 00024: Catch ex As Exception 00025: My.Computer.Clipboard.SetText(ex.Message) 00026: End Try 00027: 00028: End Sub 00029: End Class 00030: 00031: <Runtime.InteropServices.ComImport(), Runtime.InteropServices.Guid("6d5140c1-7436-11ce-8034-00aa006009fa"), Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)> _ 00032: Public Interface _IServiceProvider 00033: Sub QueryService(ByRef guid As Guid, ByRef riid As Guid, <Runtime.InteropServices.Out(), Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.Interface)> ByRef Obj As Object) 00034: End Interface 00035: 00036: <Runtime.InteropServices.ComImport(), Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown), Runtime.InteropServices.Guid("f1db8392-7331-11d0-8c99-00a0c92dbfe8")> _ 00037: Public Interface IInputObjectSite 00038: <Runtime.InteropServices.PreserveSig()> _ 00039: Function OnFocusChangeIS(<Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.IUnknown)> ByVal punkObj As Object, ByVal fSetFocus As Integer) As Integer 00040: End Interface 00041: 00042: <Runtime.InteropServices.ComImport(), _ 00043: Runtime.InteropServices.Guid("B722BCCB-4E68-101B-A2BC-00AA00404770"), _ 00044: Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)> _ 00045: Public Interface IOleCommandTarget 00046: 00047: Sub QueryStatus(ByRef pguidCmdGroup As Guid, ByVal cCmds As UInt32, _ 00048: <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.LPArray, _ 00049: SizeParamIndex:=1)> ByVal prgCmds() As OLECMD, ByRef pCmdText As OLECMDTEXT) 00050: 00051: Sub Exec(ByRef pguidCmdGroup As Guid, ByVal nCmdId As UInt32, ByVal nCmdExecOpt As UInt32, _ 00052: ByRef pvaIn As Object, ByRef pvaOut As Object) 00053: 00054: End Interface 00055: 00056: <Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential, _ 00057: CharSet:=Runtime.InteropServices.CharSet.Unicode)> _ 00058: Public Structure OLECMDTEXT 00059: Public cmdtextf As UInt32 00060: Public cwActual As UInt32 00061: Public cwBuf As UInt32 00062: <Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=100)> _ 00063: Public rgwz As Char 00064: End Structure 00065: 00066: <Runtime.InteropServices.StructLayout(Runtime.InteropServices.LayoutKind.Sequential)> _ 00067: Public Structure OLECMD 00068: Public cmdID As UInt32 00069: Public cmdf As UInt32 00070: End Structure 00071: 00072: <Runtime.InteropServices.ComImport(), _ 00073: Runtime.InteropServices.Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352"), _ 00074: Runtime.InteropServices.InterfaceType(Runtime.InteropServices.ComInterfaceType.InterfaceIsIUnknown)> _ 00075: Public Interface IObjectWithSite 00076: Sub SetSite(<Runtime.InteropServices.[In](), _ 00077: Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.IUnknown)> ByVal pUnkSite As Object) 00078: End Interface
- После выполнения регистрационного скрипта наша наконец кнопка появляется в перечне его расширений на панели браузера:
- И теперь если вы правильно подключитесь к процессу браузера - произойдет чудо, о котором вы мечтали:
- Теперь вы УЖЕ можете проанализивать любым нужным вам образом HTML, что-то сбросить в базу и тд, но пока не можете сделать MSGBOX из среды браузера. Это отдельная техника и дочитав до этого места вы уже достаточно погрузились в тематику программирования в среде браузера, чтобы Асилить работу с Browser Helper Objects - именно так называется оконная форма, работающая внутри среды браузера. Ниже приводятся ссылки для более полного погружения в тематику работы с BHO.
- Browser Helper Objects: The Browser the Way You Want It.
- Building Browser Helper Objects with Visual Studio 2005
- Band Objects - .NET 2.0 Redux
- HOW TO: Invoke the Find, View Source, and Options Dialog Boxes for the WebBrowser Control from Visual Basic .NET
<SITEMAP> <MVC> <ASP> <NET> <DATA> <KIOSK> <FLEX> <SQL> <NOTES> <LINUX> <MONO> <FREEWARE> <DOCS> <ENG> <CHAT ME> <ABOUT ME> < THANKS ME> |