Getting Script Name from wscript.exe Process - vbscript

I am using this code:
Dim name
name = CreateObject("WScript.Shell").ExpandEnvironmentStrings("%computername%")
Set wmi = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& name & "\root\cimv2")
For Each hwnd In wmi.InstancesOf("Win32_Process")
If hwnd.Name = "wscript.exe" Then
'get name and possibly location of currently running script
End If
Next
I am successfully listing all processes and picking out the wscript.exe. However, I have searched and have found no way to find the name of the script running in wscript.exe, ie. is it myscript.vbs or jscript.js or anything. Bonus if there is a way to find the whole path of the script.
EDIT:
With more searching, I found a solution. In the above script, the hwnd variable stores the handle for the wscript.exe process. There is a property for handles: hwnd.CommandLine. It shows how to call it from the command line, so it would be something like:
"C:\Windows\System32\wscript.exe" "C:\path\to\script.vbs"
So I can parse the hwnd.CommandLine string to find the path and name of all running scripts.

You have ScriptName and ScriptFullName properties.
' in VBScript
WScript.Echo WScript.ScriptName
WScript.Echo WScript.ScriptFullName
// in JScript
WScript.Echo(WScript.ScriptName);
WScript.Echo(WScript.ScriptFullName);
[EDIT] Here you go (use .CommandLine property):
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& "." & "\root\cimv2")
Set colProcesses = objWMIService.ExecQuery( _
"Select * from Win32_Process " _
& "Where Name = 'WScript.exe'", , 48)
Dim strReport
For Each objProcess in colProcesses
' skip current script, and display the rest
If InStr (objProcess.CommandLine, WScript.ScriptName) = 0 Then
strReport = strReport & vbNewLine & vbNewLine & _
"ProcessId: " & objProcess.ProcessId & vbNewLine & _
"ParentProcessId: " & objProcess.ParentProcessId & _
vbNewLine & "CommandLine: " & objProcess.CommandLine & _
vbNewLine & "Caption: " & objProcess.Caption & _
vbNewLine & "ExecutablePath: " & objProcess.ExecutablePath
End If
Next
WScript.Echo strReport

myProcess="wscript.exe"
Set Processes = GetObject("winmgmts:").InstancesOf("Win32_Process")
For Each Process In Processes
If StrComp(Process.Name, myProcess, vbTextCompare) = 0 Then 'check if process exist
CmdLine=process.commandline
End If
Next
myArr=split(CmdLine,"\")
mySN=replace(myArr(ubound(myArr)),"""","")
Wscript.Echo "Full Pth: " & Cmdline &vbcrlf&"Script Name: "& mySN

Related

Call recently added script from another script

As soon as the file is added to script folder it is detected by this code.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""c:\\\\scripts""'")
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
Wscript.Echo objLatestEvent.TargetInstance.PartComponent
Loop
I want to execute VBScript as soon as it is added to script folder from this VBScript. How to do that? Getting the name of the file that is added to script folder and then executing that VBScript.
Replace this line of code with the code you want executed any time a new file is detected: Wscript.Echo objLatestEvent.TargetInstance.PartComponent. For instance, next code snippet shows a possible approach (and that's why there is wide Echo output, wider than necessary...):
''''(unchanged code above)
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
''''Wscript.Echo objLatestEvent.TargetInstance.PartComponent
Call DoWithName( objLatestEvent.TargetInstance.PartComponent)
Loop
Sub DoWithName( strPartComp)
Dim arrFileName
arrFileName = Split( strPartComp, """")
If True Or UBound(arrFileName) > 0 Then
Wscript.Echo strPartComp _
& vbNewLine & UBound( arrFileName) _
& vbNewLine & "[" & arrFileName( 0) & "]" _
& vbNewLine & "[" & arrFileName( 1) & "]" _
& vbNewLine & "[" & arrFileName( 2) & "]" _
& vbNewLine & ShowAbsolutePath( arrFileName( 1))
End If
End Sub
Function ShowAbsolutePath( strPath)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
ShowAbsolutePath = fso.GetAbsolutePathName( strPath)
End Function
Note that
the ShowAbsolutePath( arrFileName( 1)) returns the name of the file that is added to script folder; now you could
check whether it's a valid .vbs file name, and if so, launch it combining any Windows Script Host engine (wscript.exe or cscript.exe) in either
Run Method or
Exec Method.
You can try this modified script :
If AppPrevInstance() Then
MsgBox "There is an existing proceeding !" & VbCrLF &_
CommandLineLike(WScript.ScriptName),VbExclamation,"There is an existing proceeding !"
WScript.Quit
Else
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceCreationEvent WITHIN 10 WHERE " _
& "Targetinstance ISA 'CIM_DirectoryContainsFile' and " _
& "TargetInstance.GroupComponent= " _
& "'Win32_Directory.Name=""d:\\\\scripts""'")
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
Call DoWithName(objLatestEvent.TargetInstance.PartComponent)
Loop
End if
' --------------------------------------
Sub DoWithName( strPartComp)
Dim Title,arrFileName,Question,ws
Title = "Execute vbscript"
set ws = CreateObject("wscript.shell")
arrFileName = Split( strPartComp, """")
If True Or UBound(arrFileName) > 0 Then
Wscript.Echo strPartComp _
& vbNewLine & UBound( arrFileName) _
& vbNewLine & "[" & arrFileName( 0) & "]" _
& vbNewLine & "[" & arrFileName( 1) & "]" _
& vbNewLine & "[" & arrFileName( 2) & "]" _
& vbNewLine & DblQuote(ShowAbsolutePath(arrFileName(1)))
End If
Question = MsgBox("Did you want to execute this vbscript : " & DblQuote(ShowAbsolutePath(arrFileName(1))),vbYesNo+vbQuestion,Title)
If Question = vbYes Then
ws.run DblQuote(ShowAbsolutePath(arrFileName(1)))
Else
End if
End Sub
' --------------------------------------
Function ShowAbsolutePath( strPath)
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
ShowAbsolutePath = fso.GetAbsolutePathName( strPath)
End Function
' --------------------------------------
Function DblQuote(Str)
DblQuote = Chr(34) & Str & Chr(34)
End Function
' --------------------------------------
Function CommandLineLike(ProcessPath)
ProcessPath = Replace(ProcessPath, "\", "\\")
CommandLineLike = "'%" & ProcessPath & "%'"
End Function
' --------------------------------------
Function AppPrevInstance()
With GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
With .ExecQuery("SELECT * FROM Win32_Process WHERE CommandLine LIKE " & CommandLineLike(WScript.ScriptFullName) & _
" AND CommandLine LIKE '%WScript%' OR CommandLine LIKE '%cscript%'")
AppPrevInstance = (.Count > 1)
End With
End With
End Function
' --------------------------------------

How to handle unavailable computers in WMI connections?

I want to assess the memory and other details of computers connected to my domain. What I am doing is writing the computer name in a text file, one per line. the Script will read the file (hostname) one by one, gather the information, and write it to a file. This is working fine.
Problem is that if one computer is not available then it's making problems. For example, if first host name is available and second is not available, then it keeps showing the same information repeatedly.
INPUT_FILE_NAME = "D:\tmp\Computer.txt"
Const FOR_READING = 1
Const HKEY_LOCAL_MACHINE = &H80000002
strRegKey = "SYSTEM\CurrentControlSet\Services\Tcpip\Parameters"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(INPUT_FILE_NAME, FOR_READING)
strComputers = objFile.ReadAll
objFile.Close
arrComputers = Split(strComputers, vbCrLf)
For Each strComputer In arrComputers
On Error Resume Next
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!" & _
"//./root/default:StdRegProv")
objReg.GetStringValue HKEY_LOCAL_MACHINE, strRegKey, "Hostname", strHostname
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colPageFiles = objWMIService.ExecQuery _
("Select * from Win32_PageFileUsage")
For each objPageFile in colPageFiles
Wscript.Echo "Host Name: " & strHostName, _
"AllocatedBaseSize: "& vbTab & objPageFile.AllocatedBaseSize, _
"CurrentUsage: "& vbTab & objPageFile.CurrentUsage, _
"Description: "& vbTab & objPageFile.Description, _
"InstallDate: "& vbTab & objPageFile.InstallDate, _
"Name: " & vbTab & objPageFile.Name, _
"PeakUsage: " & vbTab & objPageFile.PeakUsage
Next
Next
When GetObject() fails, the variable objWMIService retains its previous value, so you're reporting the same host over and over again, until either GetObject() can connect to a host or the loop terminates. Change this:
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colPageFiles = objWMIService.ExecQuery _
("Select * from Win32_PageFileUsage")
For each objPageFile in colPageFiles
Wscript.Echo "Host Name: " & strHostName, _
"AllocatedBaseSize: "& vbTab & objPageFile.AllocatedBaseSize, _
"CurrentUsage: "& vbTab & objPageFile.CurrentUsage, _
"Description: "& vbTab & objPageFile.Description, _
"InstallDate: "& vbTab & objPageFile.InstallDate, _
"Name: " & vbTab & objPageFile.Name, _
"PeakUsage: " & vbTab & objPageFile.PeakUsage
Next
into this:
Set objWMIService = Nothing
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
If Not objWMIService Is Nothing Then
Set colPageFiles = objWMIService.ExecQuery _
("Select * from Win32_PageFileUsage")
For each objPageFile in colPageFiles
Wscript.Echo "Host Name: " & strHostName, _
"AllocatedBaseSize: "& vbTab & objPageFile.AllocatedBaseSize, _
"CurrentUsage: "& vbTab & objPageFile.CurrentUsage, _
"Description: "& vbTab & objPageFile.Description, _
"InstallDate: "& vbTab & objPageFile.InstallDate, _
"Name: " & vbTab & objPageFile.Name, _
"PeakUsage: " & vbTab & objPageFile.PeakUsage
Next
Else
WScript.Echo strComputer & " unavailable."
End If
and the problem will disappear.
On a different note, the first 2 lines in the outer loop will always retrieve the hostname of your local computer:
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!" & _
"//./root/default:StdRegProv")
objReg.GetStringValue HKEY_LOCAL_MACHINE, strRegKey, "Hostname", strHostname
If that's what you actually want, you should move the code outside the loop, because the value of strHostname won't change:
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!" & _
"//./root/default:StdRegProv")
objReg.GetStringValue HKEY_LOCAL_MACHINE, strRegKey, "Hostname", strHostname
For Each strComputer In arrComputers
'...
Next
If you actually want the name of the remote computer (which would make a lot more sense when the rest of the information is from the remote computer as well), you could simply use strComputer and remove the registry query entirely.

VBS Code for Program Terminator

I would like a VBS code that:
Displays an input box to enter a process name
and can append the process to the code written below:
Option Explicit
Dim strComputer, strProcessToKill, objWMIService, colProcess, objProcess
strComputer = "."
strProcessToKill = "notepad.exe"
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer _
& "\root\cimv2")
Set colProcess = objWMIService.ExecQuery _
("Select * from Win32_Process Where Name = '" & strProcessToKill & "'")
For Each objProcess in colProcess
msgbox "... terminating " & objProcess.Name
objProcess.Terminate()
Next
Replace the line
strProcessToKill = "notepad.exe"
with
strProcessToKill = InputBox("Enter process name:")
You should add some safety checks, though, in case the user presses Cancel or presses OK without having anything entered:
If IsEmpty(strProcessToKill) Then
WScript.Echo "User pressed 'Cancel'."
WScript.Quit 1
ElseIf strProcessToKill = "" Then
WScript.Echo "Nothing entered."
WScript.Quit 1
End If

Basic VBS help - optimizing VBS script

I found this simple script that outputs the logical disk sizes.
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
("Select * from Win32_LogicalDisk")
For Each objDisk in colDisks
Wscript.Echo "DeviceID: " & objDisk.DeviceID & " with a Disk Size: " & objDisk.Size
Next
My VBS skills are very poor and I need help:
I would like to get a single size number of ONLY the C and D partitions added together
if the size (from step1) is not equal to 500-GB (between 450,000,000,000 and 550,000,000,000) I need the computer to prompt a warning and "press any key" to continue
I don't want a pop-up window since this is going to run from the prompt of WinPE, is it possible to get the output in the prompt window?
I'm asking a lot so thank you in advance if you can help
You will need to start your script using cscript.
The code for this comes from http://ask.metafilter.com/79481/vbscript-printing-to-command-line
This allows the echos to go to the command line instead of a Message box.
CheckStartMode
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colDisks = objWMIService.ExecQuery _
("Select * from Win32_LogicalDisk")
For Each objDisk in colDisks
If(objDisk.DeviceID="C:" or objDisk.DeviceID="D:") then
Wscript.Echo "DeviceID: " & objDisk.DeviceID & " with a Disk Size: " & objDisk.Size
TotalSize = CCur(TotalSize) + CCur(objDisk.Size)
End if
Next
If(TotalSize <450000000000 or TotalSize >550000000000) then
Wscript.Echo "Disk size of " & TotalSize & " is out of range."
Wscript.Echo "Press enter to contine."
z = WScript.StdIn.Read(1)
End if
Wscript.Echo "Complete, Press enter to end."
z = WScript.StdIn.Read(1)
Sub CheckStartMode
' Returns the running executable as upper case from the last \ symbol
strStartExe = UCase( Mid( wscript.fullname, instrRev(wscript.fullname, "\") + 1 ) )
If Not strStartExe = "CSCRIPT.EXE" Then
' This wasn't launched with cscript.exe, so relaunch using cscript.exe explicitly!
' wscript.scriptfullname is the full path to the actual script
set oSh = CreateObject("wscript.shell")
oSh.Run "cscript.exe """ & wscript.scriptfullname & """"
wscript.quit
End If
End Sub

How to monitoring folder files by vbs

Can anyone help me where i do mistake ?
this script is for monitoring folder for create, delete or modified text files
sPath = "C:\scripts\test"
sComputer = "."
sDrive = split(sPath,":")(0)
sFolders1 = split(sPath,":")(1)
sFolders = REPLACE(sFolders1, "\", "\\") & "\\"
Set objWMIService = GetObject("winmgmts:\\" & sComputer & "\root\cimv2")
Set colMonitoredEvents = objWMIService.ExecNotificationQuery _
("SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE " _
& "TargetInstance ISA 'CIM_DataFile' AND " _
& "TargetInstance.Drive='" & sDrive & "' AND " _
& "TargetInstance.Path='" & sFolders & "' AND " _
& "TargetInstance.Extension = 'txt' ")
Wscript.Echo vbCrlf & Now & vbTab & _
"Begin Monitoring for a Folder " & sDrive & ":" & sFolders1 & " Change Event..." & vbCrlf
Do
Set objLatestEvent = colMonitoredEvents.NextEvent
Select Case objLatestEvent.Path_.Class
Case "__InstanceCreationEvent"
WScript.Echo Now & vbTab & objLatestEvent.TargetInstance.FileName & "." & objLatestEvent.TargetInstance.Extension _
& " was created" & vbCrlf
Case "__InstanceDeletionEvent"
WScript.Echo Now & vbTab & objLatestEvent.TargetInstance.FileName & "." & objLatestEvent.TargetInstance.Extension _
& " was deleted" & vbCrlf
Case "__InstanceModificationEvent"
If objLatestEvent.TargetInstance.LastModified <> _
objLatestEvent.PreviousInstance.LastModified then
WScript.Echo Now & vbTab & objLatestEvent.TargetInstance.FileName & "." & objLatestEvent.TargetInstance.Extension _
& " was modified" & vbCrlf
End If
End Select
Loop
Set objWMIService = nothing
Set colMonitoredEvents = nothing
Set objLatestEvent = nothing
This script is run perfect when i write
sPath = "\\ComputerName\C$\scripts\test"
insted of
sPath = "C:\scripts\test"
Thank you....
If you google for "WMI TargetInstance.Drive", you'll see that the drive letter needs a colon. A query like
SELECT * FROM __InstanceOperationEvent WITHIN 1 WHERE TargetInstance ISA 'CIM_DataFile' AND TargetInstance.Drive='E:' AND TargetInstance.Path='\\trials\\SoTrials\\answers\\10041057\\data\\' AND TargetInstance.Extension = 'txt'
works as expected.

Resources