Show logging for a vbs script - vbscript

I have a script i use for uninstalling an application
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
& "{impersonationLevel=impersonate}!\\" _
& strComputer & "\root\cimv2")
Set colSoftware = objWMIService.ExecQuery _
("Select * from Win32_Product " _
& "Where Name = 'Personnel database'")
For Each objSoftware in colSoftware
Wscript.Echo "Name: " & objSoftware.Name
Wscript.Echo "Version: " & objSoftware.Version
objSoftware.Uninstall()
Next
The problem is i don't know if the
Has started running or has completed
uninstall has completed
Has completed
Is there a way to show this in a log file or a console.
Thanks

Uninstall has completed when Uninstall returns with return code 0. Having your script log something is entirely up to you, though. You could write stuff to a log file or the eventlog, show a MsgBox or write text to the console (when running with cscript.exe).
A while ago I wrote this to simplify the handling (if you'll forgive the shameless plug). You could use it like this:
'insert class code here
Set clog = New CLogger
clog.LogToConsole = False
clog.LogFile = "C:\path\to\your.log"
clog.IncludeTimestamp = True
clog.Log "Starting"
'...
For Each objSoftware in colSoftware
clog.Log "Uninstalling " & objSoftware.Name & " (v" & objSoftware.Version & ")"
rc = objSoftware.Uninstall()
If rc = 0 Then
clog.Log "Uninstall complete"
Else
clog.LogError "An error occurred: " & rc
End If
Next
clog.Log "Finished"

You could always put msgbox in your script in your for each loop
MsgBox("Uninstalling " + objSoftware.Name)
or you could do a simple in your for each loop
Wscript.Echo "Uninstalling " + objSoftware.Name
Just run your vbs from admin command prompt window open
wscript uninstallfile.vbs
This will show up in your command console.

Related

Script to display a pop-up and then kills a windows process

I'm trying to deploy an application through SCCM 2012 for Windows7 (x86 and x64) that requires to notify the user that his Microsoft Outlook should be closed before to continue with the installation. It could be either with a Timer or a (Yes / No) choice, then if the user press Yes then it will close Outlook and will continue with the installation otherwise it will send a log file saying the the user cancelled the installation but it can be retried at any time.
So far I just have the installation script that works only to install the applications using a command line script. So, it will just execute some MSI's installations and Windows updates, and then it quits.
The script I have that creates the pop up and that can be called by my CMD file is the following VBScript and was taken from a TechNet article.
Const TIMEOUT = 7
Set objShell = WScript.CreateObject("WScript.Shell")
Set objFS = WScript.CreateObject("Scripting.FileSystemObject")
strPath = Wscript.FullName
strFileVersion = objFS.GetFileVersion(strPath)
iRetVal = objShell.Popup(Wscript.FullName & vbCrLf & _
"File Version: " & _
strFileVersion & vbCrLf & _
"Would you like to close Outlook application and continue with the installation?" _
,TIMEOUT,"Outlook Validation",vbYesNo + vbQuestion)
Select Case iRetVal
Case vbYes
Set objFile = objFS.GetFile(strPath)
objShell.Popup WScript.FullName & vbCrLf & vbCrLf & _
"File Version: " & strFileVersion & vbCrLf & _
"File Size: " & Round((objFile.Size/1024),2) & _
" KB" & vbCrLf & _
"Date Created: " & objFile.DateCreated & vbCrLf & _
"Date Last Modified: " & objFile.DateLastModified & _
vbCrLf,TIMEOUT
Wscript.Quit
Case vbNo
Wscript.Quit
Case -1
WScript.StdOut.WriteLine "Popup timed out."
Wscript.Quit
End Select
So I don't know if there's any useful example that I can use and customize it from there. I'm clueless, blindfolded, I don't see the light. Well you understand my frustration.
Any ideas, examples or links will be really appreciated!!
Thanks & kind regards.
Joel.
This is one way.
Set objWMIService = GetObject("winmgmts:\\.\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * From Win32_Process")
For Each objItem in colItems
'msgbox objItem.name & " " & objItem.CommandLine
If LCase(objItem.name) = "outlook.exe" then
If Msgbox("Close Outlook", 33, "Install") = 1 then
objItem.terminate
End If
End If
Next
VBScript's Help file - https://www.microsoft.com/en-au/download/details.aspx?id=2764
For help with the WMI object use wmic at the command prompt.
wmic process get /? (same as wmic path win32_process get /?) and wmic process call /? list properties and methods.
Here my procedure which closes outlook before modifying the profile.
Is is part of a logon script. The show is a logging and informing procedure.
sub CloseOutlook
on error resume next 'to be able to log and continue
dim objWMIService, colProcessList, objProcess, sResult, oShell
set oShell = WScript.CreateObject("WScript.Shell")
set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\.\root\cimv2")
set colProcessList = objWMIService.ExecQuery ("Select * from Win32_Process Where Name = 'OUTLOOK.EXE'")
for Each objProcess in colProcessList
show "outlook is being closed"
objProcess.Terminate()
if Err <> 0 then
show "Error while closing outlook: " & err.Description
end if
sResult = oShell.Popup("Outlook is being closed, profile is configured")
next
end sub
If you want confirmation from the user you will have to use a MsgBox instead.
I'd recommend not faffing about with warnings and closing Outlook, but instead configure the advert to run when no users are logged in. Less chance for problems or accidentally miss-clicked "oh no you lost my emails" situations.

How to check the current windows command prompt is hidden by using vbscript or command lines

I want to detecting if the current running bat script is hidden by the caller, that means (nCmdShow=0) for example.
There is windows API to get this information, GetStartupInfo, but it can not be called by command prompt or VBScript(without third party libraries).
The following script can retrieve the startup information, but the problem is that's only works under WinXp, it's doesn't work under Win7. I am looking for a way can support across winxp - win8.
Dim wmiService
Set wmiService = GetObject("winmgmts:\\.\root\cimv2")
Dim startupInfo
Set startupInfo = wmiService.Get("Win32_ProcessStartup")
The following code works fine under xp, but doesn't work under win7, it's show all the startup information.
On Error Resume Next
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\cimv2")
Set colItems = objWMIService.ExecQuery("Select * from Win32_ProcessStartup",,48)
For Each objItem in colItems
Wscript.Echo "CreateFlags: " & objItem.CreateFlags
Wscript.Echo "EnvironmentVariables: " & objItem.EnvironmentVariables
Wscript.Echo "ErrorMode: " & objItem.ErrorMode
Wscript.Echo "FillAttribute: " & objItem.FillAttribute
Wscript.Echo "PriorityClass: " & objItem.PriorityClass
Wscript.Echo "ShowWindow: " & objItem.ShowWindow
Wscript.Echo "Title: " & objItem.Title
Wscript.Echo "WinstationDesktop: " & objItem.WinstationDesktop
Wscript.Echo "X: " & objItem.X
Wscript.Echo "XCountChars: " & objItem.XCountChars
Wscript.Echo "XSize: " & objItem.XSize
Wscript.Echo "Y: " & objItem.Y
Wscript.Echo "YCountChars: " & objItem.YCountChars
Wscript.Echo "YSize: " & objItem.YSize
Next
There is a way of calling API calls in VBS or batch.
appactivate between multiple internet explorer instances
Although the sample given doesn't work 7 and later because of a name conflict. Rename sendmail to something else for 7 and later.
If a limited user you need to manually add the registry entries to hkcu\software\classes.

Can't get WMI namespace RSOP to work

I need to create a subroutine to check for certain policies on a system. I'm currently just trying to do that.
strComputerFQDN is defined at the beginning of the program and that is working fine.
Do you see anything wrong?
Here is my code:
'*************************************************************************
' This Subroutine checks Local Policies
'*************************************************************************
Sub CheckPolicies()
Dim objGPOSrvc,colItems,objItem
Set objGPOSrvc = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputerFQDN & "\root\RSOP")
Set colItems = objGPOSrvc.ExecQuery("SELECT * FROM RSOP_GPO")
WScript.Echo("Check Policies")
WScript.Echo("------------------------------------")
For Each objItem in colItems
If InStr(UCase(objItem.Name),"WSUS") Then
If InStr(UCase(objItem.Name),"SERVER") Then
WScript.Echo("Policy applied: " & objItem.Name)
Else
WScript.Echo("Wrong WSUS Policy Applied - Check Computer object location")
End If
End If
Next
If strWSUSApplied = "FALSE" Then
WScript.Echo("No WSUS Policy Applied!")
End If
WScript.Echo vbCrLf
End Sub
The namespace should be root\RSOP\Computer
Set objGPOSrvc = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputerFQDN & "\root\RSOP\Computer")
or root\RSOP\User
Set objGPOSrvc = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputerFQDN & "\root\RSOP\User")
Most typically you would do something like this:
strComputer = "."
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strComputer & "\root\RSOP\Computer")
Set colItems = objWMIService.ExecQuery("Select * from RSOP_GPO")
For Each objItem in colItems
WScript.Echo "Name: " & objItem.Name
WScript.Echo "GUID Name: " & objItem.GUIDName
WScript.Echo "ID: " & objItem.ID
WScript.Echo "Access Denied: " & objItem.AccessDenied
WScript.Echo "Enabled: " & objItem.Enabled
WScript.Echo "File System path: " & objItem.FileSystemPath
WScript.Echo "Filter Allowed: " & objItem.FilterAllowed
WScript.Echo "Filter ID: " & objItem.FilterId
WScript.Echo "Version: " & objItem.Version
WScript.Echo
Next
If you receive Error 0x80041003, you will need to run this script with administrator credentials. For Vista and later, open your start menu and type cmd. When "Command Prompt" appears, right-click and choose Run As Administrator. You can now launch your script from the elevated command prompt without error.

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

VbScript, Install exe remotely without user input?

I'm really stuck on a problem so I figured I would get a second opinion(s).
I'm trying to remotely install .exe and .msi to client computers. I have a vb script that downloads the file and runs the file, but there's a few problems. First, I'm having trouble getting it to the run on the local admin account. For testing purposes I'm running it as an Admin and it works fine, but if put on a client computer it would need access to the local Admin.
Secondly, and more importantly, microsoft requires some amount of user input before installing an exe file. I know silent msi install is possible, but I assume silent exe is impossible?
As a solution I'm looking into PsExec, but I feel like I'm missing something here.
For reference, here is my vb script:
Dim TApp
Dim IEObj
Dim tArea
Dim tButton
Const HIDDEN_WINDOW = 12
Const SHOW_WINDOW=1
'Array of Patch files to install.
Dim InstallFiles()
'maximum of 100 workstations to install patches to.
Dim wsNames(100)
Dim numComputers
Dim retVal
Dim PatchFolder
'Create explorer window
Set IEObj=CreateObject("InternetExplorer.Application")
IEObj.Navigate "about:blank"
IEObj.Height=400
IEObj.Width=500
IEObj.MenuBar=False
IEObj.StatusBar=False
IEObj.ToolBar=0
set outputWin=IEObj.Document
outputWin.Writeln "<title>RemotePatchInstall version 1.0</title>"
outputWin.writeln "<HTA:APPLICATION ID='objPatchomatic' APPLICATIONNAME='Patchomatic' SCROLL='no' SINGLEINSTANCE='yes' WINDOWSTATE='normal'>"
outputWin.writeln "<BODY bgcolor=ButtonFace ScrollBar='No'>"
outputWin.writeln "<TABLE cellSpacing=1 cellPadding=1 width='75pt' border=1>"
outputWin.writeln "<TBODY>"
outputWin.writeln "<TR>"
outputWin.writeln "<TD>"
outputWin.writeln "<P align=center><TEXTAREA name=Information rows=6 cols=57 style='WIDTH: 412px; HEIGHT: 284px'></TEXTAREA></P></TD></TR>"
outputWin.writeln "<TR>"
' outputWin.writeln "<TD><P align=center><INPUT id=button1 style='WIDTH: 112px; HEIGHT: 24px' type=button size=38 value='Install Patches' name=button1></P></TD>"
outputWin.writeln "</TR>"
outputWin.writeln "<TR>"
outputWin.writeln "<TD></TD></TR></TBODY></TABLE>"
outputWin.writeln "</BODY>"
IEObj.Visible=True
'Get the Information textarea object from the window
set tempObj=outputWin.getElementsByName("Information")
objFound=false
'loop through its object to find what we need
For each objN in tempObj
if objN.name="Information" then
objFound=true
set tArea=objN
end if
next
'if we didnt find the object theres a problem
if ObjFound=False then
'so show an error and bail
MsgBox "Unable to access the TextBox on IE Window",32,"Error"
WScript.Quit
end if
'*************************
'ADMINS: The below is all you should really have to change.
'*************************
'Change this to the location of the patches that will be installed.
'they should be limited to the amout you try to install at one time.
'ALSO the order they are installed is how explorer would list them by alphabetically.
'So given file names:
'patch1.exe
'patch2.exe
'patch11.exe
'installation order would be patch1.exe,patch11.exe, patch2.exe
PatchFolder="C:\IUware Online\Install\"
'Change this to location where the patches will be copied to on remote cp. This directory must exist on remote computer.
'I have it hidden on all workstations.
RemotePatchFolder="C:\Users\jorblume\Backup\"
'Workstation names to refer to as array
wsNames(1)="129.79.205.153"
'wsNames(2)="192.168.0.11"
'number of remote computers
numComputers=1
'**********************
'ADMINS: The above is all you should really have to change.
'**********************
'Copy files to remote computers.
'Get a list of the executable file in the folder and put them into the InstallFiles array
'on return, retVal will be number of files found.
retVal=GetPatchFileList (PatchFolder,InstallFiles)
'for each file copy to remote computers
For cc=1 to numComputers 'for each computer
For i = 1 to retVal 'for each file
Dim copySuccess
Dim SharedDriveFolder
'do a replacement on the : to $, this means you must have admin priv
'this is because i want to copy to "\\remotecpname\c$\PathName"
SharedDriveFolder=replace(RemotePatchFolder,":","$")
'copy it from the PatchFolder to the path on destination computer
'USE: RemoteCopyFile (SourceFilePath,DestinationFilePath, RemoteComputerName)
CurrentCP=cc
copySuccess=RemoteCopyFile(PatchFolder & "\" & InstallFiles(i),SharedDriveFolder,wsNames(CurrentCP))
if copySuccess=true then
tArea.Value=tArea.Value & PatchFolder & "\" & InstallFiles(i) & " copy - OK" & vbcrlf
else
tArea.Value=tArea.Value & PatchFolder & "\" & InstallFiles(i) & " copy - FAILED" & vbcrlf
end if
Next
Next
'Install the files on remote computer
'go through each filename and start that process on remote PC.
'for each file install them on the computers.
For cc=1 to numComputers
'if theres more than one patch
if retVal>1 then
For i=1 to retVal-1
CurrentCp=cc
'Now create a process on remote computer
'USE: CreateProcessandwait( ComputerName, ExecutablePathonRemoteComputer
'Create a process on the remote computer and waits. Now this can return a program terminated which is ok,
'if it returns cancelled it means the process was stopped, this could happen if the update required a
'computer restart.
CreateProcessandWait wsNames(CurrentCP), RemotePatchFolder & InstallFiles(i) & " /quiet /norestart", tArea
next
end if
'do the last patch with a forcereboot
CreateProcessandWait wsNames(CurrentCP), RemotePatchFolder & InstallFiles(retVal) & " /quiet" & " /forcereboot" , tArea
next
tArea.value=tArea.Value & "Script Complete!" & vbcrlf
'**************************** FUNCTIONS
'Get list of files in Folder.
Function GetPatchFileList(FileFolder, FileStringArray())
'create file system object
Set objFS=CreateObject("Scripting.FileSystemObject")
'set the a variable to point to our folder with the patches in it.
Set objFolder=objFS.GetFolder(FileFolder)
'set the initial file count to 0
numPatches=0
for each objFile in objFolder.Files
if UCase(Right(objFile.Name,4))=".EXE" then
numPatches=numPatches+1
redim preserve FileStringArray(numPatches)
FileStringArray(numPatches)=objFile.Name
end if
next
GetPatchFileList=numPatches
End Function
'Copy files to remote computer.
Function RemoteCopyFile(SrcFileName,DstFileName,DestinationComputer)
Dim lRetVal
'create file system object
Set objFS=CreateObject("Scripting.FileSystemObject")
lRetVal=objFS.CopyFile (SrcFileName, "\\" & DestinationComputer & "\" & DstFileName)
if lRetVal=0 then
RemoteCopyFile=True
else
RemoteCopyFile=False
end if
End Function
'Create process on remote computer and wait for it to complete.
Function CreateProcessAndWait(DestinationComputer,ExecutableFullPath,OutPutText)
Dim lretVal
strComputer= DestinationComputer
Set objWMIService = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2:Win32_Process")
Set objWMIServiceStart= GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2:Win32_ProcessStartup")
Set objConfig = objWMIServiceStart.SpawnInstance_
objConfig.ShowWindow = 1 'show window or use HIDDEN_WINDOW
lretVal= objWMIService.Create(ExecutableFullPath, null, objConfig, intProcessID)
if lretVal=0 then
OutPutText.Value = OutPutText.Value & "Process created with ID of " & intProcessID & " on " & DestinationComputer & vbcrlf
OutPutText.Value = OutPutText.Value & " Waiting for process " & intProcessID & " to complete." & vbcrlf
WaitForPID strComputer, intProcessID,OutPutText
OutPutText.Value = OutPutText.Value & "Process complete." & vbcrlf
else
OutPutText.Value = OutPutText.Value & "Unable to start process " & ExecutableFullPath & " on " & DestinationComputer & vbcrlf
end if
End Function
'Wait for PRocess to complete
Function WaitForPID(ComputerName,PIDNUMBER,OutPutText)
Dim ProcessNumber
Set objWMIServiceQ = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & ComputerName & "\root\cimv2")
Set colItems = objWMIServiceQ.ExecQuery("Select * from Win32_Process",,48)
For Each objItem in colItems
'check if this process is the one we are waiting for
if objItem.ProcessID=PIDNUMBER then
OutPutText.Value = OutPutText.Value & "Process Info:" & vbcrlf
OutPutText.Value = OutPutText.Value & " Description: " & objItem.Description & vbcrlf
OutPutText.Value = OutPutText.Value & " ExecutablePath: " & objItem.ExecutablePath & vbcrlf
OutPutText.Value = OutPutText.Value & " Name: " & objItem.Name & vbcrlf
OutPutText.Value = OutPutText.Value & " Status: " & objItem.Status & vbcrlf
OutPutText.Value = OutPutText.Value & " ThreadCount: " & objItem.ThreadCount & vbcrlf
ProcessNumber=objItem.ProcessID
end if
Next
PidWaitSQL="SELECT TargetInstance.ProcessID " & " FROM __InstanceDeletionEvent WITHIN 4 " _
& "WHERE TargetInstance ISA 'Win32_Process' AND " _
& "TargetInstance.ProcessID= '" & ProcessNumber & "'"
Set Events = GetObject("winmgmts:" & "{impersonationLevel=impersonate}!\\" & ComputerName & "\root\cimv2").ExecNotificationQuery (PidWaitSQL)
Set TerminationEvent = Events.nextevent
OutPutText.Value = OutPutText.Value & "Program " & TerminationEvent.TargetInstance.ProcessID & _
" terminated. " & vbcrlf
set TerminationEvent=Nothing
exit function
End Function
As suggested in the comments, psexec will be your best solution for this scenario. Just don't forget to use /accepteula in its syntax to ensure it doesn't effectively "hang" while waiting for someone to accept its EULA. :) If you have questions or issues with psexec in your installs, comment back here.

Resources