How do I code the progress property under VBScript

Hi folks,

I'm working on a function to add missing EXIF informations to files using their filename.

I coded it in VBScript and it works so far...

Now I' like to have a progressbar to show me how long the process will take.

Here's my working code without progress bar:

Option Explicit
Function OnClick(ByRef ClickData)

Dim strFileName
Dim arrFileName
Dim strDate
Dim strTime
Dim strDateTime
Dim strCommand
Dim x

Dim DOpusRTPath
DOpusRTPath = "C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe"

Dim Shell
Set Shell = CreateObject("WScript.Shell")

arrFileName = Array()

for each strFileName in ClickData.func.sourcetab.selected_files
	arrFileName = split(strFileName, "  -  ")

	if ubound(arrFileName) = 1 then
			strDate = replace(right(arrFileName(0),10),"-",":")
			strTime = replace(left(arrFileName(1),8),".",":")
	end if
	
    if len(strTime) < 8 then WScript.Quit 
	strDateTime =  strDate & " " & strTime

	strCommand = "C:\Windows\exiftool.exe -createdate=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

    strCommand = "C:\Windows\exiftool.exe -datetimeoriginal=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

	strCommand = """" & DOpusRTPath & """ /cmd SetAttr FILE=""" & strFileName & """ CREATED=""" & replace(strDate,":","-") & " " & strTime & """ MODIFIED=""" & replace(strDate,":","-") & " " & strTime & """"
	Shell.Run strCommand,0,true

	strCommand = "cmd /c del """ & strFileName & "_original"""
	Shell.Run strCommand,0,True

next

End Function

...and here my first try to implement the progress property (doesn't work)

Option Explicit
Function OnClick(ByRef ClickData)

Dim strFileName
Dim arrFileName
Dim strDate
Dim strTime
Dim strDateTime
Dim strCommand
Dim x

dim DOpusRTPath
DOpusRTPath = "C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe"

Dim Shell
Set Shell = CreateObject("WScript.Shell")

Dim Files
Files = ClickData.func.sourcetab.selected_files

Dim Progress
Progress = ClickData.func.command.progress
Progress.pause = false 'Allow pause button or not.
Progress.abort = false 'Allow abort button or not.
Progress.Init = clickData.func.sourcetab
Progress.AddFiles = Files.count
Progress.Show

arrFileName = Array()

for each strFileName in Files 'ClickData.func.sourcetab.selected_files
	arrFileName = split(strFileName, "  -  ")

	if ubound(arrFileName) = 1 then
			strDate = replace(right(arrFileName(0),10),"-",":")
			strTime = replace(left(arrFileName(1),8),".",":")
	end if
	
    if len(strTime) < 8 then WScript.Quit 
	strDateTime =  strDate & " " & strTime

	strCommand = "C:\Windows\exiftool.exe -createdate=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

    strCommand = "C:\Windows\exiftool.exe -datetimeoriginal=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

	strCommand = """" & DOpusRTPath & """ /cmd SetAttr FILE=""" & strFileName & """ CREATED=""" & replace(strDate,":","-") & " " & strTime & """ MODIFIED=""" & replace(strDate,":","-") & " " & strTime & """"
	Shell.Run strCommand,0,true

	strCommand = "cmd /c del """ & strFileName & "_original"""
	Shell.Run strCommand,0,True

	Progress.StepFiles = 1
next

End Function

Is there somebody who can help me?

regards,
Berndi

There are a couple of examples here:

The second thread is probably closest to what you are doing.

Many thanks.
Here is my final code:

Option Explicit
Function OnClick(ByRef ClickData)

Dim strFileName
Dim arrFileName
Dim strDate
Dim strTime
Dim strDateTime
Dim strCommand
Dim x

dim DOpusRTPath
DOpusRTPath = "C:\Program Files\GPSoftware\Directory Opus\dopusrt.exe"

Dim Shell
Set Shell = CreateObject("WScript.Shell")

Dim Progress 
Set Progress = ClickData.func.command.progress
Progress.Init ClickData.func.sourcetab.lister, "Zeitstempel aus Dateiname zu EXIF-Meta"

With Progress
	.pause = false 
	.abort = true
	.skip = true 
	.owned = true
	.bytes = false
	.full = false
	.AddFiles ClickData.func.sourcetab.selected_files.count
End With

Progress.Show
Progress.SetStatus "Übertrage Zeitstempel..."

arrFileName = Array()

for each strFileName in ClickData.func.sourcetab.selected_files

	if Progress.GetAbortState = "a" then
		Progress.Hide
		WScript.Quit
	end if

	if Progress.GetAbortState = "s" then continue

	arrFileName = split(strFileName, "  -  ")

	if ubound(arrFileName) = 1 then
			strDate = replace(right(arrFileName(0),10),"-",":")
			strTime = replace(left(arrFileName(1),8),".",":")
	end if
	
    if len(strTime) < 8 then WScript.Quit 
	strDateTime =  strDate & " " & strTime

	Progress.SetName CStr(strFileName)
	Progress.Stepfiles 1

	strCommand = "C:\Windows\exiftool.exe -createdate=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

    strCommand = "C:\Windows\exiftool.exe -datetimeoriginal=""" & strDateTime & """ """ & strFileName & """" 
	Shell.Run strCommand,0,True

	strCommand = """" & DOpusRTPath & """ /cmd SetAttr FILE=""" & strFileName & """ CREATED=""" & replace(strDate,":","-") & " " & strTime & """ MODIFIED=""" & replace(strDate,":","-") & " " & strTime & """"
	Shell.Run strCommand,0,true

	strCommand = "cmd /c del """ & strFileName & "_original"""
	Shell.Run strCommand,0,True

next

Progress.Hide

End Function

The only problem I have is, that the SKIP- and ABORT-button won't appear.
any suggestions?

The properties to control which buttons are enabled (Progress.skip = true etc.) need to be set before Progress.Init is called:

	Dim Progress 
	Set Progress = ClickData.func.command.progress

	Progress.skip = True
	With Progress
		.pause = true 
		.abort = true
		.skip = true 
		.owned = true
		.bytes = false
		.full = true
	End With
	
	Progress.Init ClickData.func.sourcetab.lister, "Zeitstempel aus Dateiname zu EXIF-Meta"
	Progress.AddFiles ClickData.func.sourcetab.selected_files.count

(We'll make this more explicit in the docs as it's easy to overlook.)


Another thing to note: You can't use WScript.Quit in Opus scripts, since they're running inside Opus rather than WScript. Instead, you can use Exit Function in the same places.

Using the Opus Command objects to run the commands instead of Shell.Run is usually also preferable, and will save you having to run Opus commands via DOpusRT.exe. (You can use it for the non-Opus commands as well.) Similarly, using the Opus Delete command instead of cmd /c del.


PS: Found a more complete example script that uses the Progress object, in case it's useful to anyone:


PPS: The skip option may not make sense with your script unless any of the individual commands take a long time. If you do support the skip option, you'd want to check if the user wants to skip between each individual command, else there isn't much point to it. (Checking it at the top of the loop is not really useful as you'd be skipping the next file, not the one the user clicked skip on. Checking Abort there makes sense, but not Skip.)

Thank you!

I tried the EXIT function allready, but it ends with error.
The WScript.Quit works quit good.

How do I use the Opus Delete command inside the VBScript instead of cmd /c del ?

Are you sure? When running the script from an Opus button?

You've probably just never hit the lines which run WScript.Quit, so the problem hasn't been triggered yet.

It definitely won't work in an Opus script:

Exit Function works fine in VBScript (or return in JScript):

ClickData.func.command gives you a Command object. Almost every script on the forum uses this to run commands, if you need full examples. The most important methods to look at are:

  • RunCommand (run a single-line command)
  • AddLine + Run (add multiple lines then run them all at once)
  • ClearFiles / AddFile (specify which files the command sees as "selected")

The object you're given via ClickData will have the source folder tab's selected files added to it already.

If you only want to delete one file, you can either specify its path to the Delete command explicitly (e.g. cmd.RunCommand "Delete FILE=""C:\xyz\abc.txt"" QUIET" in VBScript) or you can use ClearFiles and AddFile to make just that one file be selected in the cmd object, then run the command without specifying a file.

If I don't want commands to run on the initial selection, I usually call cmd.ClearFiles at the start, just in case, then specify the paths to each command using FILE and similar arguments. But it depends on what you're doing.

You could also keep a list of all the files you want to delete and delete them all in one go at the end, instead of doing them one at a time, if you wanted. (You'd want to remember to still do that clean-up if the Abort button was pushed.)

You need to have to create a Shell Object first, but I'll try.

I used only EXIT except of Exit Function

The object you get from CreateObject("WScript.Shell") isn't the same as the WScript object. They're two different things.

(Putting it in a variable called Shell would also not make WScript.Quit work. It might make Shell.Quit do something, but I don't think the WScript.Shell object has a Quit method like the WScript object does.)

As far as I know, there is no way for a script to create a new WScript object like you can create a new WScript.Shell object. The WScript object is only ever given to you by the WScript host process, which creates it for you before your script starts running.

(Similarly, there is no way for a script to create a new DOpus object like the one Opus provides for the script automatically before it starts running. Both the WScript and DOpus objects provide a way for scripts to interact with their host process, and are specific to that process.)

In VBScript I don't think Exit on its own does anything, as it needs to be told what you want to exit (e.g. Exit Function or Exit Loop I think is another one, although that's from memory).

Other languages have separate things like return and break for a similar purpose. VBScript is a bit unusual in that regard.

Have you considered using the -progress: tag for exiftool.exe? It will "Show file progress count".

Check here for details.

On top of that, from Progress dialog, abort, skip buttons greyed out:

It also looks like there was no way to get the Skip button enabled from a script (or if there was, it was very hard; it only happens if the speed timers in the progress dialog were enabled, and I'm not sure scripts can do that).

We'll be adding a new EnableSkip method to the progress object for this.