Найти её и обезвредить
Автор: Артём Курсанов
[Обсудить в форуме]
Бывает такое, что при запуске своей программы необходимо обнаружить какую-то нежелательную программу и закрыть ее. Например, нам нужно во время работы нашей программы закрывать окна блокнота. Как же можно его обнаружить? Первый способ это находить в процессах "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 и т.д. Делайте наблюдение за несколькими классами.