Skip to content

Instantly share code, notes, and snippets.

@wangye
Last active November 28, 2022 04:38
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save wangye/4491664 to your computer and use it in GitHub Desktop.
Save wangye/4491664 to your computer and use it in GitHub Desktop.
'
' Usage:
' WScript.exe srvany.vbs -name [ServiceName]
' -srvany [SrvAnyFileName]
' -file [ExeFileName]
' -dir [ExeFileDirectory]
' -params [ExeFileParameters]
'
' For more information please visit http://wangye.org
'
Option Explicit
Const HKLM = &H80000002
' Service Type
Const KERNEL_DRIVER = 1
Const FS_DRIVER = 2
Const ADAPTER = 4
Const RECOGNIZER_DRIVER = 8
Const OWN_PROCESS = 16
Const SHARE_PROCESS = 32
Const INTERACTIVE_PROCESS = 256
Const INTERACT_WITH_DESKTOP = FALSE
' Error Control
Const NOT_NOTIFIED = 0
Const USER_NOTIFIED = 1
Const SYSTEM_RESTARTED = 2
Const SYSTEM_STARTS = 3
Class CommandLineParser
' Written by WangYe
' http://wangye.org
Private parameters
Private splitargs
Private Sub Class_Initialize()
Set parameters = WSH.CreateObject("Scripting.Dictionary")
Set splitargs = WSH.CreateObject("Scripting.Dictionary")
End Sub
Private Sub Class_Terminate()
splitargs.RemoveAll
Set splitargs = Nothing
parameters.RemoveAll
Set parameters = Nothing
End Sub
Public Sub addSplitter(key, value)
splitargs.Add key, value
End Sub
Public Sub parse(args)
Dim i, j, k, token, c, statusChanged
Dim statusSkipped, tokens
Dim keys, items
statusChanged = False
keys = splitargs.Keys
items = splitargs.Items
For i = 0 To args.Count-1
If statusChanged Then
parameters.Add token, args(i)
statusChanged = False
End If
c = Left(Trim(args(i)), 1)
If c = "-" Then
statusChanged = True
statusSkipped = False
For j=2 To Len(args(i))-1
c = MID(args(i), j, 1)
statusSkipped = CBool(c = "-")
If Not statusSkipped Then Exit For
Next
token = Right(args(i), Len(args(i)) - j+1)
For k = 0 To splitargs.Count - 1
tokens = Split(token, items(k))
If UBound(tokens) > 0 Then
If keys(k) = tokens(0) Then
parameters.Add tokens(0), _
tokens(1)
statusChanged = False
End If
End If
Next
End If
If i = args.Count-1 And statusChanged Then
parameters.Add token, ""
End If
Next
End Sub
Public Sub dump()
Dim i, Keys, Items
Keys = parameters.Keys
Items = parameters.Items
For i = 0 To parameters.Count - 1
WSH.Echo Keys(i) & "=" & Items(i)
Next
End Sub
Public Function hasArgument(name)
hasArgument = parameters.Exists(name)
End Function
Public Function getArgument(name)
getArgument = ""
If parameters.Exists(name) Then
getArgument = parameters(name)
End If
End Function
Public Default Property Get Item(name)
Item = getArgument(name)
End Property
End Class
Sub RestartService( myService, blnQuiet )
' This subroutine restarts a service
' Arguments:
' myService use the service's DisplayName
' blnQuiet if False, the state of the service is displayed
' every second during the restart procedure
'
' Written by Rob van der Woude
' http://www.robvanderwoude.com
' Standard housekeeping
Dim colServices, colServicesTest, objService
Dim objServiceTest, objWMIService, strQuery, strTest
' Create a WMI object
Set objWMIService = GetObject( "winmgmts:\\.\root\CIMV2" )
' Query the services for "our" service
strQuery = "SELECT * FROM Win32_Service WHERE DisplayName='" & myService & "'"
Set colServices = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objService In colServices
' See if we need to tell the user we're going to stop the service
If Not blnQuiet Then
WScript.Echo "Stopping " & myService
End If
' Stop the service
objService.StopService
' Wait until the service is stopped
Do Until strTest = "Stopped"
' Create a new object for our service; this work-around is required
' since otherwise the service's state information isn't properly updated
Set colServicesTest = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objServiceTest In colServicesTest
' Check the service's state
strTest = objServiceTest.State
' See if we need to show the progress
If Not blnQuiet Then
WScript.Echo "State: " & strTest
End If
' Wait 1 second
WScript.Sleep 1000
Next
' Clear the temporary object
Set colServicesTest = Nothing
Loop
' See if we need to tell the user we're going to (re)start the service
If Not blnQuiet Then
WScript.Echo "Starting " & myService
End If
' Start the service
objService.StartService
' Wait until the service is running again
Do Until strTest = "Running"
' Create a new object for our service; this work-around is required
' since otherwise the service's state information isn't properly updated
Set colServicesTest = objWMIService.ExecQuery( strQuery, "WQL", 48 )
' Loop through the "collection" of returned services
For Each objServiceTest In colServicesTest
' Check the service's state
strTest = objServiceTest.State
' See if we need to show the progress
If Not blnQuiet Then
WScript.Echo "State: " & strTest
End If
' Wait 1 second
WScript.Sleep 1000
Next
' Clear the temporary object
Set colServicesTest = Nothing
Loop
Next
End Sub
Const L_Argument_Service_Name = "name"
Const L_Argument_SrvAnyFile_Name = "srvany"
Const L_Argument_AppFile_Name = "file"
Const L_Argument_AppParams_Name = "params"
Const L_Argument_AppDir_Name = "dir"
Function VBMain(argc, args)
VBMain = 0
If argc<1 Then
VBMain = -1
WSH.Echo "Usage: -name [ServiceName]" & vbCrLf & _
" -srvany [SrvAnyFileName]" & vbCrLf & _
" -file [ExeFileName]" & vbCrLf & _
" -dir [ExeFileDirectory]" & vbCrLf & _
" -params [ExeFileParameters]"
Exit Function
End If
Dim nResult
Dim strAppFileName, strAppParameters, strAppDirectory
Dim strComputer, strServiceName, strSrvAnyFileName
strComputer = "."
Dim objCommandLineParser
Set objCommandLineParser = New CommandLineParser
Call objCommandLineParser.parse(args)
' objCommandLineParser.dump
strServiceName = objCommandLineParser(L_Argument_Service_Name)
strSrvAnyFileName = objCommandLineParser(L_Argument_SrvAnyFile_Name)
strAppFileName = objCommandLineParser(L_Argument_AppFile_Name)
strAppParameters = objCommandLineParser(L_Argument_AppParams_Name)
strAppDirectory = objCommandLineParser(L_Argument_AppDir_Name)
If strServiceName = "" Then
WSH.Echo "Service Name is invalid (Usage: -name [ServiceName])"
VBMain = -2
Exit Function
End If
Dim objFileSystemObject
Set objFileSystemObject = WSH.CreateObject("Scripting.FileSystemObject")
If strSrvAnyFileName <> "" Then
strSrvAnyFileName = objFileSystemObject.GetAbsolutePathName(strSrvAnyFileName)
If Not objFileSystemObject.FileExists(strSrvAnyFileName) Then
strSrvAnyFileName = ""
End If
End If
If strSrvAnyFileName = "" Then
WSH.Echo "SrvAny File Name is invalid (Usage: -srvany [SrvAnyFileName])"
VBMain = -2
Exit Function
End If
If strAppFileName <> "" Then
strAppFileName = objFileSystemObject.GetAbsolutePathName(strAppFileName)
If Not objFileSystemObject.FileExists(strAppFileName) Then
strAppFileName = ""
End If
End If
If strAppFileName = "" Then
WSH.Echo "Application File Name is invalid (Usage: -file [SrvAnyFileName])"
VBMain = -2
Exit Function
End If
If strAppDirectory = "" Then
strAppDirectory = objFileSystemObject.GetParentFolderName(strAppFileName)
End If
Set objFileSystemObject = Nothing
Dim objWMI, objService
Set objWMI = GetObject("winmgmts:\\" & _
strComputer & "\root\cimv2")
Set objService = objWMI.Get("Win32_Service")
nResult = objService.Create( _
strServiceName , _
strServiceName , _
strSrvAnyFileName , _
OWN_PROCESS , _
NOT_NOTIFIED , _
"Automatic" , _
INTERACT_WITH_DESKTOP, _
"NT AUTHORITY\LocalService", _
"" _
)
Set objService = Nothing
Set objWMI = Nothing
If nResult > 0 Then
VBMain = nResult
Exit Function
End If
' Write Registry
Dim strKeyPath, objReg
strKeyPath = "SYSTEM\CurrentControlSet\Services\" & _
strServiceName & "\Parameters"
Set objReg = GetObject("winmgmts:\\" & _
strComputer & "\root\default:StdRegProv")
objReg.CreateKey HKLM,strKeyPath
objReg.SetStringValue HKLM, strKeyPath, "Application" , strAppFileName
objReg.SetStringValue HKLM, strKeyPath, "AppParameters" , strAppParameters
objReg.SetStringValue HKLM, strKeyPath, "AppDirectory" , strAppDirectory
Set objReg = Nothing
RestartService strServiceName, True
End Function
WSH.Quit(VBMain(WScript.Arguments.Count, WScript.Arguments))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment