Im using ping to create a delay in my batch file, but there seems to be quite a big limit on how short you can make the ping delay.
ping -n 1 -w 1 1.1.1.1
this will wait for maybe 500ms
ping 127.0.0.1
this will wait for maybe 100ms
So is there a way to get an even smaller delay?
This is on XP, so "timeout" isnt enabled
You can do this in XP with Windows scripting, by creating a VBScript file millisleep.vbs that looks like this (with decent error checking built in):
if wscript.arguments.count <> 1 then
wscript.echo "millisleep.vbs: Not enough arguments"
wscript.quit 1
end if
delay = wscript.arguments(0)
if not isnumeric(delay) then
wscript.echo "millisleep.vbs: " & delay & " is not numeric"
wscript.quit 1
end if
wscript.sleep delay
Then, from your own script, you can use something like this to get a quarter-second delay:
cscript //nologo millisleep.vbs 250
Related
This is a weird question based on bad VBScript behavior that I am trying to work around. Please bear with me and thank you in advance.
In VBScript, you can do the following to start a task:
Set WshShell = CreateObject("WScript.Shell")
Set WshShellExec = WshShell.Exec(strCommand)
Do While WshShellExec.Status <> WshFinished
WScript.Sleep(1000)
Loop
However, there is a bug where, if the command/task started by the WshShell.Exec call writes >=4kb to either StdOut or StdErr, WshShellExec.Status will never be equal to WshFinished (1). I assume this is because there is no space in a buffer the system uses for stdout/stderr, so the initiated task hangs on the next write to stdout/stderr once it writes enough bytes to the buffer(s).
Depending on the program running, you may be able to do something like the following to get around it:
Set wshShellExec = WshShell.Exec(cmd)
Set objStdOut = wshShellExec.StdOut
Set objStdErr = wshShellExec.StdErr
Do Until objStdOut.AtEndOfStream
standardout = standardout & objStdOut.ReadLine & vbCrlf
Loop
Do Until objStdErr.AtEndOfStream
errtext = errtext & objStdErr.ReadLine & vbCrlf
Loop
However, this does not always work. If the running program writes 4kb to stderr before writing anything to stdout, this code hangs on the evaluation of objStdOut.AtEndOfStream or on objStdOut.ReadLine (note, you cannot use objStdOut.ReadAll because that will also block forever).
So, I've come up with the following solution that seems to work:
strCommand = "c:\Windows\System32\cmd.exe /C StdOutTester.exe > " & rsltTextFile & " 2>&1 || call echo %^errorLevel% > " & rsltErrCodeFile
Set WshShellExec = WshShell.Exec(strCommand)
Do While WshShellExec.Status <> WshFinished
Wscript.Sleep(1000)
secCount = secCount+1
If secCount >= 10 Then 'kill children
If KillTaskChildren(WshShellExec.ProcessID) <> 0 Then
WScript.Echo "WMI Terminate Failed. Killing CMD..."
WshShellExec.Terminate
End If
End If
Loop
What this does is run the actual task in another cmd window and redirect both stdout/stderr into a file (and also the error code if applicable). Because I'm running the command in another cmd window, stdout and stderr are decoupled from the WshShellExec object. This also allows me to kill the running task for a timeout (the real one, i.e. not the cmd window but the actual task, by using WMI).
So, my question becomes this:
Since I am running another cmd.exe window, it is possible that cmd prompt itself runs into the same issue if it writes enough data into stdout/stderr (in which case, my timeout logic should kill it)? Does it ever actually write anything into stdout/stderr? What about if I use the /Q option?
I was wondering if there is any better way to wait until program starts before interacting with it?
Right now I'm using sleep which isn't exactly great.
Just to be clear I don't want to wait until program is finished (terminated) just to wait until it starts to be able to interact with it.
my code:
set MyShell = WScript.CreateObject("WScript.Shell")
MyShell.Run "<path to my exe app>"
WScript.Sleep 4000
MyShell.AppActivate "<my app name>"
MyShell.SendKeys "{TAB}"
...
I've tried to make it myself, but it didn't work, as I'm not experienced enough with .bat to get it working.
So what I need is bascily a .bat file which I only need to click once and it will "simulate" me clicking the key 'Enter' every 10800 seconds (3 hours) in a loop, so that it doesn't ever stop clicking the key 'Enter' with a loop time of 10800 seconds, would someone help me out please! :)
You can do this with VBScript and the WScript host:
Save this as "press_enter.vbs" and run it from the CLI with "wscript press_enter.vbs"
Dim WshShell, FSO, secs
Set WshShell = WScript.CreateObject("WScript.Shell")
Set FSO = CreateObject("Scripting.FileSystemObject")
secs = 10800
kill_file = "C:\Users\Public\Documents\kill_switch.txt"
Do While true
WScript.Sleep(secs * 1000) ' this is in milliseconds, multiple by 1000
WshShell.SendKeys "{ENTER}"
if FSO.FileExists(kill_file) then exit do
Loop
As you probably guessed, the program runs forever until it detects the existence of the file "C:\Users\Public\Documents\kill_switch.txt"
You can also kill the program by opening Task Manager and killing the "Microsoft Windows Based Script Host" which will be listed under the "Background processes" section...
Remember that if you stop the application with the "kill_switch.txt" file, you will need to remove it before you start the application again. Perhaps it is best just to kill it with Task Manager...
Hey guys my Applescript doesn't do what I expect.
Where is my mistake?
try
set NAS to do shell script "ping -c 1 192.168.222.5"
if NAS contains "100.0% packet loss" then repeat until NAS contains "0% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5"
end repeat
delay 20
tell application "Terminal" to activate
end try
I want ping to my NAS and when I don't get response I want to wake him up, but my script stops after send ping without response.
Any idea what I am doing wrong?
I want to send packets until the NAS wakes up.
I have changed the Code
try
do shell script "ping -c 1 192.168.222.5"
on error
set NAS to "100% packet loss"
repeat while NAS contains "100% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5"
if NAS contains "0% packet loss" then exit repeat
end repeat
say "Server startet, 20 sek"
delay 20
end try
tell application "Terminal" to activate
now i don't know how i get the loop to work with the on error command wich i get from the ping
Even if you have found the solution yourself there is no answer here so I try to complete it here. The string when we lay both strings on top of eachother we'll see "100.0%packet loss". As you can see when looking for "0% packet loss" it always will return true when you're sending just 1 packet. To be better safe than sorry you'd better match the entire line "1 packets transmitted, 1 packets received, 0.0% packet loss". Your first solution would be solved by changing the matches (also you can get rid if the if statement, if ping succeeds the first time the repeat will not run once):
set NAS to do shell script "ping -c 1 192.168.222.5 || true"
repeat until NAS contains "1 packets transmitted, 1 packets received, 0.0% packet loss"
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
set NAS to do shell script "ping -c 1 192.168.222.5 || true"
end repeat
delay 20
tell application "Terminal" to activate
Update: A better version who does not match the printed string from ping but matches the returned number and coerce it into a boolean value.
repeat until ping("192.168.222.5")
do shell script "python /Users/Selim/Desktop/wol2.0.sh"
end repeat
delay 20
tell application "Terminal" to activate
on ping(IPNumber)
return (do shell script "ping -t 1 -c 1 " & IPNumber & " >/dev/null && echo yes || echo no") as boolean
end ping
the working script now:
try
do shell script "ping -c 1 192.168.222.5"
on error
set NAS to "q"
repeat until NAS contains "1 packets transmitted, 1 packets received, 0.0% packet loss"
do shell script "python /Users/Selim/Documents/scripte/wol2.0.sh"
delay 0.1
try
set NAS to do shell script "ping -c 1 192.168.222.5"
end try
end repeat
delay 5
end try
tell application "Kodi" to activate
I have a scheduled task which runs on my server to put 2 other desktop machines asleep at 2am.
I also have a .bat file scheduled to run at 1:40am on all of my systems to let me know of the impending shutdown operation and give me the option to cancel, standby immediately or close the window and allow it to proceed. Works fine on all systems except a Win7 Laptop.
Despite me having the task set not to run past it's scheduled time, if I open my laptop and it resumes from standby any time after 2am, the file will still run.
I wanted to try and create a workaround by scheduling a .vbs to launch the .bat instead. Along the lines of:
if Hour(Time) > 1 Then
wscript.quit
else if Hour(Time) = 1 Then
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "cancel-confirm-autostandby.bat C:\WINDOWS\system32\cmd.exe", 1
end if
wscript.quit
But the .bat file runs regardless, even testing now at 3am. If I try;
msgbox Hour(Time)
It returns a value of 3, so I don't understand this behavior. 3 is > than 1...
I have tried assigning the cutoff time (2am) to a varible tried Hour(Now) & Hour(Date).
Any suggestions welcome, thank you for reading...
Seem to have got it with
if Hour(Time) > 1 Then
wscript.quit
else if Hour(Time) = 1 Then
Set objShell = WScript.CreateObject("WScript.Shell")
objShell.Run "cancel-confirm-autostandby.bat C:\WINDOWS\system32\cmd.exe", 1
end if
wscript.quit
End if
Don't know why it wouldn't work with just the second last "End if", but there you go...