1

Тема: WSH: как из скрипта определить его идентификатор процесса (PID)

Из скрипта, посредством объекта WshScriptExec, запускается дочерний процесс «mshta.exe». Затем, посредством WMI, извлекается экземпляр Win32_Process объекта SWbemObjectEx запущенного дочернего процесса «mshta.exe», основываясь на полученном из объекта WshScriptExec PID этого дочернего процесса. После чего, из полученного экземпляра Win32_Process берётся родительский PID (.ParentProcessID), который и будет являться идентификатором процесса скрипта. Последним действием будет закрытие запущенного дочернего процесса через объект WshScriptExec.

Замечание: приложение «mshta.exe» и его специальным образом подобранная командная строка позволяют создать скрытое окно, чтобы GUI окно (или окно консоли) дочернего процесса не отображалось на экране и не мешало работе.

Option Explicit

WScript.Echo GetScriptProcessID()

WScript.Quit 0
'=============================================================================

'=============================================================================
Function GetScriptProcessID()
    Dim objWshShell
    Dim objWshScriptExec
    Dim objSWbemObjectEx_ChildProcess
    
    Dim strPath
    
    
    strPath = """mshta.exe"" " & _
        """<HTML><HEAD><HTA:APPLICATION APPLICATIONNAME='GetParentPID' " & _
        "WINDOWSTATE='minimize' SHOWINTASKBAR='no'</HEAD></HTML>"""
    
    Set objWshShell                   = WScript.CreateObject("WScript.Shell")
    Set objWshScriptExec              = objWshShell.Exec(strPath)
    Set objSWbemObjectEx_ChildProcess = GetObject( _
        "winmgmts:\\.\root\CIMV2:Win32_Process.Handle='" & CStr(objWshScriptExec.ProcessID) &"'")
    
    GetScriptProcessID = objSWbemObjectEx_ChildProcess.ParentProcessID
    objWshScriptExec.Terminate
    
    Set objSWbemObjectEx_ChildProcess = Nothing
    Set objWshScriptExec              = Nothing
    Set objWshShell                   = Nothing
End Function
'=============================================================================

Отдельное спасибо коллеге Slav за ценное замечание.

2

Re: WSH: как из скрипта определить его идентификатор процесса (PID)

Получение характеристик текущего процесса с помощью Win32 API и DynamicWrapperX, пример на JScript.

DW=new ActiveXObject("DynamicWrapperX")
DW.Register("KERNEL32.DLL","GetCurrentProcessId","f=s","r=l")
DW.Register("KERNEL32.DLL","GetModuleHandle","i=l","f=s","r=l")
DW.Register("KERNEL32.DLL","GetModuleFileNameA","i=lll","f=s","r=l")


//-------------------------------------------------------------
PID    =DW.GetCurrentProcessId()    //Идентификатор процесса
//-------------------------------------------------------------
hModule    =DW.GetModuleHandle(0)    //Основной модуль процесса
//-------------------------------------------------------------
sPtr    =DW.StrPtr(DW.Space(255),"s")    //Имя файла модуля
hRes    =DW.GetModuleFileNameA(hModule,sPtr,255)
FileName=DW.StrGet(sPtr,"s")
//------------------------------------------------------------
WScript.Echo(    '[Идентификатор текущего процесса]    \n'+
        PID+    '                \n'+
        '[Модуль:]                 \n'+
        hModule+'                \n'+
        '[Файл модуля:]                \n'+
        FileName)
WScript.Quit()
//------------------------------------------------------------

Автор примера - Poltergeyst.

Предложения в русском языке начинаются с большой буквы и заканчиваются точкой.
В названии ветки всегда должен быть указан язык программирования или среда исполнения скрипта, если это возможно.

3

Re: WSH: как из скрипта определить его идентификатор процесса (PID)

Немного ужатые в целях экономии варианты скрипта Poltergeyst'a. Язык - JScript.

С выводом в диалоговое окно:

with(new ActiveXObject("DynamicWrapperX")) {
  Register("kernel32","GetCurrentProcessId","r=u")
  Register("kernel32","GetModuleHandle","i=u","r=h")
  Register("kernel32","GetModuleFileName","i=hSu")
  FileName = Space(255)
  PID = GetCurrentProcessId()
  hModule = GetModuleHandle(0)
  GetModuleFileName(hModule, FileName, 510)
}

WScript.Echo("PID: " + PID + "\nМодуль: " + hModule + "\nФайл модуля: " + FileName)

С выводом в консоль:

with(new ActiveXObject("DynamicWrapperX")) {
  Register("kernel32","GetCurrentProcessId","r=u")
  Register("kernel32","GetModuleHandle","i=u","r=h")
  Register("kernel32","GetModuleFileName","i=hSu")
  Register("msvcrt","system","i=s")
  FileName = Space(255)
  PID = GetCurrentProcessId()
  hModule = GetModuleHandle(0)
  GetModuleFileName(hModule, FileName, 510)
  system("Echo PID: " + PID +
         " & Echo Модуль: " + hModule + 
         " & Echo Файл модуля: " + FileName +
         " & Echo." +
         " & Pause")
}

В последнем примере использована функция system из msvcrt.dll. Переданную ей строку она отправляет командному интерпретатору (cmd.exe) и тот выполняет содержащиеся в ней команды.

4

Re: WSH: как из скрипта определить его идентификатор процесса (PID)

старый финт подобен первому методу

set test=GetObject("winmgmts:\\.\root\cimv2:win32_process.Handle='" & CreateObject("WScript.Shell").Exec("rundll32 kernel32,Sleep").ProcessId & "'")
msgbox test.ParentProcessId
test.Terminate
Я конечно далек от мысли... (с)

5 (изменено: Xameleon, 2014-07-15 17:39:57)

Re: WSH: как из скрипта определить его идентификатор процесса (PID)

Ещё чуть-чуть оптимизировал код:


MsgBox GetCurrentProcessID()

Function GetCurrentProcessID()
    With GetObject("winmgmts:root\cimv2:win32_process.Handle='" &_
        CreateObject("WScript.Shell").Exec("rundll32 kernel32,Sleep").ProcessId & "'")
        GetCurrentProcessID = .ParentProcessId
        .Terminate
    End With
End Function
Передумал переделывать мир. Пашет и так, ну и ладно. Сделаю лучше свой !