Дата публикации статьи: 26.05.2006 20:37

Найти её и обезвредить

Автор: Артём Курсанов
[Обсудить в форуме]

    Бывает такое, что при запуске своей программы необходимо обнаружить какую-то нежелательную программу и закрыть ее. Например, нам нужно во время работы нашей программы закрывать окна блокнота. Как же можно его обнаружить? Первый способ это находить в процессах "notepad.exe" и снимать задачу. Но как программу назовешь, под таким именем она и будет в процессах, нас могут обмануть, переименуют блокнот в "notepud.exe" и наша программа работать не будет. Второй способ найти окно по его заголовку, но заголовок зависит от названия файла .txt, и будет всегда разным – тоже не подходит. А вот найти окно по имени класса, которому оно принадлежит – это можно. У Блокнота имя класса окна – Notepad, и как бы не назывался исполняемый файл и файлы .txt имя класса у них будет одно и тоже – это Notepad. Давайте напишем две программы, первая по заголовку окна узнает его имя класса. Т.е. Вы введете в текстовом поле "Безымянный - Блокнот" и получите "Notepad". И вторая, будет следить за именами классов окон и если найдет "Notepad", то закроет его.

Получение имени класса, которому принадлежит окно

Создайте проект Standart EXE. Добавьте на форму CommandButton и два TextBox'а:

Option Explicit
 
Private Declare Function GetClassName Lib "user32.dll" Alias "GetClassNameA" (ByVal hWnd As Long, ByVal lpClassName As _
String, ByVal nMaxCount As Long) As Long Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long Private Sub Command1_Click() Dim win_hWnd As Long Dim class_name As String win_hWnd = FindWindow(vbNullString, Text1) ' FindWindow – ищет все окна, которые
' соответствуют имени класса окна и(или) его заголовку ' в win_hWnd содержится дескриптор найденного окна ' Дескриптор - уникальное целое число, которое
' присваивается объекту ' vbNullString, чтобы игнорировать класс окна class_name = Space(255)' место под имя класса GetClassName win_hWnd, class_name, 255 ' GetClassName – возвращает имя класса, которому
' принадлежит окно ' в class_name содержится имя класса class_name = Left(class_name, 255)' удаляю лишние пробелы Text2 = class_name' отображаю имя класса End Sub

    Вот и все, давайте проверим. Откройте Пуск -> Выполнить и введите regedit – откроется редактор реестра. Запускайте проект и в TextBox1 введите заголовок окна редактора реестра, т.е. "Редактор реестра". Нажмите на кнопку, и в TextBox2 у Вас должно появиться имя класса – " RegEdit_RegEdit". Поэкспериментируйте с другими окнами.

Найти её и обезвредить

    Теперь мы можем узнавать имена классов любых окон, будь это какой либо отладчик, "монитор" или "шпион". Забудем про блокнот и вспомним, про замечательный "монитор" – Regmon, шпионящий за программами, которые работают с реестром. Напишем программку, которая будет закрывать Regmon во время своей работы. Создайте проект Standart EXE. Добавьте на форму Timer, Interval поставте равным единице:

Option Explicit

Private Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" (ByVal lpClassName As String, ByVal_
lpWindowName As String) As Long Private Declare Function SendMessage Lib "user32.dll" _
Alias "SendMessageA" (ByVal hWnd As Long, ByVal Msg _
As Long, wParam As Any, lParam As Any) As Long Const WM_CLOSE = &H10 Dim WinWnd As Long Private Sub Timer1_Timer() WinWnd = FindWindow("18467-41", vbNullString) '"18467-41" - имя класса Regmon ' здесь мы уже игнорируем имя окна If WinWnd <> 0 Then
' если дескриптор не равен 0, т.е окно
' с данным классом существует SendMessage WinWnd, WM_CLOSE, 0, 0
' посылаем ему сообщение - закрыться End If End Sub

    Готово. Запустите проект, а затем и Regmon v6.06 и Вы увидите как он закроется. Включайте Ваше воображение, делайте, чтобы программа приостанавливалась, появлялось сообщение о закрытии Regmon'a и т.д. Делайте наблюдение за несколькими классами.