.ShellExecute and Wait - vbscript

I've got a VBScript that calls multiple other scripts. (Most of them are just copying files from NAS to multiple places on users PC.
One of the VBScripts needs to be run as administrator using .ShellExecute.
It does work but there are other VBScripts after it's call that rely on it, so I get an error for the files are missing.
I know the command
shell.Run "sample.vbs", , True
for waiting till the script is done.
Is there a similar way to get ShellExecute to wait?

ShellExecute always runs asynchronously. If you have other scripts that need to run only after this script finished you could create some kind of marker upon completion to signal "go" to the other script(s).
For example, you can create a file in a specific path:
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile("C:\path\to\marker.txt", True)
If you need to run your batch of scripts more than once, have the script remove the marker when it starts and re-create it at the end.
The script that's supposed to run next needs to check for this marker and suspend execution until it appears. For example:
Set fso = CreateObject("Scripting.FileSystemObject")
Do Until fso.FileExists("C:\path\to\marker.txt")
WScript.Sleep 100
Loop
Other options are creating a registry value, or an eventlog entry.
Checking the process list (e.g. via Win32_Process) won't work, because normal users don't have access to the CommandLine property of elevated processes (which would be required to identify this particular process).

Related

How to give script a name?

I have a script that I run to keep my computer from going to sleep. It's a simple script that presses the Num Lock key. How can I give my script a name so I can see it in Task Manager? I would like to end the process every now and then and not sure which application it is.
Here is the code (idle.vbs):
Dim objResult
Set objShell = WScript.CreateObject("WScript.Shell")
Do While True
objResult = objShell.sendkeys("{NUMLOCK}{NUMLOCK}")
Wscript.Sleep (60000)
Loop
Your script is being executed in an interpreter, and in Task Manager you will see the name of the executable : wscript.exe
You cannot change the process name, although you can identify the name of the running script using another script and the property of handles.
But the easiest way would be to make a copy of the executable wscript.exe, rename it with something suggestive for you, and use that executable in cmd to run the script. For example idleEx.exe and run it :
...\idleEx.exe idle.vbs
Or, the other method: create a shortcut for the vbs and change Properties / General / Opens with, browse and choose idleEx.exe.
After that, your process name will apear as idleEx.exe

Wscript make proccess not run on background or wait while finishes

Scenario: We have some scheduled jobs (Control-M) running many proccesses and some of them execute a .VBS file (with parameters) that reads the configuration from an XML file and sends it to a company's software that interprets it and loads data onto tables.
I need help with the VBS file, that as stated above, only gets the instructions from the XML and send it to the software with these steps (also, logs each step):
Finds the XML;
Creates an object to login the software (with XML parameters);
Dim object
Set object = CreateObject("service.location.id")
Login into the Database (with XML parameters);
object.Login("DATABASE_NAME")
Select which Data base (XML...);
object.SelectDatabase("DATABASE_NAME")
Sends command to start load proccess
object.LoadRepositoryTable(XML)
The problem is that since the default interpreter is wscript, when executing the script, it runs on the background and the Job Scheduler thinks it finished executing and starts the next job.
Executing the script on CMD, if I start it as cscript SCRIPT.vbs it waits for the whole load proccess to finish (it doesn't run on background), and I want to do this when running as wscript - because since there are many jobs, editing how they calls the script is not an option right now. This includes creating an .bat file that calls the SCRIPT.vbs as cscript.
I also tried searching on "how to run another .vbs file inside a VB Script" to run as cscript, but didn't manage to make it work.
What can I do?
Is there a way to make wscript wait for the load?
Is there a way to call a .vbs in the same folder (without sending it as parameter) while passing 2 arguments?
Another option I'm not seeing?
Edit: Here is what I've come to so far, but I'm getting "expected end of statement".
Dim objShell
Dim arg_dir
arg_dir = Wscript.Arguments.Item(0)
Dim arg_xml
arg_xml = Wscript.Arguments.Item(1)
Set objShell = CreateObject("Wscript.Shell")
objShell.Run "cmd /k cscript ""C:\Folder\Scripts\SCRIPT.vbs" &" "& arg_dir &" "& arg_xml"", 1, True
cscript is the solution for your problem. Either have your scheduler run each VBScript with cscript.exe, or (if that isn't possible for some reason) make cscript the default script host by running
wscript.exe //h:cscript
once as an administrator.
The script you have cobbled together won't resolve your problem, even if you fixed the syntax error in the last line, because as long as you run it with wscript.exe it will still return immediately. It doesn't matter that the code in that script is running other scripts synchronously as long as all of that is happening in the background.

Run a vbscript as an admin from itself (Nagios / NSclient)

I'll detail as much as I can so you can understand in which environment I'm working on and what I am trying to do.
I am using Nagios at work to monitor our servers. Each one of our Windows servers has NSclient++ installed on it. One of the many scripts Nagios' calling is check_updates.vbs; here 's how it goes if someone need to know:
On the Nagios' server side, we execute the following command:
/usr/lib/nagios/plugins/check_nrpe -H WindowsServerIpAddress -p 5666 -t 120 -c check_updates
When we execute that command, here is what's happening on the Windows Server:
By using the nscp service, it calls the following command, defined in the nsclient.ini file (into NSclient++ folder):
check_updates=cscript.exe //T:120 //NoLogo scripts\\check_updates.vbs
Then, it calls the check_updates.vbs script.
The local account on the Windows Server is the administrator one. We have changed nscp service's properties so that this service is called with another account, created especially for monitoring.
So, when we call the check_updates.vbs script directly on the Windows server (i.e locally), everything goes well, the script is working perfectly. But if we call it remotely, on the Nagios server, we have a simple (but deadly) error that says Permission denied.
That is why we are focusing on giving enough permissions to the monitoring-user.
After searching more and more and trying everything we could, I must say we're kinda lost right now.
The last solution I tried was to add these lines at the beginning of the script, to give the monitoring-user enough permissions to execute the script properly:
Set WshShell = WScript.CreateObject("WScript.Shell")
If WScript.Arguments.length = 0 Then
Set ObjShell = CreateObject("Shell.Application")
ObjShell.ShellExecute "wscript.exe", """" & _
WScript.ScriptFullName & """" &_
" RunAsAdministrator", , "runas", 1
End if
(I found this here)
When I use this, locally I get an [error notice*] but the script is working anyway. However, when I call the script remotely, I just have a timeout after 120s.
More info: UAC is disabled on the Windows server, and the monitoring-user has full access control on the NSclient++\scripts folder. Using the nscp service with the admin account is not the solution we are seeking for this matter.
So, am I missing something here ? Do you have any idea about this ?
Thanks for the help ! :)
[*error notice]: Invalid arguments, check help with cscript.exe check_available_updates.vbs -h
If UAC is off then it's not a UAC permission error therefore don't worry about runas.
It's also unlikely to be a file permissions problem (all admins are equal unless someone made it different).
What is likely is the different environments. You have an assumption that is true for the interactive user only. You need to log what is happening in your script (see wshshell.LogEvent(intType, strMessage [,strTarget])). If your script has
on error remove next
remove it.
Mapped drives are a problem. As are environmental variables and special folders.
Try using Runas command line command with various options (eg /env) to see if you can duplicate the behaviour.
Also run
cmd /c set > c:\set.log
and compare the output from the two ways of running it (ie with your client and direct).
Thanks for your answer Tony, I've tried your suggestions, but eventually we ended up getting around the problem.
Despite we gave the monitoring-user all permissions needed to execute this script, it was not working. So here's what we've done:
We created a bat file which contains the command-line to call check_update.vbs and to write its output into a new file:
cscript.exe //T:120 //NoLogo "C:\Program Files\NSClient++\scripts\check_updates.vbs" > "C:\Program Files\NSClient++\check_update.log"
Then, we've created a scheduled task (using the TaskScheduler) which calls the bat file every day to check for new updates.
To have the correct output in Nagios, we created another vbscript which only has to read the check_update.log file and return the appropriate value to Nagios:
Const ForReading = 1
Const rOK = 0
Const rWarning = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:\Program Files\NSClient++\check_update.log", ForReading)
FirstChar = objFile.Read(1)
Content = objFile.ReadAll
If FirstChar = "O" Then
Wscript.Echo FirstChar + Content
Wscript.Quit(rOK)
Else
WScript.Echo FirstChar + Content
End If
Wscript.Quit(rWarning)
This vbscript is really basic, since it only reads the first letter of the file to decide which value to return. Indeed, if there are no updates available, the message will always be "OK - No patches missing".
So, by calling the bat file using the SchedulerTask, we get around the fact that the monitoring-user has not enough permissions to execute the script.

VBS script (VBScript) errors 800A0035 and/or 800A004C only on the first execution of the script

I am pretty new to all this VBS stuff because basically all I need to do is to make one simple VBS script, which I have possibly written, however, my problem is that it gives me 800A0035 or 800A004C error when I execute it for the first time on a particular PC, as soon as I execute it for the second time, it runs just OK and does what it is supposed to do. Incidentally, on my own computer it works OK even on the first execution.
I know that the errors have something to do with the wrong paths but I have checked my script several times and I am 100% positive that they are correct.
Here is the script:
Set objFSO = CreateObject("Scripting.FileSystemObject")
objFSO.MoveFile "rar.bat" , "rarp.bat"
'HideBat.vbs
CreateObject("Wscript.Shell").Run "rarp.bat", 0, True
What the script is supposed to do is to rename the rar.bat file to rarp.bat and run that batch file (rarp.bat) without popping up the command prompt. What the batch file does is not relevant, I guess, but anyway, it just runs WinRAR.
The rar.bat file and the VBS script are in the same folder, that's why I have used relative paths in the script. I cannot use absolute paths because I need to run the script on several computers.
I have read somewhere on the internet that by default VBS script first looks for the files in C:\Windows\System32 when relative paths are used. I have even tried using absolute paths in the script but it didn't work either. Here is how I need them to look like: %systemdrive%\users\%username%\appdata\roaming\rar.bat but this simply didn't work in the VBS script.
I really think that what I need is really a simple script but apparently it's pretty hard to get it working properly. I will be very grateful to those who help me.
Thank you a lot in advance.
Regards.
The only way your script - at least the part published - can give an error is by not finding the source file for renaming, you should have added full script and error message to be sure.
I suppose this is caused by a security setting on your pc that are more forgiving than on the rest of the pc's, eg UAC ? On the other pc's, try to put the files in a map like c:\test and then run it again after checking that the file rar.bat does exist in the same map. Do you have the same credentials (admin) on the other pc's ?
If you just want to run the bat file hidden, why the renaming ?
how do you download the bat ? and how then is invoked the script ? could be a timing issue that the second time is no longer a problem. In that case check in your script if the file is allready there and do a sleep in a loop while it doesn't
If you want to use the absolute path you could try this
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell")
Set WshSysEnv = WshShell.Environment("PROCESS")
path = WshSysEnv("USERPROFILE") & "\appdata\roaming\rar.bat"
wscript.echo path
objFSO.MoveFile path , "rarp.bat"
CreateObject("Wscript.Shell").Run "rarp.bat", 1, True

Batch File calls VBScript which calls EXE that won't open

I have a VBS file 'migration.vbs' that runs a number of commands and then calls an AutoIt .exe file to begin the uninstall of a product. The entire script runs successfully when you call it by itself from the command line with 'cscript migration.vbs'
This script is going to be pushed out to a number of other machines where techs need to be able to double-click to run it. A lot of the machines don't execute VBS by default on a double click, so I've added a batch file to run it.
The problem is that when the batch file calls the VBS, it starts to run but never calls the exe. It just.. skips that step. I'm guessing there's an issue with nested system calls or something that I don't know about.
Anyways, any solutions? I'd rather not put the EXE call in the batch file due to logic checking the VBS does against registry keys (that'd be hard/impossible to duplicate in BAT).
Thanks again
start.bat
START /WAIT cscript .\data\migration.vbs
migration.vbs
WSHSHell.Run "uninstall.exe", 0, True
There is no nested system calls limit, I'm guessing that the path or current directory is wrong, try using a full path or monitor the filesystem calls with Process Monitor

Resources