Add And Remove Services Entries

This is a quick script I’ve used to add and remove entries to the windows services file. It ignores commented lines (lines starting with a hash (#)), and it also doesn’t validate the format of the host or port/protocol so use with care!

Usage

cscript.exe services.vbs “Add” “localhost” “8080/http”
cscript.exe services.vbs “Remove” “localhost” “8080/http”

Option Explicit

Const ForReading = 1
Const ForWriting = 2
Const ReadOnly = 1

'Usage
'cscript.exe services.vbs "Add" "host" "port/protocol" 
'cscript.exe services.vbs "Remove" "host" "port/protocol"

If (wscript.arguments.count < 3) Then
	'need a verb, host and port
	Wscript.quit
End If

'Add/Remove
dim inputAction : inputAction = wscript.arguments(0)

dim inputhostName : inputhostName = wscript.arguments(1)

dim inputPortProtocol : inputPortProtocol = wscript.arguments(2)

dim oFSO : Set oFSO = CreateObject("Scripting.FileSystemObject")

dim objShell : Set objShell = CreateObject("WScript.Shell")
dim strSystemRoot : strSystemRoot = objShell.ExpandEnvironmentStrings("%systemroot%")
dim pathToHosts : pathToHosts = strSystemRoot & "\system32\drivers\etc\services"

'make changes in memory first - we need to open it in write mode first otherwise we get 'Bad file mode' error
dim hostsFile : Set hostsFile = oFSO.OpenTextFile(pathToHosts, ForReading, true)
'get original read from file.  We'll amend hosts in memory until we commit changes at the end
dim hostsContent
If Not hostsFile.AtEndOfStream Then hostsContent = hostsFile.ReadAll

dim hostEntry

if (inputAction = "Add") Then
	hostsContent = AddServicesEntry(inputhostName,inputPortProtocol)
End If

if (inputAction = "Remove") Then
	hostsContent = RemoveServicesEntry(inputhostName,inputPortProtocol)
End If

hostsFile.Close()

'set attribute to read/write if readonly
dim objFile : Set objFile = oFSO.GetFile(pathToHosts)
If objFile.Attributes AND ReadOnly Then
    objFile.Attributes = objFile.Attributes XOR ReadOnly
End If

'then write changes to actual file
Set hostsFile = oFSO.OpenTextFile(pathToHosts, ForWriting, true)
hostsFile.Write hostsContent
hostsFile.Close()
    
Function RemoveServicesEntry(hostName, portProtocol)
  
	dim objRegEx : Set objRegEx = CreateObject("VBScript.RegExp")
	objRegEx.Pattern = "^(?!#)(" & hostName & ")(\s|\t)+" & portProtocol

	dim strNewContents : strNewContents = ""
	
	dim hostsContentLines : hostsContentLines = Split(hostsContent,vbCrlf)
	For each hostEntry in hostsContentLines
		If NOT objRegEx.Test(hostEntry) Then	
			strNewContents = strNewContents & hostEntry & vbCrLf		
		End If
	Next
	  
	'remove last carriage return	
	If Right(strNewContents, 2) = vbCrLf Then
		strNewContents = Left(strNewContents, Len(strNewContents) - 2)
	End If
	
	Set objRegEx = Nothing
	
	RemoveServicesEntry = strNewContents

End Function

Function AddServicesEntry(hostName, portProtocol)
  
	dim objRegEx : Set objRegEx = CreateObject("VBScript.RegExp")
	objRegEx.Pattern = "^(?!#)(" & hostName & ")(\s|\t)+" & portProtocol

	dim strNewContents : strNewContents = ""
	dim portProtocolExists : portProtocolExists = false	
	
	dim hostsContentLines : hostsContentLines = Split(hostsContent,vbCrlf)
	For each hostEntry in hostsContentLines
		If objRegEx.Test(hostEntry) Then
			portProtocolExists = true	
		End If
		strNewContents = strNewContents & hostEntry & vbCrLf
	Next
			  
	If Not portProtocolExists Then
		strNewContents = strNewContents & hostName & vbTab & portProtocol 
	End If
	
	'remove last carriage return	
	If Right(strNewContents, 2) = vbCrLf Then
		strNewContents = Left(strNewContents, Len(strNewContents) - 2)
	End If
	
	Set objRegEx = Nothing
	
	AddServicesEntry = strNewContents

End Function


Set hostsFile = Nothing
Set objFile = Nothing
Set oFSO = Nothing
Set objShell = Nothing

and here’s an example of how it can be called from another vbscript:

Option Explicit

Dim objFSO : Set objFSO = CreateObject("Scripting.FilesystemObject")
Dim objShell : Set objShell = CreateObject("Wscript.Shell")

dim strFolder : strFolder = objFSO.GetParentFolderName(WScript.ScriptFullName) 
dim strScript : strScript = strFolder & "\services.vbs"

If objFSO.FileExists(strScript) Then

	'example to add an entry
	addEntry "localhost","8080/tcp"
	'addEntry "localhost","8080/udp"

	'example to remove an entry
	'removeEntry "localhost","8080/udp"

End If

Function addEntry(host, portProtocol)

	dim commandLine : commandLine = chr(34) & strScript & chr(34) & " " & chr(34) & "Add" & chr(34) & " " & chr(34) & host & chr(34) & " " & chr(34) & portProtocol & chr(34)
	objShell.Run "cscript.exe " & commandLine

End Function

Function removeEntry(host, portProtocol)

	dim commandLine : commandLine = chr(34) & strScript & chr(34) & " " & chr(34) & "Remove" & chr(34) & " " & chr(34) & host & chr(34) & " " & chr(34) & portProtocol & chr(34)
	objShell.Run "cscript.exe " & commandLine

End Function

Set objFSO = Nothing
Set objShell = Nothing