vbscript: Constantly check if file(s) exists and display life-time - file

I got a very specific question regarding my code.
So I got a folder. In this folder there can be >=0 files.
My first script is running in the background, checking if file-count is >0.
As soon as it is >0, it activates a second script with the path+filename, and as soon as
a file is deleted/removed from the folder, it displays the lifetime of the file.
Everything works fine, but there is one problem:
If there are multiple Files in the folder simultaniously, it only "observers" the top one (filename,ascending). So if the first one gets deleted, it sure does observe the second, but the lifetime is wrong because it did not start until the first one got deleted.
Here are my two codes:
Script1.vbs:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
While True
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Next
End If
WScript.Sleep 2000
WEnd
Script2.vbs:
filename = CStr(WScript.Arguments(0))
pfad = CStr(WScript.Arguments(1))
Set fso = CreateObject("Scripting.FileSystemObject")
startZeit = Timer()
komplett = pfad&"\"&filename
While fso.FileExists(komplett) = True
WScript.Sleep 100
WEnd
endZeit = Timer()
differenz = endZeit-startZeit
msgbox "Existenz von Job " & filename & " in Sekunden: " & differenz

Thanks for your help guys.
#Bond: Removing the while true loop is no option, since the program is not allowed to stop running. Even if there are no files at this time, there will always be new files later which have to be observed too. But your hint with the "false" parameter of the Run-Statement was great!
#Rob1991:
Good idea, that was actually my first idea before I put my question here.
I figured it out by myself with a different solution. Maybe it helps anybody:
Set fso =CreateObject("Scripting.FileSystemObject")
If WScript.Arguments.Count = 1 Then
pfadTiff0 = CStr(WScript.Arguments(0))
Else
msgbox "Bitte Argumente (Pfade) angeben"
WScript.Quit
End If
Set ordnerTiff0 = fso.GetFolder(pfadTiff0
Set filesTiff0 = ordnerTiff0.Files
letztesFile = "000a" // PART OF SOLUTION, IT´S "LAST FILE"
While True
For Each objFile in filesTiff0
If objFile.Name > letztesFile Then // PART OF SOLUTION
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False // thanks Bond for "false"
letztesFile = objFile.Name // PART OF SOLUTION
End If
Next
WScript.Sleep 500
WEnd

This statement:
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, True
Uses a value of True as the last parameter. That specifies that you want to wait until the script completes (synchronous) before returning. So your main script is put in a wait state until your second script (QueueTimeUp.vbs) exits, which doesn't happen until the first file is deleted.
You should be able to use False as the last param, which doesn't wait for the second script to complete. Then remove your While True loop and just allow your main script to complete.
' Main script. Remove "While True" loop.
Set ordnerTiff0 = fso.GetFolder(pfadTiff0)
Set filesTiff0 = ordnerTiff0.Files
anzFilesTiff0 = ordnerTiff0.Files.Count
If anzFilesTiff0 > 0 Then
For Each objFile in filesTiff0
' Use False for last param to specify asynchronous call...
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0, 0, False
Next
End If
' Allow script to complete.
Now you'll have a QueueTimeUp.vbs script running for each file in your folder.
FYI: If you're familiar with scripting WMI via VBScript, it provides the __InstanceCreationEvent and __InstanceDeletionEvent classes that can notify your script when a file is created or deleted, respectively. Then you won't have to poll a folder every few seconds looking for changes.

I believe for each file it will load the vbs2, but will not start the next execution until vbs2 has ended. If i used the following code below it will not iterate until the instance of cmd has been ended
For Each objFile in colFiles
oShell.run "cmd /k CD C:\Program File" ,1 , true
Next
I think you would want to have a start timer in your first vbs, and then pipe it to the second vbs2. Which would mean the start time is only called once at the start of the programs execution
startZeit = Timer()
For Each objFile in filesTiff0
CreateObject("WScript.Shell").Run "QueueTimeUP.vbs " & objFile.Name & " " & pfadTiff0 & " " & startZeit , 0, True
Next
vbs 2
startZeit = CStr(WScript.Arguments(2))
Hope this helps

Related

How to open exe file with parameters

I have batch file & vbs file that runs exe application in hidden mode.
Now I would like to open this exe applicatio, but with parameters passed to it.
Batch file:
wscript.exe "C:\~some path~\invisible2.vbs" "C:\~some path~\Rserve_d.exe"
invisible2.vbs:
CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False
Above code makes sure it runs hidden. But now I need to pass this parameter to the Rserve_d.exe when starting it:
--RS-conf "E:\~some path~\Rconf.cfg"
Please advise. I've tried with adjustments, but it seems, that there is always something wrong in the syntax.
Build the arguments string for your command from the arguments to the script:
Function qq(str)
qq = """" & str & """"
End Function
args = ""
For i = 1 To WScript.Arguments.Count - 1
If InStr(WScript.Arguments(i), " ") > 0 Then
args = " " & qq(WScript.Arguments(i))
Else
args = " " & WScript.Arguments(i)
End If
Next
CreateObject("Wscript.Shell").Run qq(WScript.Arguments(0)) & args, 0, False
Ansgar Wiechers posted his answer before I did so he should deserve the credits. Unfortunately, I had already made the effort of posting an answer as well. To provide some additional functionality to your batch script, you could also check for the return value of the executed VBScript.
Batch file:
setlocal
set "script=c:\~some path~\invisible2.vbs"
set "program=c:\~some path~\rserve_d.exe"
set "params=--RS-conf "e:\~some path~\rconf.cfg""
cscript "%script%" //nologo "%program%" %params%
:: %errorlevel% = 0 - VBScript was executed successfully
:: %errorlevel% = 1 - Missing arguments
:: %errorlevel% = 2 - Shell object creation failed
:: %errorlevel% = 3 - Run method was unable to execute the program
VBScript:
Option Explicit
On Error Resume Next
Dim objShell,_
strCmdLine,_
intCount
If (WScript.Arguments.Count < 1) Then
WScript.Quit(1)
End If
Set objShell = WScript.CreateObject("WScript.Shell")
If (Err.Number <> 0) Then
WScript.Quit(2)
End If
For intCount = 1 To WScript.Arguments.Count - 1
strCmdLine = strCmdLine & " " & """" & WScript.Arguments.Item(intCount) & """"
Next
objShell.Run """" & WScript.Arguments.Item(0) & """" & strCmdLine, 0, False
If (Err.Number <> 0) Then
WScript.Quit(3)
End If

Windows batch script spawn normal windows copy process

Im writing a batch script to help me collect some bandwidth data about numerous offices on our WAN. It uses random data file creator to help me avoid wan optimisers affecting the results.
How can I copy a file by spawning a standard windows copy window that shows transfer rate?
If i use the 'copy' method, it just copies silently in the cmd window and i cant see the rate.
if not exist "C:\temp\xfertest" mkdir C:\test\xfertest
rdfc C:\test\xfertest\random100.dat 100000000
copy C:\test\xfertest\random100.dat \\nat-srv-007\Deliver
exit
This vbscript wrappped in a batch file will do what you want. Save it with a .bat/.cmd extension. Or without the first line with a .vbs extension.
The technic used is based on com and works with every script language supporting it.
Just to see start/end date time, total bytes and bytes per/s it outputs these values to the console after the copy dialog window has vanished.
rem^ &#cscript //nologo //e:vbscript "%~f0" %* & exit /b
' Copy with the windows dialog box
Option Explicit
Dim cArgs : Set cArgs = WScript.Arguments
Dim iArgCnt : iArgCnt = cArgs.Count
Dim sSource : sSource = cArgs.Item(0)
Dim sDest : sDest = cArgs.Item(1)
Dim oFS : Set oFS = CreateObject("Scripting.FileSystemObject")
Dim oSH : Set oSH = CreateObject("shell.application")
Dim oFile, Size, dStart, dEnd
If iArgCnt <> 2 Then
Wscript.Echo "Wrong args, need SourceFile and DestFolder"
Wscript.Quit
End if
If oFS.FileExists(sSource) Then
Set oFile = oFS.GetFile(sSource)
Size = oFile.Size
If oFS.FolderExists(sDest) Then
dStart = Now()
Wscript.Echo "Copy : " & sSource & " " & sDest
Wscript.Echo "Start: " & dStart & " Size : " & Size
FolderCopyHere sSource, sDest
dEnd = Now()
Wscript.Echo "End : " & dEnd & " per/s: " & _
Int(Size / DateDiff("s", dStart, dEnd))
Else
Wscript.Echo "Destination Folder doesn't exist" & sDest
End if
Else
Wscript.Echo "Source file doesn't exist" & sSource
End if
Wscript.Quit
function FolderCopyHere(sSource,sDest)
dim oFld
set oFld = oSH.NameSpace(sDest)
if not oFld is nothing then
oFld.CopyHere(sSource)
end if
set oFld = nothing
end function
Returning this output on my pc
20:28:24 C:\Test________________________________________
> k:\Bat\CopyExpl.cmd c:\test\big.file Q:\Test
20:28:36 C:\Test________________________________________
> rem &
Copy : c:\test\big.file Q:\Test
Start: 2016-10-30 20:28:36 Size : 2147483648
End : 2016-10-30 20:29:10 per/s: 63161283
20:29:10 C:\Test________________________________________
The Rem stems from the wrapper the dialog box is widely known. HTH

determine whether user clicked NO in UAC prompt

My VBScript file:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute(WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0)
WScript.Quit 2
WScript.Echo("Done 1")
Else
I need a way to determine, whether the user clicked NO and then return an errorcode to a batch file. Does ShellExecute return any error codes or something?
The problem is that the errorcode returned to the bat is always the same (in this case 2), regardless of whether I clicked yes or no.
EDIT:
Dim objShell, objWMIService, servSpooler, objReg, objShellApp, result, oShell
Dim whoami, strWhoamiOutput, whoamiOutput
Const PrinterPort = "NUL:"
Const HKLM = &h80000002
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Set oShell = CreateObject("WScript.Shell")
Set whoami = oShell.Exec("whoami /groups")
Set whoamiOutput = whoami.StdOut
strWhoamiOutput = whoamiOutput.ReadAll
If InStr(1, strWhoamiOutput, "S-1-16-12288", vbTextCompare) Then
Wscript.Echo("ADMIN")
WScript.Echo("Port")
Set objWMIService = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2")
set servSpooler = objWMIService.Get("Win32_Service.Name='spooler'")
Set objReg = GetObject("winmgmts:root\default:StdRegProv")
servSpooler.StopService
objReg.SetStringValue HKLM, "SOFTWARE\Microsoft\Windows NT\CurrentVersion\Ports", PrinterPort, ""
servSpooler.StartService
WScript.Quit 1
End if
WScript.Echo("Done 2")
End If
WScript.Quit 2
WScript.Echo("Done 3")
It only ever returns the errorcode of the very first WScript.Quit, after getting the elevating rights. No matter whether I click no or yes. When I click yes, it runs the program as expected, and it does quit after starting the spooler, but the error code returned to the batch is still that of the first Wscript.Quit and not the one after the spooler.
I expect this to run as follows:
no elevated rights
get the elevation, if no, Quit with 10
if user clicked yes: run the script again
run the code in the ELSE block, quit with WScript.Quit 1
the code after the END IFs should never run
EDIT:
If Not WScript.Arguments.Named.Exists("elevate") Then
Set objShellApp = CreateObject("Shell.Application")
objShellApp.ShellExecute WScript.FullName, WScript.ScriptFullName & " /elevate", "", "runas", 0
WScript.Quit 10
WScript.Echo("Done 1")
Else
Dim fso, MyFile
Set fso = CreateObject("Scripting.FileSystemObject")
Set MyFile = fso.CreateTextFile("testfile.txt", True)
MyFile.WriteLine("This is a test.")
MyFile.Close
End If
WScript.Quit 2
WScript.Echo("Done 3")
When I run this from .../System32 it lets me create a file when I click yes. Still, the errorcode is always the same, whether I click yes or no.
Try to create a file in c:\windows\system32 and test the error code.
Only a program marked RequireAdmin will fail when executed. Everything else will start as a limited user.
For your method.
Return Value
No return value.
WScript has a two execute methods. Both have different features so read the docs.
object.Exec(strCommand)
The Exec method returns a WshScriptExec object, which provides status and error information about a script run with Exec along with access to the StdIn, StdOut, and StdErr channels.
object.Run(strCommand, [intWindowStyle], [bWaitOnReturn])
bWaitOnReturn
Optional. Boolean value indicating whether the script should wait for the program to finish executing before continuing to the next statement in your script. If set to true, script execution halts until the program finishes, and Run returns any error code returned by the program. If set to false (the default), the Run method returns immediately after starting the program, automatically returning 0 (not to be interpreted as an error code).
One of your problems is that your code is not written correctly.
You must have On Error Resume Next or your script would have crashed. You use this statement for simple scripts that you want to keep going in case of error. In real scripts it indicates you are handling errors rather than vbs. So you need to code like this.
servSpooler.StartService
If err.number <> 0 then
'print error, exit script
wscript.echo err.number & " " & err.description & " in " & err.source
err.clear
wscript.quit
End If
But if you use vbs error handling it knows the line and column number.
Noooooooo - create the file in code.
On Error Resume Next
'Should fail for everyone so simulates being a user for an admin
Set fso = CreateObject("Scripting.FileSystemObject")
fso.CreateTextFile "C:\System Volume Information\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If
'Should succeed for admins
fso.CreateTextFile "c:\windows\system32\test.txt", vbtrue
msgbox err.number & " " & err.description & " " & err.source
If err.number = 70 then
msgbox "access denied - not an admin"
err.clear
Elseif err.number <> 0 then
Msgbox "Unspecified error"
err.clear
Else
Msgbox "Is an admin"
End If

vbs file drag and drop a folder

I need to make a vbs file that asks for the minimum file size when you drag and drop a folder to it. It's a little wierd. But then, it should return the input as a string that will be turned into an integer. Then it should look for files that are bigger than this minimum file size(all, i guess) and list their folder(if it's in a sub-folder), name and size.
I found some stuff on the internet but I'm a bit lost
Option Explicit
Dim FolderPath, objFSO, objFolder, objFile, input, objArgs
input = InputBox("Minimum size: ")
Set objArgs = Wscript.Arguments
Set objFSO = CreateObject("Scripting.FileSystemObject")
For i = 0 to objArgs.count
on error resume next
Set objFolder = objFSO.GetFolder(objArgs(i))
If err.number <> 0 then
ProcessFile(objArgs(i))
Else
For Each file In folder.Files
ProcessFile(file.path)
Next
End if
On Error Goto 0
Next
Function ProcessFile(sFilePath)
msgbox "Now processing file: " & sFilePath
For each objFile in objFolder.Files
WScript.Echo objFile.Name, objFile.Size & "bytes" & VbCR_
& "created: " & objFile.DateCreated & VbCR_
& "modified: " & objFile.DateLastModified
Next
You've got some issues in your code. You're using folder.files but you don't have folder declared (or defined) anywhere. The only reason you're not getting an error is because you have On Error Resume Next specified. There's no need to use On Error here and it should be removed so that you can properly debug your script. Here's a starting point for you.
' Get the folder dropped onto our script...
strFolder = WScript.Arguments(0)
' Ask for minimum file size...
intMinSize = InputBox("Minimum size: ")
' Recursively check each file with the folder and its subfolders...
DoFolder strFolder
Sub DoFolder(strFolder)
' Check each file...
For Each objFile In objFSO.GetFolder(strFolder).Files
If objFile.Size >= intMinSize Then
WScript.Echo "Path: " & objFile.Path & vbCrLf & "Size: " & objFile.Size
End If
Next
' Recursively check each subfolder...
For Each objFolder In objFSO.GetFolder(strFolder).SubFolders
DoFolder objFolder.Path
Next
End Sub
This isn't a complete script. Notice I haven't declared objFSO anywhere. I haven't checked that strFolder is a valid folder or that intMinSize is actually a number. I'll leave it up to you to fill in the missing pieces. But this should get you going.

monitor last modified time for a folder using batch file

I have a folder on my workstation where files are added every minute.
I have to monitor this folder every now and then, to see if new files are being added.
In case there is no new file in this folder for say 5 min, we perform an action.
Can we use batch file for this purpose in such a way that if there is no new file added for last 5 min, an alert /pop up apears on window screen.
Also I m new to Batch .Please let me know the steps
It seems unlikely that you are going to accomplish what you want to do with purely a batch file.
However, you can do this in a relatively simple/small VB Script, that doesn't require any additional installation on the system.
'-------------------------------------------------------------
' Monitors a folder for new files and warns if they
' are not being created within a certain time period.
'-------------------------------------------------------------
Dim intMinutes: intMinutes = 5 ' minute threshold for warning of no new files
Dim strDrive: strDrive = "c:" ' drive to monitor
Dim strPath: strPath = "\\temp\\" ' path to monitor. remember to double slashes
Dim intTimer: intTimer = "2"
Dim strComputer: strComputer = "."
Dim objWMIService: Set objWMIService = GetObject( "winmgmts:" & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2" )
Dim strQuery: strQuery = "Select * From __InstanceOperationEvent" & " Within " & intTimer & " Where Targetinstance Isa 'CIM_DataFile'" & " And TargetInstance.Drive='" & strDrive & "'" & " And TargetInstance.Path='" & strPath & "'"
Dim colEvents: Set colEvents = objWMIService. ExecNotificationQuery (strQuery)
Dim LastNew: LastNew = Now
WScript.Echo "Monitoring new file creation... Press [Ctrl]-[C] to exit"
Do
Set objEvent = colEvents.NextEvent()
Set objTargetInst = objEvent.TargetInstance
Select Case objEvent.Path_.Class
Case "__InstanceCreationEvent"
LastNew = Now
End Select
if DateDiff("n",LastNew,Now) >= intMinutes then
' put whatever actions you want in here... the following two lines are for demo purposes only
msgbox "The last new file was " & DateDiff("n",LastNew,Now) & " minute ago!",0,"No New Files"
exit do
end if
Loop
Execute this in WScript to make it not visible or CScript to show the console window.
Replace the code inside the IF block to do what you need done (notify you of the issue).

Resources