Discussion:
timeout on a line and resume
(too old to reply)
1***@gmail.com
2015-02-23 19:26:29 UTC
Permalink
Hi, can I be helped?

I am trying to copy a file from multiple computers, each on should only take about 2 seconds.
Instead of waiting for the timeout if on of the computers is not available, can I say resume to next line after 2 seconds?

Maybe even echo that that computer is not online?

Thanks for your help!!
Cisco
Evertjan.
2015-02-23 21:01:54 UTC
Permalink
Post by 1***@gmail.com
Hi, can I be helped?
I am trying to copy a file from multiple computers, each on should only
take about 2 seconds. Instead of waiting for the timeout if on of the
computers is not available, can I say resume to next line after 2
seconds?
Maybe even echo that that computer is not online?
What platform, the web?
--
Evertjan.
The Netherlands.
(Please change the x'es to dots in my emailaddress)
JJ
2015-02-23 21:24:32 UTC
Permalink
Post by 1***@gmail.com
Hi, can I be helped?
I am trying to copy a file from multiple computers, each on should only
take about 2 seconds. Instead of waiting for the timeout if on of the
computers is not available, can I say resume to next line after 2
seconds?
Maybe even echo that that computer is not online?
Thanks for your help!!
Cisco
No. VBScript is only single-threaded. You can't do more than one tasks
unless you let the additional tasks be handled by separate programs.

So, you'll need to handle things differently to get what you wanted.

e.g. for one file copy process...

1. Get current time and put it in a variable. This is the starting time.

2. Execute a separate VBS file using C/WSCRIPT.EXE. This VBS file's job
should simply copy a file from source to the target.

3. Start an infinite loop.

3.a. If the copied file exists and has the same size as the source, break
out of the loop and you're done. Otherwise, proceed to next step.

3.b. Get current time and calculate the elapsed time since the starting
time.

3.c. If the elapsed time is equal or longer than 2 seconds, break out of the
loop and you're done. Otherwise, issue a pause for e.g. 100ms using
WScript.Sleep to give CPU time for other process. Then loop from the start.
Mayayana
2015-02-23 23:48:04 UTC
Permalink
As JJ said, you can't do what you want within
a script. The script just goes from step to step.
But you can call outside processes.

The most flexible way to do something like that
is with an ActiveX EXE that can trigger events.
The WScript version of CreateObject can then be
used to create an event "sink":

WScript.CreateObject("Server1.Class1", "Sink1_")

If Server1.Class1 has an event like FileCopied
you can then trap it with
Sub Sink1_FileCopied()

That allows you to pass parameters to the event.
Designing your own ActiveX EXE allows for a very
luxurious design. But it does require writing a
component.

An easier way is something like the following:

Write a script like so and save it to the Desktop
as sleeper.vbs:

Arg = WScript.Arguments(0)
WScript.sleep Arg
MsgBox "Slept for " & CStr(arg \ 1000) & " seconds."

Then write another script to the Desktop like so:

Dim SH, i
Set SH = CreateObject("WScript.Shell")
For i = 1 to 3
SH.Run"sleeper.vbs " & 10000 * i
Next
Set SH = Nothing

If you then run script #2 it will run 3 instances of
sleeper.vbs, running 10, 20 and 30 seconds
respectively. The msgbox reports will confirm
that. So if you want to you could write a copy script
that keeps time and then either reports or, perhaps
better, writes a report to a log.

The following is "air code" and may not be the
best method, but it provides a general idea of how
you could do what you want. It's very sloppy,
though, needing to instantiate a new instance of
wscript for every file copy. Also, it might be tricky
to come up with a way to log it all. If every instance
opens a log file, writes, then closes the log, it's
possible there could be a traffic jam, with some
instances encountering a locked/open log file. Script
just isn't really the best tool for this job. It'd be better
if you can arrange it in such a way that you have time
to wait up to 2 seconds for each copy. Then you could
let one script handle the whole job.


Dim FSO, Arg, iTime
Arg = WScript.Arguments(0)
Set FSO = CreateObject("Scripting.FileSystemObject")
If FSO.FileExists(Arg) = True Then
Do
On Error Resume Next
FSO.CopyFile Arg, TheOtherPlace, True
If Err.Number = 0 Then
'quit loop and report file copied successfully.
Set FSO = Nothing
WScript.Quit
End If
WScript.sleep 100
iTime = iTime + 1
If iTime = 20 Then Exit Do
Loop

'-- if it got this far then copy failed
'-- And it's been about 2 seconds.
'-- report failure.
JJ
2015-02-24 18:52:48 UTC
Permalink
Post by Mayayana
As JJ said, you can't do what you want within
a script. The script just goes from step to step.
But you can call outside processes.
The most flexible way to do something like that
is with an ActiveX EXE that can trigger events.
The WScript version of CreateObject can then be
[snip]

Now that you mentioned "sink", WMI can be used as an alternative to ActiveX
since it's available on every Windows installations (except Windows 9x and
NT4.0, perhaps), and it supports asychronous function call and notification.

But the disadvantage is that it doesn't directly support UNC paths for file
copy, so it will have to be mapped/unmapped to a drive letter, at script run
time. And the mapping/unmapping process may cause noticeable and unavoidable
delays.

This is the script for copying one file using WMI. It's also possible to
cancel the file copy operation in case of unresponsive computer. But in my
experience, when Microsoft Network hits such computer, cancelling it will
have no effect and would make the cancel operation to get frozen too.

sComputer = "."

set oServices = GetObject( _
"winmgmts:" & "!\\" & sComputer & "\root\cimv2")
set oDataFile = oServices.Get("CIM_DataFile")

'---start of file copy

'!!Paths must use drive letter!!
sSrcFilePath = "Z:\Mapped\Share\data.ext"
sDestFilePath = "E:\Data\data.ext"

set oInParams = oDataFile.Methods_("Copy").InParameters.SpawnInstance_
oInParams.FileName = sDestFilePath

bDone = false
iError = 0
set oSink = WScript.CreateObject("WbemScripting.SWbemSink", "Sink_")
set oContext = WScript.CreateObject("WbemScripting.SWbemNamedValueSet")
oContext.Add "FilePath", sSrcFilePath
oServices.ExecMethodAsync oSink, "CIM_DataFile.Name=""" & _
replace(sSrcFilePath, "\", "\\") & """", "Copy", oInParams, 0, _
null, oContext

while (not bDone) and (iError = 0)
WScript.Sleep 200
wend

if iError <> 0 then
WScript.Echo "File copy failed. Error code " & iError & "."
else
WScript.Echo "File copy succeeded."
end if

'---end of file copy

WScript.Echo "Script ended."

'---------

sub Sink_OnObjectReady(oOutParams, oContext)
iError = oOutParams.ReturnValue
WScript.Echo "*OnObjectReady: ReturnValue=" & _
oOutParams.ReturnValue
end sub

sub Sink_OnCompleted(hResult, oError, oContext)
bdone = true
if iError = 0 then iError = hResult
WScript.Echo "*OnCompleted: hResult=0x" & hex(hResult) & _
"; FilePath=" & oContext("FilePath").Value
end sub
JJ
2015-02-24 20:17:51 UTC
Permalink
On Wed, 25 Feb 2015 01:52:48 +0700, JJ wrote:
[snip]
This is the script for copying one file using WMI. ...
[snip]

Oops. I forgot to add the 2 seconds limit.

tStart = Now
while (not bDone) and (iError = 0) and (DateDiff("s", tStart, Now) < 2)
WScript.Sleep 200
wend

Since DateDiff can't provide the milliseconds part of the time, it's
inaccurate for this purpose. e.g. a duration of 1500ms will be returned as 2
seconds.

Maybe there's a better solution for this?
Dr J R Stockton
2015-02-25 21:19:33 UTC
Permalink
In microsoft.public.scripting.vbscript message <3iu01xlmegvd.1g84ft7i74x
Post by JJ
[snip]
This is the script for copying one file using WMI. ...
[snip]
Oops. I forgot to add the 2 seconds limit.
tStart = Now
while (not bDone) and (iError = 0) and (DateDiff("s", tStart, Now) < 2)
WScript.Sleep 200
wend
Since DateDiff can't provide the milliseconds part of the time, it's
inaccurate for this purpose. e.g. a duration of 1500ms will be returned as 2
seconds.
Maybe there's a better solution for this?
IIRC, function Timer.

<http://www.merlyn.demon.co.uk/vb-date1.htm#Tim> (Read this with
Internet Explorer, but not tested after IE8).
--
(c) John Stockton, nr London, UK. E-mail, see Home Page. Turnpike v6.05.
Website <http://www.merlyn.demon.co.uk/> - w. FAQish topics, links, acronyms
PAS EXE etc. : <http://www.merlyn.demon.co.uk/programs/> - see in 00index.htm
Dates - miscdate.htm estrdate.htm js-dates.htm pas-time.htm critdate.htm etc.
JJ
2015-02-26 12:18:21 UTC
Permalink
Post by Dr J R Stockton
In microsoft.public.scripting.vbscript message <3iu01xlmegvd.1g84ft7i74x
Post by JJ
[snip]
This is the script for copying one file using WMI. ...
[snip]
Oops. I forgot to add the 2 seconds limit.
tStart = Now
while (not bDone) and (iError = 0) and (DateDiff("s", tStart, Now) < 2)
WScript.Sleep 200
wend
Since DateDiff can't provide the milliseconds part of the time, it's
inaccurate for this purpose. e.g. a duration of 1500ms will be returned as 2
seconds.
Maybe there's a better solution for this?
IIRC, function Timer.
<http://www.merlyn.demon.co.uk/vb-date1.htm#Tim> (Read this with
Internet Explorer, but not tested after IE8).
The problem is that, Timer is the number of seconds since 12:00am. So it'll
reset back to zero at 12:00am each day.

I'm not really sure, but I think it can be solved with below function.

Function Timestamp
Timestamp = (Now * 86400000) + ((Timer * 1000) Mod 1000)
End Function

tStart = TimeStamp
While (not bDone) And (iError = 0) And ((Timestamp - tStart) < 2000)
WScript.Sleep 200
Wend

Loading...