Why does this VBScript give me an error? - vbscript

I saved this VBScript script to my local machine as c:\test.vbs:
WScript.StdOut.WriteLine "This is a test"
When I run it from the command line, I get this error:
---------------------------
Windows Script Host
---------------------------
Script: C:\test.vbs
Line: 1
Char: 1
Error: The handle is invalid.
Code: 80070006
Source: (null)
---------------------------
OK
---------------------------
I get this under Windows Vista (SP1) and Windows XP Pro (SP3).

This link may help you:
http://www.tech-archive.net/Archive/Scripting/microsoft.public.scripting.vbscript/2004-07/0979.html
It appears that the handle StdOut is only available when using a console host (cscript.exe) and not a windowed host (wscript.exe). If you want the code to work, you have to use cscript.exe to run it.
The post also describes how to change default behavior to run scripts with cscript and not wscript.

As described by the article in the accepted answer, my script worked when I called it from the command prompt like this:
cscript test.vbs
You can also change the default script host, so that a call to cscript is not necessary every single time. After doing that, the original command works unmodified.
cscript //h:cscript //s
You can restore the original behavior with:
cscript //h:wscript //s
Thanks!!

I submitted this solution in bug "cscript - print output on same line on console?" which I feel is related to this issue.
I use the following "log" function in my JavaScript to support either wscript or cscript environment. As you can see this function will write to standard output only if it can.
var ExampleApp = {
// Log output to console if available.
// NOTE: Script file has to be executed using "cscript.exe" for this to work.
log: function (text) {
try {
// Test if stdout is working.
WScript.stdout.WriteLine(text);
// stdout is working, reset this function to always output to stdout.
this.log = function (text) { WScript.stdout.WriteLine(text); };
} catch (er) {
// stdout is not working, reset this function to do nothing.
this.log = function () { };
}
},
Main: function () {
this.log("Hello world.");
this.log("Life is good.");
}
};
ExampleApp.Main();

Related

Run Laravel queued jobs as windows service [duplicate]

I need to set up a PHP script as a windows service.
I need it to run regardless of which user is logged in, and on system start up - so it sounds like a windows service is best, but am happy to hear other suggestions.
(This script runs continuously, it's not a "run every 5 mins" thing I could use the Scheduled Task Manager for.)
http://support.microsoft.com/kb/251192 covers using the sc.exe program to install your service.
But from what I've read, I need to have a wrapper round the PHP script to accept the special commands from the windows service manager. Can anyone help with this?
Maybe the Resource Kit Tools (specifically srvany.exe) can help you here. MSDN: How To Create A User-Defined Service and possibly this hint for 2008 Server should help you setup any executable as a service. (I've successfully used this on Windows 2003 Server, Windows 2008 Server and on Windows XP Professional [other Resource Kit, though])
You'd create a bat containing php your-script.php, wrap that with srvany.exe and voila, the script is started once the machine loads the services.
srvany.exe should handle those start/stop/restart calls you'd expect a daemon to execute. It would load your executable on start, kill the process on stop, do both on restart. So you don't have to worry about this part. You might want to check if a register_shutdown_function() can help identify when your service process is killed.
You can even define dependencies to other services (say some database or some such).
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\THENAMEOFYOURSERVICE]
"DependOnService"="DEPENDONTHIS"
replace THENAMEOFYOURSERVICE with the name you gave your service and DEPENDONTHIS with the name of the service to depend on (say "Postgres9.0" or something). Save that file to dependency.reg and load it with regedit /s dependency.reg. (Or doubleclick it in explorer…)
We used FireDaemon for this task, it doesn't require wrapper scripts etc. Unfortunately it's not freeware.
You can run php on command line by giving different parameters and also the script-file as parameter. If you add the whole line you need into the service configuration it should run. So you are also able to try the device before creating the service.
If the php-script is outside your web-route perhaps you should add the folder to the PATH-Variable of windows.
I found this but haven't tried it myself. PHP actually comes with some functions to do this:
http://uk.php.net/manual/en/book.win32service.php
Here are some examples:
http://uk.php.net/manual/en/win32service.examples.php
<?php
if ($argv[1] == 'run') {
win32_start_service_ctrl_dispatcher('dummyphp');
while (WIN32_SERVICE_CONTROL_STOP != win32_get_last_control_message()) {
# do your work here.
# try not to take up more than 30 seconds before going around the loop
# again
}
}
?>
After a few days... i found this magnific option!
He build an .exe that recive the service options and works fine!
https://superuser.com/questions/628176/php-cgi-exe-as-a-windows-service/643676#643676
the command correct:
sc create FOO binPath= "service.exe \"C:\php\php-cgi.exe -b
127.0.0.1:9000 -c C:\php\php.ini"\" type= own start= auto error= ignore DisplayName= "FOO php"
NSSM - the Non-Sucking Service Manager is also a solution, and then
nssm install PHP php-cgi.exe -b 127.0.0.1:9000 -c C:\php\php.ini
Loop in shell.
In php loop add loop counter and exit after hour for restarting process.
memory usage controll
reconect to db each 100 seconds
Shell script do simple loop and each for iteration create new logfile
PHP and shell script:
ini_set('memory_limit', '300M');
$loopCnt = 0;
while(true) {
/**
* Maximal time limit for loop execution
*/
set_time_limit(10);
$loopCnt ++;
/**
* each hour finishing
*/
if($loopCnt > 60 * 60){
exit;
}
usleep(self::SLEEP_MICROSECONDS);
if ($loopCnt % 60 === 0) { //log every 60 seconds memory usage
$this->out('memory usage: '.memory_get_usage());
//reconnect DB to avoid timeouts and server gone away errors
Yii::$app->db->close();
Yii::$app->db->open();
}
if (memory_get_usage() > self::MEMORY_LIMIT) {
$this->out('memory limit reached: '.self::MEMORY_LIMIT . ' actual: ' . memory_get_usage() . ' exit');
exit;
}
/**
* do work
*/
}
}
// bat file
set loopcount=1000000
:loop
echo Loop %DATE% %TIME% %loopcount%
set t=%TIME: =0%
php cwbouncer.php > C:\logs\cwbouncer_%DATE:~2,2%%DATE:~5,2%%DATE:~8,2%_%t:~0,2%%t:~3,2%%t:~6,2%.log
set /a loopcount=loopcount-1
if %loopcount%==0 goto exitloop
goto loop
:exitloop

How to redirect Windows cmd output to a text file?

I am trying to monitor the cmd output of a certain executable .exe and use it for another process running at the same time.
The problem is that all cmd redirecting functions ( '>','>>','<' and '|') would only redirect the output after a successful return of the last command.
What I wanted to do is to generate some kind of streaming log of my cmd.
You can run in your process in background by using
start /b something.exe > somefile.txt
Windows 20H2: Redirection works fine when logged in as true administrator but will NOT work when logged in as a created administrative user. I have used it for years to redirect the output of a multi target backup system using Hobo copy to put the console output in a log file. I have never been able to get it to work successfully in Windows 10 ver 19 or 20 on a created administrative user.
You can prefix the command with "cmd /c" to start a new command prompt, and redirect the output of the command prompt:
cmd /c YOUR CODE > TextFileName.txt
Note : Use ONLY single greater than (>)
Since the output of cmd is going to TextFileName.txt.
Whereas this misses the error output, so you are not able to see : Request to UnKnown timed-out for each failed address.

Redirection to standard output in VBS

When writing a script in sh or in cmd you can put a > at the end of a line to have the output of that line redirected to a file. If not, it is sent to the standard output.
Also, both have the echo command to produce output to the standard output (which can, in turn, be redirected too).
How to perform those two things in a VBS script?
Nothing different. You only need to make sure your scripts are run with the console based script host cscript.
myscript.vbs:
' WScript.Echo is a host-aware hybrid method.
' in cscript, prints the message with final a new line feed, also accepts vary arguments (0 or more).
' in wscript, shows a message dialog window
WScript.Echo "test1", "arg2"
' WScript.Stdout.Write on the other hand is a more traditional way to write to standard output stream
' print the message as is with no new line feeds
WScript.Stdout.Write "test"
WScript.Stdout.Write "2"
Command:
cscript myscript.vbs
Output:
Microsoft (R) Windows Script Host Version 5.812
Copyright (C) Microsoft Corporation. All rights reserved.
test1 arg2
test2
There's also an option to prevent to display banner on the output.
cscript //NoLogo myscript.vbs
Output:
test1 arg2
test2
Redirection:
cscript //NoLogo myscript.vbs>output.txt
PS: cscript is the default script interpreter only on Windows Server operating systems. Otherwise the default is wscript. Therefore it is a good practice to run the scripts with a specific script host.
To change the default script host have a look at Running Your Scripts
Useful Links:
Echo Method
Write Method
Running Your Scripts

vbs how to get result from a command line command

I want to get the result of a simple command from the command line (cmd.exe) using a Windows script (.vbs). How is this done? I haven't been able to find a good/simple example or explanation. You could use the "date" or "time" command to provide an example with.
Such as:
P.S. I am able to write the script code that opens cmd.exe and sends the command.
Thanks!
When in doubt, read the documentation. You probably want something like this:
Set p = CreateObject("WScript.Shell").Exec("%COMSPEC% /c date /t")
Do While p.Status = 0
WScript.Sleep 100
Loop
WScript.Echo p.StdOut.ReadAll
Edit: When using Exec() you pass input via the .StdIn descriptor, not via SendKeys() (which is a rather unreliable way of passing input anyway).
%COMSPEC% is a system environment variable with the full path to cmd.exe and the /c option makes cmd.exe exit after the command (date /t in the example) is finished.
If the command indicates success/failure with an exit code, you can check the ExitCode property after the command finished.
If p.Status <> 0 Then WScript.Echo p.ExitCode
Edit2: Instead of using atprogram interactively, can you construct commandlines that will perform particular tasks without user interaction? With non-interactive commandlines something like this might work:
prompt = "C:\>"
atprogram_cmdline_1 = "atprogram.exe ..."
atprogram_cmdline_2 = "atprogram.exe ..."
'...
Function ReadOutput(p)
text = ""
Do Until Right(text, Len(prompt)) = prompt
text = text & p.StdOut.Read(1)
Loop
ReadOutput = text
End Function
Set cmd = CreateObject("WScript.Shell").Exec("%COMSPEC% /k")
ReadOutput cmd ' skip over first prompt
cmd.StdIn.WriteLine(atprogram_cmdline_1)
WScript.Echo ReadOutput(cmd)
cmd.StdIn.WriteLine(atprogram_cmdline_2)
WScript.Echo ReadOutput(cmd)
'...
cmd.Terminate ' exit CMD.EXE
%COMSPEC% /k spawns a command prompt without running a command. The /k prevents it from closing. Because it isn't closing automatically, you can't use the While p.Status = 0 loop here. If a command needs some time to finish, you need to WScript.Sleep a number of seconds.
Via cmd.StdIn.WriteLine you can run commandlines in the CMD instance. The function ReadOutput() reads the output from StdOut until the next prompt appears. You need to look for the prompt, because read operations are blocking, so you can't simply say "read all that's been printed yet".
After you're finished you quit CMD.EXE via cmd.Terminate.

Hiding curl Window on Windows

One of the answers on a previous question mentioned that I can use curl to fetch a url; this can be done in Thread.new or in Process.spawn. But it seems that in either case, on Windows, I get a small command-prompt window appearing while curl is going out to the network.
I am invoking curl like this:
`curl "#{url}"`
Is there any way to hide the window so that it doesn't appear? Not only does it grab the focus away from the game (freezing it), but if I make frequent calls, it will be extremely annoying to the end user.
After some experimenting i got it working, no window when doubleclicking on the script, i use WMI from ruby, you just have to alter the path to curl.
IMPORTANT: save it with the extension .rbw and make sure that rubyw.exe is associated with that extenstion.
#hidden_curl.rbw
require 'win32ole'
HIDDEN_WINDOW = 0
cmd = '"C:\\Program Files\\curl\\curl.exe" --output c:\\test2.txt "http://stackoverflow.com/questions/10869789/hiding-curl-window-on-windows"'
objStartup = WIN32OLE.connect("winmgmts:\\\\.\\root\\cimv2:Win32_ProcessStartup")
objConfig = objStartup.SpawnInstance_
objConfig.ShowWindow = HIDDEN_WINDOW
objProcess = WIN32OLE.connect("winmgmts:root\\cimv2:Win32_Process")
errReturn = objProcess.Create(cmd, nil, objConfig, nil)
Hope this works on your system.
You could try passing the -s option to curl which will make it run in silent mode.
Something like
`curl -s "#{url}"`
I am guessing this will not show up the console.
I think you problem is that you run the command in a subshell and the subshell in windows is CMD which is attached to a window.
I don't have a ruby to test the following but you could try :
IO#popen
Runs the specified command string as a subprocess;
The subprocess‘s standard input and output will be connected to the returned IO object.
=> http://ruby-doc.org/core-1.8.6/IO.html if IO is available to you
you could also try to run
start /B curl -s "#{url}" instead of just curl see http://www.computerhope.com/starthlp.htm for start specs.
This solution doesn't pop up a window on my W7 system
cmd = '"C:\Program Files\curl\curl.exe" --silent --output c:\test.txt "http://stackoverflow.com/questions/10869789/hiding-curl-window-on-windows"'
IO.popen(cmd)
or without creating a file
cmd = '"C:\Program Files\curl\curl.exe" --silent "http://stackoverflow.com/questions/10869789/hiding-curl-window-on-windows"'
IO.popen(cmd, "w+") { |io| puts io.readlines }

Resources