Windows Update Check with vbscript - windows

has someone a script/or can help me to check, is there a windows update for a server available?
So i will get a mail when the yellow update icon is in the taskbar.
My idea is: Send a mail, if the wuauclt.exe longer than 10 minutes in the taskbar.
But i have no idea to make this.
I found only this:
Dim strComputer, strProcess
Do
strProcess = inputbox( "Please enter the name of the process (for instance: explorer.exe)", "Input" )
Loop until strProcess <> ""
Do
strComputer = inputbox( "Please enter the computer name", "Input" )
Loop until strComputer <> ""
If( IsProcessRunning( strComputer, strProcess ) = True ) Then
WScript.Echo "Process " & strProcess & " is running on computer " & strComputer
Else
WScript.Echo "Process " & strProcess & " is NOT running on computer " & strComputer
End If
Thanks for help.

How about something like this
'Microsoft magic
Set updateSession = CreateObject("Microsoft.Update.Session")
Set updateSearcher = updateSession.CreateupdateSearcher()
Set searchResult = updateSearcher.Search("IsInstalled=0 and Type='Software'")
'End Microsoft magic
If searchResult.Updates.Count <> 0 Then 'If updates were found
'This is where you add your code to send an E-Mail.
'Send E-mail including a list of updates needed.
'This is how you can list the title of each update that was found.
'You could include the list in the body of your E-Mail.
For i = 0 To searchResult.Updates.Count - 1
Set update = searchResult.Updates.Item(i)
WScript.Echo update.Title
Next
End If

wuauclt could quite possibly be running for more than 10 minutes, without necessarily be notifying the user that there are pending updates.
I know that this is StackOverflow, and this is a programming question, but I'm a sysadmin, and I'm of the opinion that this belongs on ServerFault, and that you're doing it wrong. WSUS (http://technet.microsoft.com/en-us/wsus/default.aspx) is designed to manage Windows Updates.

Related

Run BAT file on remote server using VBScript. No psexec, and as a different user

I'm trying to execute a a BAT file on a remote server using VBScript. Further requirements:
psexec is not allowed
I need the script to operate under the permissions of another user, not those of my own workstation
I have consulted this article: https://learn.microsoft.com/en-us/windows/desktop/WmiSdk/connecting-to-wmi-remotely-with-vbscript
I see how creating the connection works, but I can't figure out how to then create a process using that same connection.
I believe this solution is really close, the only problem is I think it impersonates the user of the computer it is currently running on:
strCommand = "C:\temp\copyall.bat"
strPath = "C:\temp"
strcomputer="."
process = "winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2"
msgbox process
Set objWMIService = GetObject(process)
Set objProcess = objWMIService.Get("Win32_Process")
errReturn = objProcess.Create(strCommand, strPath, Null, intProcessID)
If errReturn = 0 Then
WScript.Echo "scan success: " & intProcessID
Else
WScript.Echo "scan fail: " & errReturn
End If
This example from Microsoft's site shows how to create the connection properly but I don't know how to then use that connection.
' Full Computer Name
' can be found by right-clicking My Computer,
' then click Properties, then click the Computer Name tab)
' or use the computer's IP address
strComputer = "FullComputerName"
strDomain = "DOMAIN"
Wscript.StdOut.Write "Please enter your user name:"
strUser = Wscript.StdIn.ReadLine
Set objPassword = CreateObject("ScriptPW.Password")
Wscript.StdOut.Write "Please enter your password:"
strPassword = objPassword.GetPassword()
Set objSWbemLocator = CreateObject("WbemScripting.SWbemLocator")
Set objSWbemServices = objSWbemLocator.ConnectServer(strComputer, _
"Root\CIMv2", _
strUser, _
strPassword, _
"MS_409", _
"ntlmdomain:" + strDomain)
Set colSwbemObjectSet = objSWbemServices.ExecQuery("Select * From Win32_Process")
For Each objProcess in colSWbemObjectSet
Wscript.Echo "Process Name: " & objProcess.Name
Next
The answer is probably staring me in the face but I just can't see it right now. Ideas?
After connecting to the remote server simply get the Win32_Process object and call the Create() method like you'd do locally.
Set objSWbemServices = objSWbemLocator.ConnectServer(...)
Set objProcess = objSWbemServices.Get("Win32_Process")
errReturn = objProcess.Create(strCommand, strPath, Null, intProcessID)
The file you want to run must exist locally on the remote server for this to work.
Also note that this normally requires admin privileges on the remote system.

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.

File Folder copy

Below is the VBScript code. If the file/s or folder exist I get scripting error, "File already exists".
How to fix that?
How to create folder only if it does not exist and copy files only that are new or do not exist in source path?
How to insert the username (Point 1) after "Welcome" and at (Poin 3) instead of user cancelled?
Can the buttons be changed to Copy,Update,Cancel instead of Yes,No,Cancel? (Point 2)
The code:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set wshShell = WScript.CreateObject( "WScript.Shell" )
strUserName = wshShell.ExpandEnvironmentStrings( "%USERNAME%" )
Message = " Welcome to the AVG Update Module" & vbCR '1*
Message = Message & " *****************************" & vbCR & vbCR
Message = Message & " Click Yes to Copy Definition Files" & vbCR & vbCR
Message = Message & " OR " & vbCR & vbCR
Message = Message & " Click No to Update Definition Files." & vbCR & vbCR
Message = Message & " Click Cancel (ESC) to Exit." & vbCR & vbCR
X = MsgBox(Message, vbYesNoCancel, "AVG Update Module") '2*
'Yes Selected Script
If X = 6 then
objFSO.FolderExists("E:\Updates")
if TRUE then objFSO.CreateFolder ("E:\Updates")
objFSO.CopyFile "c:\Docume~1\alluse~1\applic~1\avg8\update\download\*.*",
"E:\Updates\" , OverwriteFiles
MsgBox "Files Copied Succesfully.", vbInformation, "Copy Success"
End If
'No Selected Script
If X = 7 then
objFSO.FolderExists("Updates")
if TRUE then objFSO.CreateFolder("Updates")
objFSO.CopyFile "E:\Updates\*.*", "Updates", OverwriteFiles
Message = "Files Updated Successfully." & vbCR & vbCR
Message = Message & "Click OK to Launch AVG GUI." & vbCR & vbCR
Message = Message & "Click Cancel (ESC) to Exit." & vbCR & vbCR
Y = MsgBox(Message, vbOKCancel, "Update Success")
If Y = 1 then
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\Progra~1\avg\avg8\avgui.exe" & Chr(34), 0
Set WshShell = Nothing
End if
If Y = 3 then WScript.Quit
End IF
'Cancel Selection Script
If X = 2 then
MsgBox "No Files have been Copied/Updated.", vbExclamation, "User Cancelled" '3*
End if
How to create folder only if it does not exist
This your code:
objFSO.FolderExists("E:\Updates")
if TRUE then objFSO.CreateFolder ("E:\Updates")
simply calls the FolderExists and CreateFolder methods in sequence (CreateFolder is always called because the if TRUE condition evaluates to True) and is equal to:
objFSO.FolderExists("E:\Updates")
objFSO.CreateFolder ("E:\Updates")
You want to call CreateFolder depending on the return value of the FolderExists method:
If Not objFSO.FolderExists("E:\Updates") Then
objFSO.CreateFolder "E:\Updates"
and copy files only that are new or do not exist in source path?
Neither VBScript nor the FileSystemObject object have this functionality. However, it is possible to call an external tool that can do that, such as xcopy, from your script using the WshShell.Run method. I guess you need something like this:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "xcopy c:\Docume~1\alluse~1\applic~1\avg8\update\download\*.* E:\Updates\ /D", , True
How to insert the username (Point 1)
Concatenate the message text with the strUserName variable value:
Message = " Welcome " & strUserName & " to the AVG Update Module" & vbCR
...
MsgBox "No Files have been Copied/Updated.", vbExclamation, strUserName & " Cancelled"
Can the buttons be changed to Copy,Update,Cancel Instead of Yes,No,Cancel?(Point 2)
No, VBScript's built-in MsgBox function does not support custom buttons. There're workarounds though: you could create your custom message box using an HTA (HTML application) or use the InputBox function to prompt the user for the task they wish to perform. You can find examples here.
I'd also like to note that you can improve your script by using the Select Case statement to check the MsgBox return value instead of multiple If...Then...End If statements. Also, it's a bad practice to use "magic numbers" like 6 or 7 - use the appropriate constants instead. For example:
Select Case X
Case vbYes
...
Case vbNo
...
Case Else ' vbCancel
...
End Select
When you say
"copy files only that are new or do
not exist in source path?"
do you mean you only want to copy files from the source directory to the destination directory if they do not exist in the destination? If so this will accomplish that
Const SourceFolder = "C:\Test1\"
Const DestinationFolder = "C:\Test2\"
Set fso = CreateObject("Scripting.FileSystemObject")
'Get a collection of al the files in the source directory
Set fileCol = fso.GetFolder(SourceFolder).Files
'Loop through each file and check to see if it exists in the destination directory
For Each objFile in fileCol
If NOT fso.FileExists(DestinationFolder & objFile.Name) Then
'If the file does not exist in the destination directory copy it there.
objFile.Copy DestinationFolder
Else
If objFile.DateLastModified > fso.GetFile(DestinationFolder & objFile.Name).DateLastModified Then
'If the file is newer than the destination file copy it there
objFile.Copy DestinationFolder, True
End If
End If
Next
Set fileCol = Nothing
Set fso = Nothing
Added the requested date check.

VBScript FTP Login with Username and Password

I am trying to update a VBScript (very little experience with this, I do a lot of VB.NET), that reads an FTP directory and moves certain files to a new local directory on a daily basis. I have old code that works on an FTP site that uses anonymous logins, but I now need it to access an FTP site that requires username and password.
Here is my current code -
Sub MoveNSPurolatorFile()
Dim NSPurolatorFTPSite, NSPurolatorMoveFilePath, NSPurolatorFTPFolder, NSPurolatorFTPFileName
Dim folder, files
Dim fso
set fso = CreateObject("Scripting.FileSystemObject")
NSPurolatorFTPSite="\\xxx.xxx.x.xx\"
NSPurolatorMoveFilePath = "F:\TestDirectory"
NSPurolatorFTPFolder = "TestFolder"
NSPurolatorFTPFileName = "MAN0201.CSV"
If InStr(NSPurolatorFTPFileName, "_processed") = 0 and InStr(NSPurolatorFTPFileName, ".CSV") > 0 Then
If fso.FolderExists(NSPurolatorFTPSite & NSPurolatorFTPFolder) Then
If fso.FileExists(NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName) Then
objfile.writeline "NS Purolator File Found: " & NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName
fso.copyFile NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName, NSPurolatorMoveFilePath & "\"
Else
objfile.writeline "File does not exist: " & NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName
End If
End If
End If
Next
End Sub
It says the folder does not exist, but I know it does and when I run this code against an ftp site that does not require username and password it works fine. I guess my question is - How do I pass in the username and password using VBScript to the ftp site before trying to access folders, etc?
Thanks.
This really is an incredibly bad way to do this. You can't just treat folders on a remote FTP site as local folders.
You really should be using InetCtrls.Inet.1
Here's an example I lifted from somewhere else that does not do what you want, but contains all the parts you need - you need to pick it apart to suit your needs.
'Option Explicit
'const progname="FTP upload script by Richard Finegold"
'const url = "ftp://ftp.myftpsite.com"
'const rdir = "mydir"
'const user = "anonymous"
'const pass = "myname#mymailsite.com"
'This is an example of ftp'ing without calling the external "FTP" command
'It uses InetCtrls.Inet.1 instead
'Included is a "hint" for simple downloading
'Sources:
'http://msdn.microsoft.com/library/partbook/ipwvb5/loggingontoftpserver.htm
'http://msdn.microsoft.com/library/partbook/egvb6/addinginternettransfercontrol.htm
'http://cwashington.netreach.net/ - search on "ftp" - inspiration only!
'Insist on arguments
dim objArgs
Set objArgs = Wscript.Arguments
If 0=objArgs.Count Then
MsgBox "No files selected for operation!", vbOkOnly + vbCritical, progname
WScript.Quit
End If
'Force console mode - csforce.vbs (with some reorganization for efficiency)
dim i
if right(ucase(wscript.FullName),11)="WSCRIPT.EXE" then
dim args, y
For i = 0 to objArgs.Count - 1
args = args + " " + objArgs(i)
Next
Set y = WScript.CreateObject("WScript.Shell")
y.Run "cscript.exe " & wscript.ScriptFullName + " " + args, 1
wscript.quit
end if
'Do actual work
dim fso, ftpo
set fso = WScript.CreateObject("Scripting.FileSystemObject")
set ftpo = WScript.CreateObject("InetCtls.Inet.1") 'Msinet.ocx
ftpo.URL = url
ftpo.UserName = user
ftpo.Password = pass
WScript.Echo "Connecting..."
ftpo.Execute , "CD " & rdir
do
' WScript.Echo "."
WScript.Sleep 100 'This can take a while loop while ftpo.StillExecuting
for i = 0 to objArgs.Count - 1
dim sLFile
sLFile = objArgs(i)
if (fso.FileExists(sLFile)) then
WScript.Echo "Uploading " & sLFile & " as " & FSO.GetFileName(sLFile) & " "
ftpo.Execute , "Put " & sLFile & " " & FSO.GetFileName(sLFile)
'ftpo.Execute , "Get " & sRemoteFile & " C:\" & sLFile
do
'WScript.Echo "."
WScript.Sleep 100 'This can take a while
loop while ftpo.StillExecuting
else
MsgBox Chr(34) & sLFile & Chr(34) & " does not exist!", _
vbOkOnly, progname
end if
next
WScript.Echo "Closing"
ftpo.Execute , "Close"
WScript.Echo "Done!"
Here's a pretty nice way to do it - I'm sure this could be improved upon, but I just got it going.. :-)
Dim fso, folder1, folder2, folder2a
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder2a = fso.GetFolder("C:\temp")
ftpFolderString = "ftp://username:password#ftp.ftpsite.com/folderpath"
targetFoldder = "C:\temp"
fileSearchStr = "searchstring"
Dim SH, txtFolderToOpen, thing
Set SH = CreateObject("Shell.Application")
'SH.Open txtFolderToOpen
Set folder1 = SH.NameSpace(ftpFolderString)
Set folder2 = SH.NameSpace(targetFoldder)
For Each item In folder1.items
If InStr(LCase(item.Name),fileSearchStr) > 0 Then
Debug.WriteLine item.Name
folder2.CopyHere item,4
WScript.Sleep(200)
For Each item2 In folder2a.Files
If item2.Name = item.Name Then
While item2.Size < item.Size
WScript.Sleep(200)
Wend
End If
Next
WScript.Sleep(200)
End If
Next
Set SH = Nothing
Debug.WriteLine "Done"
How is the script being run? Manually, automatically? By a service?
Mapped-letter drives are not always available when running as a service.
Experiment with the script to ensure that it even able to see the F:\ drive, and then see what else is visible.
Is the FTP site accessed by a UNC path (looks like it is)? If it is just a standard FTP address then you can incorporate the username / password in the URL e.g. ftp://user:pass#myftpsite.com. If it is a UNC path that you are trying to access using different credentials then the easiest way would probably be to map a drive, do the work and then unmap the drive. 2 different approaches can be found here

Resources