delete multiple specific local user accounts from servers - vbscript

I am trying to write a VBScript to delete specific user account from server.
If in server found the users "adm" and/or "ame" the script should delete them and also print the result whether the deletion was successful or not.
Below is the script which I tried writing and I am getting an error. Can anyone help me to correct this?
Dim disuser, objNetwork, strComputer, objComputer
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.ComputerName
Set objComputer = GetObject("WinNT://" & strComputer)
On Error Resume Next
For Each disuser In "adm ame"
Call objComputer.Delete("user", disuser)
On Error GoTo 0
Next
'On Error res="fail"

If you want to pass multiple usernames as a list this is fine, but to enumerate them using a For Each they need to be enumerable in other words an object that supports enumeration like an Array or Collection.
Dim disuser, objNetwork, strComputer, objComputer
Set objNetwork = CreateObject("Wscript.Network")
strComputer = objNetwork.ComputerName
Set objComputer = GetObject("WinNT://" & strComputer)
On Error Resume Next
'Split list of space delimited usernames into an Array.
Dim list: list = Split("adm ame", Chr(32))
For Each disuser In list
'Clear previous error before checking if the Delete works.
Call Err.Clear()
Call objComputer.Delete("user", disuser)
If Err.Number = 0 Then
'Was successful do something
Else
'Failed do something
End If
Next
On Error GoTo 0
'On Error res="fail"

Related

Need VBScript to list disabled accounts

The following script check local computers for inactive (90 days or more) accounts and disables them. The script works fine, but it lists all the disabled accounts every time is executed. I only need it to list the accounts that have been disabled the day is was executed.
Option Explicit
Dim objNetwork, strComputer, objComputer, objUser, dtmLast, objGroup, ObjGroupDict
Dim FSO, OutPutFile
Set FSO = CreateObject("Scripting.FileSystemObject")
'1 = reading, 2 = writing, and 8 = appending. The third parameter is a
'boolean true means a new file can be created if it doesn't exist. False
'means a new file cannot be created.
Set OutPutFile = FSO.OpenTextFile("C:\Test\Result.log", 8, True)
'Bind to the local computer.
Set objNetwork = CreateObject("WScript.Network")
strComputer = objNetwork.ComputerName
Set objComputer = GetObject("WinNT://" & strComputer & ",computer")
'Enumerate all users.
objComputer.Filter = Array("user")
For Each objUser In objComputer
Set ObjGroupDict = CreateMemberOfObject(objUser)
If ((Left(objUser.Name,3) <> "au_") And (CBool(ObjGroupDict.Exists("Administrators") = False))) Then
'Trap error if user never logged in.
On Error Resume Next
dtmLast = objUser.lastLogin
If (Err.Number <> 0) Then
dtmLast = #1/1/1970#
End If
On Error GoTo 0
'Check if last logon was more than 90 days in the past.
If (DateDiff("d", dtmLast, Now()) > 90) Then
'Disable the user.
objUser.AccountDisabled = True
objUser.SetInfo
OutPutFile.WriteLine(Now & " " & strComputer & " " & Wscript.ScriptName & " " & objUser.Name & " " & "Disabled")
'MsgBox objUser.Name
Set FSO = Nothing
End If
End If
Next
Function CreateMemberOfObject(objUser)
'Given a domain name and username, returns a Dictionary
'object of groups to which the user is a member of.
'Inputs: objUser - User Object
Set CreateMemberOfObject = CreateObject("Scripting.Dictionary")
CreateMemberOfObject.CompareMode = vbTextCompare
Dim objGroup
For Each objGroup In objUser.Groups
CreateMemberOfObject.Add objGroup.Name, "-"
Next
End Function
You're disabling all accounts whose last login was more than 90 days ago, even if the account already is disabled. Add a condition that matches only accounts that are not disabled, and the code will do what you want:
If DateDiff("d", dtmLast, Now) > 90 And Not objUser.AccountDisabled Then
...
End If

Scriptcontrol object returns recordset object

I am creating a library using vbscript and using scriptcontrol object to call these routines from vba. I am trying to create a recordset as a routine with the given sql as parameter as below
sub GetData(sql, byref retrst)
stADO = "Provider=SQLOLEDB.1;Persist Security Info=False;Initial
Catalog=CCMSProd;Data Source=sv-hfi-ccms;UID=vc;PWD=dw;"
cnconn as adoconnection
Set cnconn = CreateObject("ADODB.Connection")
cnconn.Open stADO
msgbox cnconn.ConnectionString
msgbox cnconn.state
With cnconn
.CommandTimeout = 0
Set retrst = .Execute(sql)
msgbox retrst.recordcount
End With
cnconn.close
end sub
and calling this routine as below
scr.Run "GetConnection", tempload, rst
but my recordset returns as nothing, eventhough the connection and recordset created within vbscript.
I need help in this.
There are quite a few problems with your script. I'm not going to go in to each one but be aware that the recordset open call has more parameters. They aren't required but the defaults are adForwardOnly for the cursor type, and adLockReadOnly for locking. Using the defaults will not enable you to get a record count from the recordset so the code I provide just shows the value of the first record in the recordset to indicate data was retrieved.
https://support.microsoft.com/en-us/help/272067/how-to-get-a-record-count-from-a-sql-server-ce-recordset
The code below works but you'll need to modify it for your usage.
Batch file to run the script:
GetRecordset.bat
cscript.exe /nologo GetRecordset.vbs
pause
Script to run:
GetRecordset.vbs
Dim objADORecordset
Dim strDBTableName
On Error Resume Next
'*****Modify below to a table name in your database*****
strDBTableName = "SomeDBTableName"
Set objADORecordset = CreateObject("ADODB.Recordset")
If Err.Number = 0 Then
GetRecordset "SELECT * FROM " & strDBTableName, objADORecordset
With objADORecordset
If Not .BOF Then
.MoveFirst
WScript.Echo "Field 0: " & .Fields(0).Value
Else
WScript.Echo "No records in recordset"
End If
End With
Else
WScript.Echo "Unable to create ADO Recordset"
End If
set objADORecordset = Nothing
WScript.Quit
'*********************************************
Sub GetRecordset(astrSQLQuery, aobjRecordset)
Dim strOLEConnect
Dim strUserID
Dim strUserPW
Dim objADOConnection
On Error Resume Next
WScript.Echo "SQLQuery: " & astrSQLQuery
strOLEConnect = "Provider=SQLOLEDB.1;Persist Security Info=False;Initial Catalog=CCMSProd;Data Source=sv-hfi-ccms;UID=vc;PWD=dw;"
strUserID = "vc"
strUserPW = "dw"
Set objADOConnection = CreateObject("ADODB.Connection")
If Err.Number = 0 Then
objADOConnection.Open strOLEConnect, strUserID, strUserPW
If Err.Number = 0 Then
aobjRecordset.Open astrSQLQuery, objADOConnection
If Err.Number <> 0 Then
WScript.Echo "Recordset open failed ERROR=" & Err.Number
End If
Else
WScript.Echo "Connection open failed ERROR=" & Err.Number
End If
Else
WScript.Echo "ADO connection failed ERROR=" & Err.Number
End If
Set objADOConnection = Nothing
End Sub
I left it similar to your code so you can understand it but it should really create and open the ADO connection before the ADORecordset. You would typically open the connection, run all of the required queries and process them before closing the connection. There's no sense in creating a new connection to the same database multiple times for different queries to the same database. It just adds unnecessary overhead. I'll leave it to you to improve the code for your use.

ignore workstations that are offline and resume

I have this VBScript to help me remove local users from the local admins. I can't seem to get it to ignore workstations that are not on the network.
Is there a way to ignore workstations that are not found and have it continue to the next line under the computers.txt file?
For example, say PC1 and PC3 are found but PC2 is not found I want it to ignore not found workstations and continue until the end of the list of computers.
I've tried On Error Resume Next (didnt work), and I tried Const ForReading = 1, Const ForAppending = 8, Const OverwriteExisting = True (didnt work either).
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\adminScript\computers.txt")
strComputer = objFile.ReadLine
Set objGroup = GetObject("WinNT://" & strComputer & "/Administrators")
For Each objUser In objGroup.Members
If objUser.Name <> "Administrator" AND objUser.Name <> "Domain Admins" AND objUser.Name <> "G_SCCMAgent" AND objUser.Name <> "User" Then
Wscript.Echo objUser.Name
objGroup.Remove(objUser.ADsPath)
End If
Next
wscript.Echo "I am done!"
Contrary to popular belief On Error Resume Next doesn't magically make errors go away. Neither does defining symbolic constants for parameters of the OpenTextFile method.
If you want to skip over computers that aren't available you need to actually test the availability of each computer. A common way to do this is the Win32_PingStatus WMI class.
Set wmi = GetObject("winmgmts://./root/cimv2")
isAvailable = False
qry = "SELECT * FROM Win32_PingStatus WHERE Address='" & strComputer & "'"
For Each res In wmi.ExecQuery(qry)
If res.StatusCode = 0 Then isAvailable = True
Next
If isAvailable Then
'modify administrators group
End If
Also, you probably need to process the content of computers.txt in a loop. Your current code reads only the first line. To process more than one line from the file use something like this:
Set objFile = objFSO.OpenTextFile("C:\adminScript\computers.txt")
Do Until objFile.AtEndOfStream
strComputer = objFile.ReadLine
'...
Loop
objFile.Close

Attempting to extract printers from users machine and then outputting to a text fill.

I am attempting to extract the printers from a users machine and then output to a text file but when I run the test I get a invalid procedure call or argument for this specific line of code.
Set objOutputFile = objFSO.OpenTextFile(outFile, ForAppending, True)
I have attempted to change OpenTextFileto CreateTextFile but I need the lines to appended to file as it will be running as a log on script.
I have done some research and used the Microsoft developer articles to help me debug the issue in the code but I don't have much experience in Visual Basic.
I have added the entire script to give context to the what is going on.
dim objComputerName, ObjNetwork , strText , objfile, StrComputer
dim wshnetwork
Set wshnetwork = CreateObject ("Wscript.network")
StrComputer = WshNetwork.ComputerName
If IsEmpty(StrComputer) Then Wscript.Quit
Set WshNetwork = CreateObject("WScript.Network")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")
Set colInstalledPrinters = objWMIService.ExecQuery("Select * from Win32_Printer")
Set colItems = objWMIService.ExecQuery("Select * from Win32_ComputerSystem",,48)
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
outFile = "C:\scripts\Printers" & StrComputer
Set objOutputFile = objFSO.OpenTextFile(outFile, ForAppending, True)
For Each objPrinter in colInstalledPrinters
strTest = Left(objPrinter.Name, 2)
objOutputFile.WriteLine(objPrinter.Name)
objfile.close
Next
Set objPrinter = WshNetwork.EnumPrinterConnections
'Set objOutputFile = objFSO.OpenTextFile (filOutput, ForAppending, True)
If objPrinter.Count = 0 Then
WScript.Echo "No Printers Mapped "
else
For intDrive = 0 To (objPrinter.Count -1) Step 2
intNetLetter = IntNetLetter +1
printer = "UNC Path " & objPrinter.Item(intDrive) & " = " & objPrinter.Item(intDrive +1) & " Printer : " & intDrive
objOutputFile.WriteLine(printer)
Next
end if
objOutputFile.Close``*
Invalid procedure call or argument
You passed an invalid parameter in your procedure call. This could be because the parameter was out of range, or contained invalid data. Alternately, you may have invoked a procedure at an unexpected time.
To correct this error
Verify that the parameters being passed to the procedure are valid.
Verify that you are calling the function at an appropriate time.
My guess is this line is an ilegal filename.
outFile = "C:\scripts\Printers" & StrComputer
On my computer this is c:\scripts\PrintersSerenity which is probably not right that your text file is called PrintersSerenity without an extension.

how to add a log to my vbscript

i have this script that reads a list of computers and check to see if the computers have the right software version install. the script echo to me the computers with the wrong version, but i want to make a log instead
Dim strComputer, objFSO, ObjShell, strDisplayName, objList, strObject
Dim objReg, arrSubKeys, strProduct, strVersion, strReqVersion
Const For_Writing = 2
Const ForReading = 1
const ForAppending = 3
Const HKLM = &H80000002
Const strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
strReqVersion = "8.2.1 MP2"
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject("WScript.Shell")
Set objList = objFSO.OpenTextFile("c:\test\test.txt",ForReading)
Do While Not objList.AtEndOfStream
strComputer = objList.ReadLine
If HostOnline(strComputer) = True Then
Inventory(strComputer)
End If
Loop
Function Inventory(strComputer)
Set objTextFile = objFSO.OpenTextFile("c:\test\inventory.txt",2,true)
'creating a dictionary object
Set objDictionary = CreateObject("Scripting.Dictionary")
Set objReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _
strComputer & "\root\default:StdRegProv")
' Enumerate the subkeys of the Uninstall key
objReg.EnumKey HKLM, strKeyPath, arrSubKeys
For Each strProduct In arrSubKeys
' Get the product's display name
objReg.GetStringValue HKLM, strKeyPath & "\" & strProduct, "DisplayName", strDisplayName
' Process only products whose name contain 'symantec'
If InStr(1, strDisplayName, "Symantec", vbTextCompare) > 0 Then
' Get the product's display version
objReg.GetStringValue HKLM, strKeyPath & "\" & strProduct, "DisplayVersion", strVersion
If strReqVersion <> strVersion Then
WScript.Echo strObject
objDictionary.Add strComputer, strVersion
For Each strObject In objDictionary
WScript.Echo strObject
objTextFile.WriteLine(strObject)
Next
objTextFile.Close
End If
End If
Next
End Function
Function HostOnline(strComputername)
'---------- Test to see if host or url alive through ping -----------------
' Returns True if Host responds to ping
'
' strComputername is a hostname or IP
Const OpenAsASCII = 0
Const FailIfNotExist = 0
Const ForReading = 1
Dim objShell, objFSO, sTempFile, fFile
Set objShell = CreateObject("WScript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
sTempFile = objFSO.GetSpecialFolder(2).ShortPath & "\" & objFSO.GetTempName
objShell.Run "cmd /c ping -n 2 -l 8 " & strComputername & ">" & sTempFile, 0 , True
Set fFile = objFSO.OpenTextFile(sTempFile, ForReading, FailIfNotExist, OpenAsASCII)
Select Case InStr(fFile.ReadAll, "TTL=")
Case 0
HostOnline = False
Case Else
HostOnline = True
End Select
ffile.close
objFSO.DeleteFile(sTempFile)
Set objFSO = Nothing
Set objShell = Nothing
End Function
can some one help me please thanks
There are several ways to do this. The simplest way, without any modification to your script, would be to call the script with cscript.exe (in a command prompt) and redirect the output to a file:
cscript your.vbs > output.log
However, if you want a log to be created even when users double-click your script you'll have to change your script so that it writes to a file instead of echoing the output. Open the log file at the beginning of the script:
Set myLog = objFSO.OpenTextFile("C:\my.log", For_Writing, True)
replace WScript.Echo ... with myLog.WriteLine ..., and close the file before you exit from the script:
myLog.Close
A somewhat more sophisticated approach would be to create a set of logging functions, which will allow you create log lines depending on certain conditions, e.g. LogInfo() for informational log messages and LogError() for errors.
Shameless plug: Some time ago I got fed up with writing the same boilerplate logging functions over and over again, so I wrote a logger class that encapsulates the usual logging facilities (interactive console, files, eventlog) and provides logging methods for 4 log levels (Error, Warning, Information, Debug). The class can be used for logging to a file like this:
Set myLog = New CLogger
myLog.LogToConsole = False
myLog.LogFile = "C:\my.log"
myLog.LogInfo "info message"
...
myLog.LogError "an error occurred"
The log file is automatically closed when the object is released.
Why not use the system's event log? I described how in this answer
It means most of the work is done for you and you don't need to worry about where to put your log file

Resources