I have a script on a Server 2008 R2 VM which calls to the shell to robocopy a bunch of files into a local directory and then, several seconds later, checks if a certain 2.5 MB .msi exists. It kept returning false even though robocopy successfully completed and visible inspection reveals the file is there on time. I reproduced this bug on my local Windows 7 with a script:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objWshShell = CreateObject("WScript.Shell")
Dim file : file = "LargeFile.exe"
objWshShell.Run "xcopy ""..\" & file & """ .", 1, True
WScript.Echo "EXISTS: " & objFSO.FileExists(file)
LargeFile.exe is an executable around 7MB. I place it one directory above my script, execute the script, and it prints EXISTS: False. I ran the script several times with this result before some switch flipped and it started reporting True consistently.
It still happens intermittently on my VM. It will work correctly several times, I'll do something else for a few minutes, and when I come back it stops working again.
What's going on here? I need to use the shell for copying because the network is iffy and causes objFSO.CopyFolder() to crash.
Related
We have an old Windows Server 2003 r2 which is doing nothing but using the task scheduler and a VBS file to check and rename some regularly re-occurring data files. It is setup to run every hour using my credentials. If I "run" it while I'm logged on the task runs and completes correctly. When no one is logged on the task runs but completes with an 0x1 code, ie it failed.
I have checked the event logs and see nothing which I can identify as an error or failure. We believe that it was running successfully until about 6-8 months ago (yes, it was one of those set it up and forget it things and we have not been regularly checking it).
=================Additional Information===============
I ran assoc .vbs and got this output: .vbs=VBSFile
I'm not sure how to determine the user environment variables?
For the task I have tried both the vbs file and also a bat file containing the reference to the vbs file. Both run when I'm logged and both fail to complete successfully when I'm not.
Here is the vbs script:
Dim fso, file, recentDate, recentFile, theFile, myfolder, mypath
set fso = CreateObject("Scripting.FileSystemObject")
set recentFile = Nothing
mypath = "D:\TheFTP\Main\Camera\lobby"
set myfolder = fso.GetFolder(mypath)
For Each file in myfolder.Files
If (recentFile is Nothing) Then
set recentFile = file
ElseIf (file.DateLastModified > recentFile.DateLastModified) Then
set recentFile = file
End If
Next
fso.CopyFile mypath& "\" & recentFile.name, "D:\TheFTP\main\camera\cam3.jpg"
set recentFile = nothing
set fso = nothing
Here is the last bat file where I have piped the output to a file:
C:\windows\system32\cscript.exe c:\CopyWebCamFile.vbs > c:\debug.txt
Debug.txt output when I'm not logged on shows an error, see below, which is not there when I run it and am logged on:
Microsoft (R) Windows Script Host Version 5.6
Copyright (C) Microsoft Corporation 1996-2001. All rights reserved.
CScript Error: Initialization of the Windows Script Host failed. (The system cannot find the file specified.
=====================================================
More information, I added several Wscript.Echo statements to my script, before the first line, after the FOR loop and before the "copyFile" command. When I'm logged on I see all of the output in C:\debug.txt. When NOT logged on I see the same above error message, ie no Wscript.Echo output. This would see to indicate that it can not find my vbs file when I'm not logged on.
===========================
Still no happiness here. I moved and modified the .bat file to also output the contents of the script file:
type H:\Task_Stuff\CopyWebCamFileTest.vbs > H:\Task_Stuff\debug2.txt
C:\windows\system32\cscript.exe H:\Task_Stuff\CopyWebCamFileTest.vbs > H:\Task_Stuff\debug.txt
As before I get output to both .txt files when it runs while I'm logged on and nothing in debug2.txt and the usual messages in debug.txt when I'm not.
I'll fiddle with the antivirus settings, but I need to ask about that first. We are using Symantec SEP.
How can I check on the user environment variables?
====================
Maybe this will clarify my problem or suggest a solution??
Can you offer any ideas...RDK
First off we would like to thank LeeHarvey1 for his time and suggestions as we searched for the cause of this issue. In the end it was one of his suggestions that fixed the problem, but we still have no idea what caused it.
A reboot of the system cleared up all of the issues surrounding the task scheduler and running VB Scripts! We had considered his early suggestion, but discounted it as this server had only been up for a little over 3 months. Not excessive in our experience. However, when all else failed we elected to do that and "voila" it fixed the issue. We wish we knew what caused it but are now just happy we can move on to other things.
Thanks again LeeHarvey1....
I've got a batch file that I want to run in the background whenever the system (Windows 2007) is turned on. The batch file monitors the task list for a given program, and when it sees that it's shut down, prompts the user to de-licence it.
I'm currently trying to do this without converting the batch file into either an executable or Windows service file.
I've found more online references than I can count which tell me that I should use "start /b file.bat" to run the batch file in the background, but this doesn't work for me, it just starts up the batch file in the same cmd line window that I'm using.
Can anyone suggest either what's going wrong, or even better; a nice simple way for me to get the batch file to run ion start up (I cannot use a GUI as I have to roll this out to several computers remotely)
Thanks
You could make a shortcut to your batch file and place the shortcut in your Startup Programs directory:
C:\Users\\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup
Since you have to roll this out to several computers remotely, you should be able to copy the batch file to the startup programs directory over the network assuming the remote machines have WinRM enabled and your account has adequate permissions.
If you want this batch file to run in the background at start up, you could reference your batch file from a VBScript (instead of using the batch file's short cut) and set the VBscript to run in invisible mode:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\path\to\your\batchfile.bat" & Chr(34), 0
Set WshShell = Nothing
Just give this vbscript file the .vbs extension.
If the program you are concerned about is a GUI program (ie non console) just wait for it to exit. Batch waits for GUI programs to exit (but not when started interactively).
notepad
echo My notepad exited
Start /b says to start program in same window. See Start /?. Also Start is usually the wrong command to be using. It starts programs in abnormal ways. See end of http://stackoverflow.com/questions/41030190/command-to-run-a-bat-file/41049135#41049135 for how to start programs.
This is a VBS file.
This monitors for notepad exiting, pops up a messagebox, and restarts notepad.
Set WshShell = WScript.CreateObject("WScript.Shell")
Set objWMIService = GetObject("winmgmts:\\.\root\CIMV2")
Set objEvents = objWMIService.ExecNotificationQuery("SELECT * FROM Win32_ProcessStopTrace")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.ProcessName
If lcase(objReceivedEvent.ProcessName) = lcase("Notepad.exe") then
Msgbox "Process exited with exit code " & objReceivedEvent.ExitStatus
WshShell.Run "c:\Windows\notepad.exe", 1, false
End If
Loop
This should use less battery power and CPU cycles. Batch files are read line by line so make VERY poor background tasks.
If the program you are concerned about is a GUI program (ie non console) just wait for it to exit. Batch waits for GUI programs to exit (but not when started interactively).
notepad
echo My notepad exited
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.
I cannot figure out what I'm doing wrong.
I have a batch file starting a vbs script.
The script just makes some operations in some files, like moving them, create, delete...
It works fine.
Executing the bat it starts the vbs script and everything work.
The bat file just makes a cscript file.vbs
The problem is that I've scheduled this bat file .
When the times come, it gets executed but I get the error "path not found" in the vbs script.
It's not a schedule task problem because I've 11 task running batch files and they run smootly, and the script is executed (I've put controllers on it).
But the vbs script returns always the same path not found error.
Again,if I execute the script manually, it runs without problems.
The task is scheduled with the same account I use to manual execute the file, so it's not a permission issue. I just doubleclick the batch and it runs, click on execute on the task schedule manager and it fails.
The system is windows server 2008 r2 standard.
I already tried to reboot, deleting and making a new task....
Thanks to everyone
[UPDATE]
I paste here part of the code
FILE: D:\scripts\conf.ini
[script1]
fileA=D:\Rep\exportA.csv
fileB=D:\Rep\exportB.csv
fileC=D:\Rep\exportC.csv
dirHistory=D:\Rep\history
FILE: D:\scripts\merge.vbs
Dim iniObj
Set iniObj=New ClsINI
If iniObj.OpenINIFile("D:\scripts\conf.ini") = False Then
wLog("Impossible to read file ini")
Set iniObj = Nothing
Chiudi()
End If
Dim errIni,tmpVal
Dim fileA,fileB,fileC,dirHistory
errIni = iniObj.GetINIValue("script1", "fileA", fileA)
tmpVal = iniObj.GetINIValue("script1", "fileB", fileB)
errIni = errIni+tmpVal
tmpVal = iniObj.GetINIValue("script1", "fileC", fileC)
errIni = errIni+tmpVal
tmpVal = iniObj.GetINIValue("script1", "dirHistory", dirHistory)
errIni = errIni+tmpVal
If errIni > 0 Then
wLog("Error loading file ini")
wLog(errIni)
iniObj.CloseINIFile()
Set iniObj = Nothing
Chiudi()
End If
wLog("File ini Caricato")
Dim objFso,posizioneFile,Fase
Dim arrElement,resArray,actionArray,cedoleArray,varArray ,i
Dim conn,rs,strCon
Dim maxPos,maxTemp
Dim objExcel, objSheet,cella
Set objFso = CreateObject("Scripting.FileSystemObject")
if objFso.FileExists(fileA) then
objFso.DeleteFile(posizione)
wLog("File posizione moved")
else
wLog("File posizione not found")
end if
At this line a get the error of "Path not found"
Set posizioneFile = objFso.OpenTextFile(fileA, 8, True)
If not objFso.FileExists(fileB) then
SendEmail("nego")
Fase=false
Else
Set tFile = objFso.OpenTextFile(fileB, 1)
strFile=tFile.ReadAll
tFile.Close
posizioneFile.WriteLine strFile
objFso.MoveFile fileB, dirHistory&"\Negoz_"& CreaId(2) & ".csv"
End If
posizioneFile.Close
FILE: D:\scripts\merge.bat
echo Start Merge %date% %time% >> Started.log
cscript D:\scripts\merge.vbs
Sorry if I didn't put it before, but I was thinking it was a windows issue, because I thought the code was fine.
Thanks
This sounds like an issue with the working directory although it's a bit difficult to tell, since you chose not to show the content of the batch script. If you start the script manually (by double-clicking), the working directory is the directory in which the batch script (and probably the VBScript as well) resides. If you run the batch script as a scheduled task, the working directory is %SystemRoot%\system32 unless you expressly set a working directory in the task's properties.
Now, if your batch script looks like this:
cscript.exe your.vbs
it will look for your.vbs in the working directory and won't find it if the working directory is not the directory containing your.vbs. If my assumption that both scripts are in the same directory is correct you could either set the working directory in the properties of the scheduled task or (better) change the batch script to something like this:
cscript.exe "%~dp0your.vbs"
%0 is the path to the batch script itself as it was called. %~dp0 expands %0 to the absolute path of the parent directory (including a trailing backslash).
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