В данной статье мы попробуем закрыть заданный процесс из командной строки через диалоговою форму, созданную с помощью сервера сценариев Windows Script Host на языке vbscript.
Я решил не повторять ошибку, допущенную в статье “Создаем менеджер служб”, там я впихнул сразу два огромных сценариях, и, фактически получилась сплошная каша на 12 тысяч символов. Просто я хотел сэкономить время, в результате – позиции в выдаче были хуже, чем я ожидал.
Как и прежде, для создания оконного интерфейса мы будем использовать компонент WindowSystemObject, ссылку на архив с примером вы найдете в конце статьи. Задача примера – получить список процессов, выделить нужный и (закрыть) остановить процесс из командной строки, для этого мы будем использовать утилиту taskkill.
'************************************************************************** ' Закрытие процесса из командной строки ' process-killer.vbs '************************************************************************** Option Explicit ' Формируем ссылки на объект dim WSO, WshShell, objWMIService set WSO = WScript.CreateObject("Scripting.WindowSystemObject") set WshShell = WScript.CreateObject("WScript.Shell") set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") dim list_view_obj, data_array(), t, f, def_columns dim Button_Update, Button_Kill dim Caption_class, GetOwner_class, ProcessId_class, ParentProcessId_class '************************************************* ' пользовательские классы '************************************************* Class new_class Dim Caption, GetOwner, ProcessId, ParentProcessId End Class Class C_class Property Get name name = "Описание" End Property Property Get width width = 100 End Property function set_data(item, iy) item.Text = data_array(iy).Caption end function End Class Class UN_class Property Get name name = "Имя пользователя" End Property Property Get width width = 120 End Property function set_data(item, iy) item.SubItems(0) = data_array(iy).GetOwner end function End Class Class Pid_class Property Get name name = "PID процесса" End Property Property Get width width = 80 End Property function set_data(item, iy) item.SubItems(1) = data_array(iy).ProcessId end function End Class Class PidP_class Property Get name name = "PID родителя" End Property Property Get width width = 80 End Property function set_data(item, iy) item.SubItems(2) = data_array(iy).ParentProcessId end function End Class '*************************************************** ' ************************* Параметры формы ************************************************ set f = WSO.CreateForm(0, 0, 0, 0, WSO.Translate("WS_CONTROLBOX | WS_MINIMIZEBOX")) f.Text = "Остановка процесса через командную строку" f.ClientWidth = 560 f.ClientHeight = 300 f.CenterControl() '*********************************************************************************************** '******************************************************************************** ' Управляющие кнопки set Button_Update = f.CreateButton(420,10,100,25,"Обновить список") Button_Update.OnClick = getref("ProcessUpdate") set t = f.CreateHyperLink(410,40,250,25,"scriptcoding.ru") ' Закрыть процесс через командную строку set Button_Kill = f.CreateButton(420,70,100,25,"Остановить") Button_Kill.OnClick = getref("ProcessKill") ' функция для формирования массива с данными function fill_data_array() dim colItems, objItem, inc, my_class, len_col, output dim strUser, strDomain, Domain_User Redim data_array(0) inc = 0 ' формируем коллекцию set colItems = objWMIService.ExecQuery("Select * from Win32_Process") len_col = colItems.count Redim data_array(len_col) ' произвдим перебор коллекции For Each objItem in colItems set my_class = new new_class output = objItem.GetOwner(strUser,strDomain) if output = 0 then Domain_User = strDomain & "\" & strUser else Domain_User="Нет Доступа" end if with my_class .Caption = objItem.Caption .GetOwner = Domain_User .ProcessId = objItem.ProcessId .ParentProcessId = objItem.ParentProcessId end with set data_array(inc) = my_class inc = inc +1 Next end function '*************************************************************** ' массив с данными set Caption_class = new C_class set GetOwner_class = new UN_class set ProcessId_class = new Pid_class set ParentProcessId_class = new PidP_class def_columns = Array(Caption_class, GetOwner_class, ProcessId_class, ParentProcessId_class) ' Формируем панель со списком function CreateListView() dim def_col, column, ix, iy 'Создаем объект ListView set list_view_obj = f.CreateListView( 0, 0, 400, 300,WSO.Translate("LVS_REPORT | LVS_SHOWSELALWAYS")) 'Свойства объекта ListView list_view_obj.GridLines = true list_view_obj.RowSelect = true list_view_obj.ReadOnly = false ' Определяем имя и тип колонок for ix = 0 to UBound(def_columns) set column = list_view_obj.Columns.Add(def_columns(ix).name, def_columns(ix).width) next ' Заполняем список fill_data_array() list_view_obj.Count = UBound(data_array) for ix = 0 to UBound(def_columns) for iy=0 to list_view_obj.Count-1 def_columns(ix).set_data list_view_obj.item(iy), iy next next end function 'вызываем функцию для формирования списка CreateListView() f.Show() WSO.Run() '************************************************************************ ' управляющие функции function ProcessUpdate() dim ix, iy list_view_obj.Clear() ' Заполняем список fill_data_array() list_view_obj.Count = UBound(data_array) for ix = 0 to UBound(def_columns) for iy=0 to list_view_obj.Count-1 def_columns(ix).set_data list_view_obj.item(iy), iy next next end function ' Остановить процесс из командной строки function ProcessKill(sender) dim cur_process_pid if list_view_obj.ItemIndex<0 then WScript.Echo "Выберите процесс для завершения" elseif ServiceDialog() = 1 then cur_process_pid = data_array(list_view_obj.ItemIndex).ProcessId WshShell.Run "cmd.exe /c taskkill /PID " & cur_process_pid,1,true WScript.Sleep 2000 ProcessUpdate() end if end function function ServiceDialog() dim cur_process_caption, Msg, Title, result cur_process_caption = data_array(list_view_obj.ItemIndex).Caption Msg = "Вы уверены, что хотите закрыть процесс из командной строки " & cur_process_caption & " ?" Title = "Закрытие процесса из командной строки" result = MsgBox(Msg, vbOKCancel + vbInformation, Msg) if result = vbOK then ServiceDialog = 1 else ServiceDialog = 0 end if end function |
Первое на что стоит обратить внимание – это пользовательские классы, их всего пять:
new_class – класс содержит четыре свойства (по числу колонок в списке), в каждом свойстве хранится заданная информация о процессе (Ими (Описание), Учетный данные, под которыми работает процесс, идентификатор и идентификатор родителя).
Остальные четыре класса хранят имя колонки, ее ширину и функция, которая отвечает за добавление данных в список для текущей колонки
На форме находятся две кнопки:
Button_Update – вызывает функции для обновления списка, это необходимо, если мы хотим проверить, не изменился ли состав работающих процессов, после того, как мы остановили процесс из командной строки.
Button_Kill – нужна, что бы остановить заданный процесс из командной строки. При нажатии будет вызываться функция ProcessKill.
Обратите внимание, что бы вызвать нужную функцию, мы используем функцию vbscript GetRef, и в качестве параметра передаем ей имя функции, но не целиком, а в виде строки. Это особенности самого языка vbscript. Фактически, GetRef формируют ссылку на копию заданной функции.
Далее идет формирование массива data_array в функции fill_data_array. Тут мы получаем доступ к классу Win32_Process, который возвращает коллекцию процессов и извлекаем четыре свойства. Сам массив data_array хранит в себе объекты с заданными свойства, число объектов ровно числу элементов в списке.
Для заполнения колонок мы обращаемся к массиву def_columns, который тоже хранит в себе объекты.
Функция CreateListView отвечает за создание списка, формирование колонок и добавление элементов.
Сам компонент WindowSystemObject содержит довольно широкие возможности, но… слабую справку по применению и описанию. Так, я пока не разобрался, как корректно произвести сортировку элементов, что бы было удобней остановить процесс из командной строки. Так как при сортировке данных меняется их индексы, и соответственно, должно измениться содержимое самого массива data_array.