Очередная вариация на тему forever для Windows. Карты на стол: открываю сакральную тайну постоянной подписки на события WMI, да простят меня посвященные :). Если серьезно, убежден, что в приведенном ниже коде каждый разработчик, заинтересованный в применении постоянной подписки найдет для себя что-нибудь вкусное.
Как это работает.
Скрипт состоит из трех классов, отвечающих за подключение к WMI, создание постоянной подписки на события WMI и хранение информации в пространстве имен root\default, а также вступительной части, содержащей логику выполнения скрипта.
На самом деле большая часть кода (классы) мною написана уже давно, поэтому в данном случае мне оставалось написать в основном логику самого скрипта.
Скрипт подключается к WMI, создает постоянную подписку и класс в пространстве имен root\default для хранения информации, необходимой для работы скрипта.
Свойство ScriptText создаваемого потребителя событий ActiveScriptEventConsumer содержит следующий код:
Этот код сохраняем в файл (script.vbs), тестируем, после чего преобразуем в строку с помощью следующего скрипта (scr2var.vbs):
Скрипт не идеален, зато без массивов и регулярных выражений, кроме того полученную строку все равно приходится редактировать. В общем мне хватает. Кому не лень - пилите :).
Закидываем полученную строку в свойство ScriptText потребителя событий - метод Create(c_) класса Subscription - скрипт готов.
Запуск скрипта - от имени АДМИНИСТРАТОРА. Процесс запускается НЕ ИНТЕРАКТИВНО.
Подробности, примеры - в тексте скрипта.
Тестируем. У меня Windows 8 x64 со всеми параноидальными фичами безопасности.
Запускаем процесс.
Несколько раз убиваем процесс. Читаем журнал, сохраняем.
Останавливаем процесс.
Дисклеймер: за "допиливание" полученного кода с целью противозаконного использования автор ответственности не несет.
' скрипт перманентного запуска процесса, ' использует постоянную подписку на события WMI ' TODO: ' - класс в пространстве имен root\default для хранения информации об именах классов, ' используемых для хранения информации о запущенных процессах, для того чтобы выводить список ' процессов, запущенных с помощью скрипта, обращаться к процессам по индексу, ' а не запоминать информацию о параметрах запуска скрипта ' - вынести логику выполнения скрипта в отдельный класс errString = "Примеры: " & vbCrLf & _ "- запуск notepad.exe:" & vbCrLf & _ " evermore.vbs notepad.exe" & vbCrLf & _ "- запуск notepad.exe с выводом отладочных сообщений:" & vbCrLf & _ " evermore.vbs notepad.exe /v" & vbCrLf & _ "- запуск notepad.exe с определением имени фильтра, потребителя событий и класса:" & vbCrLf & _ " evermore.vbs notepad.exe /filter:filtername /consumer:consumername /class:classname" & vbCrLf & _ "- запуск notepad.exe на удаленном компьютере:" & vbCrLf & _ " evermore.vbs notepad.exe /computer:computername /user:username /pw:password" & vbCrLf & _ "- завершние notepad.exe:" & vbCrLf & _ " evermore.vbs notepad.exe /q" & vbCrLf & _ "- заверешние notepad.exe с выводом отладочных сообщений:" & vbCrLf & _ " evermore.vbs notepad.exe /q /v" & vbCrLf & _ "- заверешние notepad.exe с определением имени фильтра, потребителя событий и класса:" & vbCrLf & _ " evermore.vbs notepad.exe /q /filter:filtername /consumer:consumername /class:classname" & vbCrLf & _ "- получение журнала мониторинга, созданного с параметрами по умолчанию, в файл:" & vbCrLf & _ " evermore.vbs /r" & vbCrLf & _ "- получение журнала мониторинга, созданного с параметрами по умолчанию, в окно консоли и в файл:" & vbCrLf & _ " evermore.vbs /r /v" & vbCrLf & _ "- получение журнала мониторинга, созданного с параметрами по умолчанию, в окно консоли:" & vbCrLf & _ " evermore.vbs /r:0 /v" Set args = WScript.Arguments ' что делать todo = Wazzup(args) If todo < 0 Then If todo = -1 Then WScript.Echo "Ошибка: недостаточно аргументов" & vbCrLf & errString If todo = -2 Then WScript.Echo "Ошибка: неверное количество аргументов" & vbCrLf & errString WScript.Quit End if ' вывод отладочных сообщений verbose = args.Named.Exists("v") '------------------------------------------------ ' подключаемся к WMI Set objWMI = new WMI If args.Named.Exists("computer") Then objWMI.Computer = args.Named.Item("computer") If args.Named.Exists("user") Then objWMI.User = args.Named.Item("user") If args.Named.Exists("pw") Then objWMI.PW = args.Named.Item("pw") ret = objWMI.Connect() If verbose Then WScript.Echo "Подключение к WMI: " & Not IsArray(ret) If IsArray(ret) Then WScript.Echo "Ошибка подключения к WMI" & vbCrLf & _ "Код ошибки: " & ret(0) & vbCrLf & "Пространство имен: " & ret(1) WScript.Quit End If ' проверяем регистрацию ActiveScriptEventConsumer Set objSubscription = new Subscription Set objSubscription.RootSubscription = objWMI.RootSubscription Set objSubscription.RootCIMV2 = objWMI.RootCIMV2 ret = objSubscription.ScriptConsumerExists() If verbose Then WScript.Echo "ActiveScriptEventConsumer зарегистрирован: " & CBool(ret) If Not ret Then ' пытаемся зарегистрировать ret = objSubscription.ScriptConsumerReg() If verbose Then WScript.Echo "Регистрация ActiveScriptEventConsumer: " & CBool(ret) If Not ret Then WScript.Echo "Ошибка: не удалось зарегистрировать ActiveScriptEventConsumer" WScript.Quit End If End If '------------------------------------------------ If todo = 0 Then ' запускаем процесс не интерактивно Set objConfig = objWMI.RootCIMV2.Get("Win32_ProcessStartup").SpawnInstance_ objConfig.ShowWindow = 0 '0 - SW_HIDE, 1 - SW_NORMAL ret = objWMI.RootCIMV2.Get("Win32_Process").Create(args.Unnamed(0), , objConfig, pid) If verbose Then WScript.Echo "Процесс " & args.Unnamed(0) & " запущен: " & CBool(Not ret) If ret Then WScript.Echo "Ошибка: не удалось запустить процесс '" & args.Unnamed(0) & "'" WScript.Quit End If End If ' создаем экземпляр объекта MyClass_ Set objMyClass = New MyClass_ Set objMyClass.RootDefault = objWMI.RootDefault If args.Named.Exists("class") Then objMyClass.Name = args.Named.Item("class") ' проверяем наличие класса exists = objMyClass.Exists() If verbose Then WScript.Echo "Наличие класса " & objMyClass.Name & ": " & CBool(exists) ' если запускаем процесс - создаем класс в пространстве имен root\default для хранения информации If todo = 0 Then ret = objMyClass.Create(args.Unnamed(0), pid) If verbose Then WScript.Echo "Создание класса " & objMyClass.Name & " в пространстве имен root\default: " & ret If Not ret Then WScript.Echo "Ошибка: не удалось создать класс " & objMyClass.Name & " в пространстве имен root\default" WScript.Quit End If ElseIf todo = 1 Then ' завершаем процесс If Not exists Then WScript.Echo "Ошибка: класс " & objMyClass.Name & " не существует" Else qpid = objWMI.RootDefault.Get(objMyClass.Name).PID If verbose Then WScript.Echo "Свойство PID класса " & objMyClass.Name & ": " & qpid Set colproc = objWMI.RootCIMV2.ExecQuery("SELECT * FROM Win32_Process WHERE ProcessID = '" & qpid & "'") gotpid = CBool(colproc.Count) If verbose Then WScript.Echo "Процесс PID = " & qpid & " обнаружен: " & gotpid If gotpid Then ret = 0 For Each proc In colproc ret = ret + proc.Terminate() Next If verbose Then WScript.Echo "Процесс PID = " & qpid & " завершен: " & Not CBool(ret) If ret Then WScript.Echo "Ошибка: не удалось завершить процесс PID = " & qpid End If End If ret = objMyClass.Delete() If verbose Then WScript.Echo "Удаление класса " & objMyClass.Name & " в пространстве имен root\default: " & CBool(ret) If Not ret Then WScript.Echo "Ошибка: не удалось удалить класс " & objMyClass.Name & " в пространстве имен root\default" WScript.Quit End If ElseIf todo = 2 And IsEmpty(args.Named.Item("r")) Then ' читаем журнал, пишем в файл If Not exists Then WScript.Echo "Ошибка: класс " & objMyClass.Name & " не существует" Else logName = "evermore.log" Set fso = CreateObject("Scripting.FileSystemObject") With fso.CreateTextFile(logName, True) With GetObject("winmgmts:\\.\root\default:" & objMyClass.Name) s = "Created: " & .Created & vbCrLf & "Process: " & .Process & vbCrLf & _ "PID: " & .PID & vbCrLf & "Log: " & .Log End With .WriteLine(s) .Close End With Set fso = Nothing End If End If If verbose Then If exists And todo <> 1 Then ' если не завершаем процесс ' читаем свойства созданного класса With GetObject("winmgmts:\\.\root\default:" & objMyClass.Name) WScript.Echo "Свойства класса " & objMyClass.Name & ":" & vbCrLf & _ "- Created: " & .Created & vbCrLf & "- Process: " & .Process & vbCrLf & _ "- PID: " & .PID & vbCrLf & "- Log: " & .Log End With End If End If ' создаем подписку If args.Named.Exists("filter") Then objSubscription.Filter = args.Named.Item("filter") If args.Named.Exists("consumer") Then objSubscription.Consumer = args.Named.Item("consumer") If todo = 0 Then ' если запускаем процесс ret = objSubscription.Create(objMyClass.Name) If verbose Then WScript.Echo "Создание подписки: " & CBool(ret) If Not ret Then WScript.Echo "Ошибка: не удалось создать подписку" WScript.Quit End If ElseIf todo = 1 Then ' если удаляем процесс ret = objSubscription.Delete() If verbose Then WScript.Echo "Удаление подписки: " & CBool(ret) If Not ret Then WScript.Echo "Ошибка: не удалось удалить подписку" WScript.Quit End If End If Set objMyClass = Nothing Set objSubscription = Nothing Set objWMI = Nothing WScript.Echo "I gonna last evermore..." WScript.Quit 0 ' -1 - недостаточно аргументов, -2 - неверное количество аргументов, ' 0 - запуск, 1 - завершение, 2 - чтение Function Wazzup(args) If args.Unnamed.Count = 0 And Not args.Named.Exists("r") Then Wazzup = -1 Exit Function ElseIf args.Named.Exists("q") And args.Named.Exists("r") Then Wazzup = -2 Exit Function ElseIf Not(args.Named.Exists("q") Or args.Named.Exists("r")) Then Wazzup = 0 Exit Function ElseIf args.Named.Exists("q") Then Wazzup = 1 Exit Function ElseIf args.Named.Exists("r") Then Wazzup = 2 Exit Function End If End Function ' свойства: ' RootDefault, RootCIMV2, RootSubscription - пространства имен WMI ' Computer, User, PW - данные для подключения к WMI удаленного компьютера ' методы: ' Connect() - попытка подключения к WMI ' в случае ошибки возвращает массив: код ошибки и пространство имен, ' при подключении к которому произошла ошибка Class WMI Private m_Default, m_CIMV2, m_Subscription Private m_Computer, m_User, m_PW Private r1, r2, r3 Public Property Get RootDefault() Set RootDefault = m_Default End Property Public Property Get RootCIMV2() Set RootCIMV2 = m_CIMV2 End Property Public Property Get RootSubscription() Set RootSubscription = m_Subscription End Property Public Property Let Computer(i) m_Computer = i End Property Public Property Let User(i) m_User = i End Property Public Property Let PW(i) m_PW = i End Property Private Sub Class_Initialize() r1 = "root\default" r2 = "root\cimv2" r3 = "root\subscription" End Sub 'подключение к пространствам имен Function Connect() On Error Resume Next Set objLocator = CreateObject("WbemScripting.SWbemLocator") With objLocator.Security_ .AuthenticationLevel = 6 'уровень секретности пакетов .ImpersonationLevel = 3 'объект-сервер может пользоваться всеми правами клиента .Privileges.Add(7) 'привилегия оператора безопасности End With Set m_Default = objLocator.ConnectServer(m_Computer, r1, m_User, m_PW, , , 128) If Err.Number <> 0 Then Connect = Array(Err.Number, r1) Exit Function End If Set m_CIMV2 = objLocator.ConnectServer(m_Computer, r2, m_User, m_PW, , , 128) If Err.Number <> 0 Then Connect = Array(Err.Number, r2) Exit Function End If Set m_Subscription = objLocator.ConnectServer(m_Computer, r3, m_User, m_PW, , , 128) If Err.Number <> 0 Then Connect = Array(Err.Number, r3) Exit Function End If Connect = 0 End Function End Class ' свойства: ' Filter, Consumer - имена фильтра и потребителя событий, по умолчанию MyFilter и MyConsumer ' RootSubscription, RootCIMV2 - объекты RootSubscription и RootCIMV2, необходимо присвоить значения ' методы: ' ScriptConsumerExists() - проверка регистрации ActiveScriptEventConsumer, ' возвращает True если ActiveScriptEventConsumer зарегистрирован ' ScriptConsumerReg() - попытка регистрации ActiveScriptEventConsumer, ' возвращает True в случае успешной регистрации ActiveScriptEventConsumer ' Create(с_) - создание подписки на событие, получает имя класса, в случае успеха возвращает True ' Delete() - удаление подписки на событие, в случае успеха возвращает True Class Subscription Private m_Filter, m_Consumer, m_Subscription, m_CIMV2 Public Property Let Filter(i) m_Filter = i End Property Public Property Let Consumer(i) m_Consumer = i End Property Public Property Get Filter Filter = m_Filter End Property Public Property Get Consumer Consumer = m_Consumer End Property Public Property Set RootSubscription(i) Set m_Subscription = i End Property Public Property Set RootCIMV2(i) Set m_CIMV2 = i End Property Private Sub Class_Initialize() 'значения по умолчанию m_Filter = "MyFilter" m_Consumer = "MyConsumer" End Sub 'проверка регистрации стандартного потребителя ActiveScriptEventConsumer Function ScriptConsumerExists() On Error Resume Next If m_Subscription.ExecQuery( _ "SELECT * FROM __Provider WHERE Name='ActiveScriptEventConsumer'").Count Then ScriptConsumerExists = True End If End Function 'регистрация стандартного потребителя Function ScriptConsumerReg() On Error Resume Next 'конфигурируем создание процесса Set objConfig = m_CIMV2.Get("Win32_ProcessStartup").SpawnInstance_ objConfig.ShowWindow = 0 'SW_HIDE, 1 - SW_NORMAL 'регистрация стандартного потребителя ret = m_CIMV2.Get("Win32_Process").Create( _ "mofcomp -N:root\subscription %SystemRoot%\system32\Wbem\scrcons.mof", , objConfig, intProcessID) If ret <> 0 Then Exit Function 'отправляем идентификатор процесса в функцию ожидания завершения процесса ScriptConsumerReg = ProcessFinished(intProcessID) End Function 'ожидание завершения процесса "до упора" Function ProcessFinished(intProcessID) On Error Resume Next Set colProcesses = m_CIMV2.ExecNotificationQuery( _ "SELECT * FROM __InstanceDeletionEvent WITHIN 2 WHERE TargetInstance ISA 'Win32_Process'" & _ " AND TargetInstance.ProcessID = '" & intProcessID & "'") Do Set objProcess = colProcesses.NextEvent If Err.Number = 0 Then ProcessFinished = True Exit Function Loop End Function 'создание подписки на событие Function Create(c_) On Error Resume Next sid = Array(1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0) ' sid администратора 'создание фильтра события With m_Subscription.Get("__EventFilter").SpawnInstance_() .Name = m_Filter .QueryLanguage = "WQL" .EventNamespace = "root\cimv2" .Query = "SELECT * FROM __InstanceDeletionEvent WITHIN 2 " & _ "WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessId = '" & pid & "'" .CreatorSID = sid Set objFilterPath = .Put_ End With var = "Const c_ = """ & c_ & """, f_ = """ & m_Filter & """" & vbCrLf & "With GetObject(""winmgmts:\\.\root\default:"" & c_)" & vbCrLf & " .Log = .Log & vbCrLf & Now() & "" - Process '"" & .Process & ""' stopped, pid: "" & .PID" & vbCrLf & " ret = GetObject(""winmgmts:\\.\root\cimv2"").Get(""Win32_Process"").Create(.Process, , , pid)" & vbCrLf & " created = Not CBool(ret)" & vbCrLf & " If created Then" & vbCrLf & " .PID = pid" & vbCrLf & " .Log = .Log & vbCrLf & Now() & "" - Process '"" & .Process & ""' started, pid: "" & pid" & vbCrLf & " Else" & vbCrLf & " .PID = vbNullString" & vbCrLf var = var & " .Log = .Log & vbCrLf & Now() & "" - Fail starting process '"" & .Process & ""' started, pid: "" & pid" & vbCrLf & " End If" & vbCrLf & " .Put_" & vbCrLf & "End With" & vbCrLf & "If created Then " & vbCrLf & " Set colFilters = GetObject(""winmgmts:\\.\root\subscription"").ExecQuery( _" & vbCrLf & " ""SELECT * FROM __EventFilter WHERE Name='"" & f_ & ""'"")" & vbCrLf & " If colFilters.Count Then " & vbCrLf & " For Each objFilter In colFilters" & vbCrLf & " With objFilter" & vbCrLf & " .Query = ""SELECT * FROM __InstanceDeletionEvent WITHIN 2 "" & _" & vbCrLf var = var & " ""WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessId = '"" & pid & ""'""" & vbCrLf & " .CreatorSID = Array(1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0) " & vbCrLf & " .Put_ " & vbCrLf & " End With " & vbCrLf & " Next" & vbCrLf & " End If " & vbCrLf & "End If" 'создание потребителя события With m_Subscription.Get("ActiveScriptEventConsumer").SpawnInstance_() .Name = m_Consumer .ScriptingEngine = "VBScript" .KillTimeout = 10 'завершить выполнение через 10 секунд .ScriptText = var .CreatorSID = sid Set objConsumerPath = .Put_ End With 'связка фильтра и потребителя With m_Subscription.Get("__FilterToConsumerBinding").SpawnInstance_() .Filter = objFilterPath .Consumer = objConsumerPath .CreatorSID = sid .Put_ End With Set objFilterPath = Nothing Set objConsumerPath = Nothing If Err.Number = 0 Then Create = True End Function 'удаление подписки на событие Function Delete() On Error Resume Next 'удаляем фильтр Set colFilters = m_Subscription.ExecQuery("SELECT * FROM __EventFilter WHERE Name='" & m_Filter & "'") If colFilters.Count Then For Each objFilter In colFilters objFilter.Delete_ ' удаляем сам фильтр Next End If Set colFilters = Nothing 'удаляем потребителя Set colConsumers = m_Subscription.ExecQuery("SELECT * FROM ActiveScriptEventConsumer WHERE Name='" & m_Consumer & "'") If colConsumers.Count Then For Each objConsumer In colConsumers objConsumer.Delete_ Next End If Set colConsumers = Nothing If Err.Number = 0 Then Delete = True End Function End Class ' свойства: ' Name - имя класса, по умолчанию MyClass, ' RootDefault - объект RootDefault, необходимо присвоить значение ' методы: ' Exists() - проверка существования класса в пространстве имен root\default, ' возвращает True если класс существует ' Create(proc, pid) - создание класса в пространстве имен root\default, ' получает команду запуска и ID процесса, возвращает True в случае успеха ' Delete() - удаление класса из пространства имен root\default, ' возвращает True в случае успеха Class MyClass_ Private m_Name, m_Default Public Property Let Name(i) m_Name = i End Property Public Property Get Name Name = m_Name End Property Public Property Set RootDefault(i) Set m_Default = i End Property Private Sub Class_Initialize() m_Name = "MyClass" 'по умолчанию End Sub 'наличие класса Function Exists() On Error Resume Next For Each objClass In m_Default.SubclassesOf() If InStr(objClass.Path_.Path, m_Name) Then Exists = True Exit Function End If Next End Function 'создаем класс Function Create(proc, pid) On Error Resume Next With m_Default.Get() .Path_.Class = m_Name .Properties_.Add "Log", 8 'журнал .Properties_.Add "Created", 8 'дата создания .Properties_.Add "PID", 8 'ID процесса .Properties_.Add "Process", 8 'команда запуска процесса .Properties_("Log") = vbNullString 'по умолчанию .Properties_("Created") = Now() .Properties_("PID") = pid .Properties_("Process") = proc .Put_ 'пишем класс в репозиторий End With If Err.Number = 0 Then Create = True End Function 'удаляем класс Function Delete() On Error Resume Next With m_Default.Get() .Path_.Class = m_Name .Put_ End With m_Default.Delete m_Name If Err.Number = 0 Then Delete = True End Function End Class
Как это работает.
Скрипт состоит из трех классов, отвечающих за подключение к WMI, создание постоянной подписки на события WMI и хранение информации в пространстве имен root\default, а также вступительной части, содержащей логику выполнения скрипта.
На самом деле большая часть кода (классы) мною написана уже давно, поэтому в данном случае мне оставалось написать в основном логику самого скрипта.
Скрипт подключается к WMI, создает постоянную подписку и класс в пространстве имен root\default для хранения информации, необходимой для работы скрипта.
Свойство ScriptText создаваемого потребителя событий ActiveScriptEventConsumer содержит следующий код:
Const c_ = "MyClass", f_ = "MyFilter" With GetObject("winmgmts:\\.\root\default:" & c_) .Log = .Log & vbCrLf & Now() & " - Process '" & .Process & "' stopped, pid: " & .PID ret = GetObject("winmgmts:\\.\root\cimv2").Get("Win32_Process").Create(.Process, , , pid) created = Not CBool(ret) If created Then .PID = pid .Log = .Log & vbCrLf & Now() & " - Process '" & .Process & "' started, pid: " & pid Else .PID = vbNullString .Log = .Log & vbCrLf & Now() & " - Fail starting process '" & .Process & "' started, pid: " & pid End If .Put_ End With If created Then Set colFilters = GetObject("winmgmts:\\.\root\subscription").ExecQuery( _ "SELECT * FROM __EventFilter WHERE Name='" & f_ & "'") If colFilters.Count Then For Each objFilter In colFilters With objFilter .Query = "SELECT * FROM __InstanceDeletionEvent WITHIN 2 " & _ "WHERE TargetInstance ISA 'Win32_Process' AND TargetInstance.ProcessId = '" & pid & "'" .CreatorSID = Array(1,2,0,0,0,0,0,5,32,0,0,0,32,2,0,0) .Put_ End With Next End If End If
Этот код сохраняем в файл (script.vbs), тестируем, после чего преобразуем в строку с помощью следующего скрипта (scr2var.vbs):
'************************************* 'создание переменной из текста скрипта '************************************* Set args = WScript.Arguments If args.Count = 0 Then WScript.Echo "Ошибка: не достаточно аргументов" WScript.Quit End If max = 9 ' максимальное количество строк файла в строке присваивания значения переменной, по умолчанию - 10 If args.Named.Exists("max") Then max = CInt(args.Named.Item("max")) + 1 Set fso = CreateObject("Scripting.FileSystemObject") With fso If Not .FileExists(args(0)) Then WScript.Echo "Ошибка: файл " & args(0) & " не найден" WScript.Quit End If Set f1 = .OpenTextFile(args(0),1) f2Name = args(0) & ".txt" Set f2 = .CreateTextFile(f2Name,True) End With Set args = Nothing f2.Write "var = " 'первая строка i = 0 Do Until f1.AtEndOfStream 'читаем If i > max Then 'новая строка f2.Write "var = var & " & Chr(34) & Replace(Trim(f1.ReadLine),Chr(34),Chr(34) & Chr(34)) & Chr(34) & " & vbCrLf & " i = 0 Else If i = max Then 'последняя строка f2.WriteLine Chr(34) & Replace(Trim(f1.ReadLine),Chr(34),Chr(34) & Chr(34)) & Chr(34) & " & vbCrLf" Else 'обычная строка f2.Write Chr(34) & Replace(Trim(f1.ReadLine),Chr(34),Chr(34) & Chr(34)) & Chr(34) If Not f1.AtEndOfStream Then f2.Write " & vbCrLf & " End If i = i + 1 End If Loop f2.Close f1.Close Set f1 = Nothing Set f2 = Nothing Set fso = Nothing WScript.Echo "Создание файла " & f2Name & " завершено"
Скрипт не идеален, зато без массивов и регулярных выражений, кроме того полученную строку все равно приходится редактировать. В общем мне хватает. Кому не лень - пилите :).
Закидываем полученную строку в свойство ScriptText потребителя событий - метод Create(c_) класса Subscription - скрипт готов.
Запуск скрипта - от имени АДМИНИСТРАТОРА. Процесс запускается НЕ ИНТЕРАКТИВНО.
Подробности, примеры - в тексте скрипта.
Тестируем. У меня Windows 8 x64 со всеми параноидальными фичами безопасности.
Запускаем процесс.
Несколько раз убиваем процесс. Читаем журнал, сохраняем.
Останавливаем процесс.
Дисклеймер: за "допиливание" полученного кода с целью противозаконного использования автор ответственности не несет.
Комментариев нет:
Отправить комментарий
Комментарий будет опубликован после модерации