Готовые решения и полезные коды на Visual Basic .NET (Часть-1) - Visual Basic .NET - Ответ 7570745

Готовые решения и полезные коды на Visual Basic .NET (Часть-1) - Visual Basic .NET - Ответ 7570745

05.05.2015, 09:10.

Показов

544833.

Ответов

250

Ответ

Расширение для Internet Explorer

В общем случае, расширения к браузерам - это программы, которые, будучи установленными в браузер, могут как-то влиять на его функционал.

Прежде всего, это

перехват и изменение HTML-кода страниц, просматриваемых в браузере

, далее - различные изменения в интерфейсе

Как устроены расширения в браузерах и как они устроены в IE?

В нормальных браузерах (Chrome, Firefox, Opera) логика расширений пишется на JS, интерфейс (например, тулбары) - на HTML+CSS. При этом используются особые API данного браузера.

Создание расширений к этим браузерам подробно описано

в моей старой статье

В IE все

через ж

кардинально отличается. Расширение к IE (так называемый Browser Helper Object) - это DLL. Написать эту DLL, в принципе, можно на любом компилируемом языке, и VB.NET не исключение. Естественно, DLL будет требовать .NET Framework и сможет использовать любые классы .NET, как и обычная библиотека классов .NET.

Чтобы иметь доступ к IE, эта DLL должна содержать COM-класс, унаследованный от стандартного COM-интерфейса IObjectWithSite, и содержащий имплементации определенных его методов - GetSite и SetSite.

В методе SetSite мы получаем объект браузера, который можем привести к типу WebBrowser (не к обычному System.Windows.Forms.WebBrowser, но к похожему на него SHDocVw.WebBrowser). Далее с этим WebBrowser можно взаимодействовать, как будто бы мы его сами создали в своем приложении.

Чтобы библиотека работала, ее еще сперва надо зарегистрировать как COM-сборку (

нужны права админа

). И прописать в особой ветке реестра, иначе IE о ней не узнает. Но обо все по порядку.

Предупреждение

Объем дальнейшей статьи вас "приятно" удивит, особенно если ранее писали расширения для нормальных браузерах.

Помимо того, что в IE все так долго и нудно, он еще и не умеет толком сообщать о различных ошибках, как мы привыкли видеть это в .NET и в норм браузерах. Если вы что-то сделаете не так, то в лучшем случае расширение просто не запустится или не сработает, а в худшем - все это убожество тупо упадет с окошком "Прекращена работа программы".

Не занимайтесь профессиональной разработкой расширений (фриланс и т.д.), пока не приобретете должный опыт в COM вообще и в BHO в частности.

На фрилансе не стесняйтесь брать хорошие бабки (тысячи, а то и десятки тысяч руб), а также дедик, если у вас мало компов для тестирования. И сроки тоже должны быть большими. Месяц для новичка в BHO, 1-2 недели для профи.

Короче -

IE - это надолго!

Создание DLL

1. Запустите Visual Studio. Создайте проект типа "Библиотека классов". Назовите его, скажем, MyFirstBHO.

2. Сперва нужно "импортировать" стандартный интерфейс IObjectWithSite. Для этого файл Class1.vb переименуйте в IObjectWithSite.vb и замените его содержимое на такой код:

VB.NETВыделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14

Imports System.Runtime.InteropServices
 
<ComVisible(True), _
InterfaceType(ComInterfaceType.InterfaceIsIUnknown), _
Guid("FC4801A3-2BA9-11CF-A229-00AA003D7352")> _
Public Interface IObjectWithSite
 
  <PreserveSig()> _
  Function SetSite(<MarshalAs(UnmanagedType.IUnknown)> ByVal site As Object) As Integer
 
  <PreserveSig()> _
  Function GetSite(ByRef guid As Guid, ByRef ppvSite As IntPtr) As Integer
 
End Interface

GUID "FC4801A3-2BA9-11CF-A229-00AA003D7352" - стандартный. Именно по нему осуществляется "импорт" того или иного интерфейса

3. Теперь от данного интерфейса нужно унаследовать COM-видимый класс, в котором обязательно реализовать оба метода интерфейса, и задать этому классу уникальный GUID, который можно сгенерировать, например, здесь:

https://www.guidgenerator.com/... rator.aspx

У нас это будет 6af768d9-6c98-4fb9-8b2f-05fb4c44f983

Имя класса - неважно. Пусть будет MyBHO. Содержимое файла MyBHO.vb:

VB.NETВыделить код

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62

Imports System.Runtime.InteropServices
 
<ComVisible(True), _
ClassInterface(ClassInterfaceType.None), _
Guid("6af768d9-6c98-4fb9-8b2f-05fb4c44f983")> _
Public Class MyBHO
  Implements IObjectWithSite
 
  Private wb As SHDocVw.WebBrowser ' !!! ВНИМАНИЕ - ДОБАВЬТЕ ССЫЛКУ НА 
                                   ' !!! C:windowssystem32mshtml.tlb (или .dll - если получится)
                                   ' и на C:windowssystem32shdocwv.dll !!!
 
  Public Sub OnBeforeNavigate2(ByVal pDisp As Object, ByRef URL As Object, _
   ByRef Flags As Object, ByRef TargetFrameName As Object, ByRef PostData As Object, ByRef Headers As Object, _
   ByRef Cancel As Boolean)
    ' покажем месседжбокс с URLом загруженной страницы
    MsgBox("URL: " + URL.ToString(), , "Ура, работает!")
 
    ' также можно сделать так
    ' Dim doc = DirectCast(wb.Document, mshtml.HTMLDocument)
    ' и далее через doc взаимодействовать с HTML, см. статью
    ' [url]https://www.cyberforum.ru/post6375281.html[/url]
    ' но это лучше делать в DocumentComplete
  End Sub
 
  Public Function SetSite(ByVal site As Object) As Integer Implements IObjectWithSite.SetSite
 
    If site IsNot Nothing Then
 
      wb = DirectCast(site, SHDocVw.WebBrowser)
 
      AddHandler wb.BeforeNavigate2, New SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(AddressOf Me.OnBeforeNavigate2)
 
    Else
 
      RemoveHandler wb.BeforeNavigate2, New SHDocVw.DWebBrowserEvents2_BeforeNavigate2EventHandler(AddressOf Me.OnBeforeNavigate2)
      wb = Nothing
 
    End If
 
    Return 0
  End Function
 
  Public Function GetSite(ByRef guid As Guid, ByRef ppvSite As IntPtr) As Integer Implements IObjectWithSite.GetSite
    Dim punk As IntPtr = Marshal.GetIUnknownForObject(wb)
    Dim hr As Integer = Marshal.QueryInterface(punk, guid, ppvSite)
    Marshal.Release(punk)
    Return hr
  End Function
 
  <ComRegisterFunction()> _
  Public Shared Sub RegisterBHO(ByVal type As Type)
    ' Это обработчик события регистрации нашей библиотеки (об этом ниже)
    MsgBox("Наше COM-сборка успешно зарегистрирована!")
  End Sub
 
  <ComUnregisterFunction()> _
  Public Shared Sub UnregisterBHO(ByVal type As Type)
    ' Это обработчик события де-регистрации нашей библиотеки (об этом тоже ниже)
    ' Можно сюда написать какой-нибудь код
  End Sub
End Class

Метод SetSite - это своего рода обработчик некоего события. Когда расширение, установленное в IE, загрузится - для каждой вкладки браузера будет вызываться этот метод, и через аргумент site в него будет передаваться объект нативного интерфейса SHDocVw::IWebBrowser2, находящийся в данной вкладке IE. Таким образом мы и сможем взаимодействовать с IE.

4. Построим библиотеку. Разрядность библиотеки должна быть

Any CPU

или

x86

. IE имеет 2 версии - x86 и x64. Да и винда как бы тоже

И x86 совместим с x64, но не наоборот. Поэтому делать x64 не советую.

5.

Внимание:

далее качаем

Microsoft.mshtml.dll

и кладем эту библиотеку рядом с нашей DLL. Там же должна лежать и Interop.SHDocVw.dll (если ее там нет - кладем ее туда). Иначе может не работать на компах, где нет Visual Studio!

Установка DLL в IE

1. Сперва надо зарегистрировать библиотеку как COM-сборку. Это делается утилитой RegAsm, которая входит в .NET Framework.
Для этого создадим такой батник:
[BAT]C:\Windows\Microsoft.NET\Framework\v4.0.30319\regasm.exe /codebase "D:\MyFirstBHO.dll"
pause[/BAT]
Внимание:
1.1. Путь к RegAsm.exe должен быть путем к фреймворку не ниже, чем фреймворк, под который написана библиотека.
1.2. Путь к DLL ("D:\MyFirstBHO.dll") должен быть абсолютным и не содержать кириллицы. Не случайно я ее закинул на диск D.
1.3. Рядом с этой DLL обязательно должны лежать библиотеки Microsoft.mshtml.dll и Interop.SHDocVw.dll (см. выше), иначе COM-сборка зарегистрируется успешно, но в IE может не работать!
1.4. Если вы все же скомпилировали DLL в x64, то и RegAsm нужен тоже x64, т.е. "Framework64", вместо "Framework".
2. Запустим батник от имени администратора.
3. Если появился MsgBox "Наша COM-сборка успешно зарегистрировано!", а текст в консоли содержит строчку "Типы зарегистрированы успешно" и warning про "регистрацию неподписанной сборки", то библиотека успешно зарегистрирована как COM. Идем далее.
4. Теперь надо установить DLL в IE. Если у нас x86, то идем по пути HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer, если x64 - то по пути HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Explorer
Короче, если присутствует второй путь, то идем по нему, если нет - то по первому.
5. Заходим в папку (раздел) Browser Helper Objects. Если такого раздела нет, то создаем его.
6. В этой папке создаем подпапку. Имя подпапки - это GUID из класса MyBHO (не путать с интерфейсом!), заключенный в фигурные скобки. В моем случае - {6af768d9-6c98-4fb9-8b2f-05fb4c44f983}
7. Наконец, запускаем IE.
Если появится окошко "включить ли такую-то надстройку" (у меня появилось на другом компе), жмем "Включить".
Заходим на какую-нибудь страницу или просто открываем пустую вкладку - видим обещанный MsgBox.

Если мы изменили DLL, то нужно ли ее заново регистрировать и устанавливать в IE?

Нет, ничего этого не нужно. Ну разве что если изменили GUID. Или добавили новый COM-класс. Или еще типа такого.

На закуску

Домашнее задание

Напишите инсталлятор, позволяющий автоматизировать всю эту нудятину с регистрацией и установкой.

Вернуться к обсуждению:

Готовые решения и полезные коды на Visual Basic .NET (Часть-1) Visual Basic .NET

1