Problem with Button in "MS-Dos Batch" Mode

I made a Button inspired by this Post:

The Button uses a Dos command so I have to choose "MS-Dos Batch Function" to make it work.
The Button copies the target of selected shortcuts to the destination.

It's fully working but shows a strange and annoying behaviour.
The Button often doesn't do anything when clicking on it.
It only does the job on every 3rd or 5th click (the "Copy FILTER=NoShortcuts" -Part is always working).
It's not the first time I saw this behaviour when using Dos commands in a Button.

What's wrong with my Button (or my System? or DOpus?) and how can I get around this?

Here's the Buttoncode:

Copy Shortcut Target[code]@nodeselect
@runmode hide
Copy FILTER=NoShortcuts

@echo off
setlocal
for %%a in ({allfile}) do (
for /f "Tokens=1* Delims== " %%b in ('C:\Programme\DopusTools\Shortcut\shortcut.exe /F:"%%a" /a:q^|find "TargetPathExpanded"') do (
"C:\Programme\Directory Opus\dopusrt.exe" /cmd copy "%%c" TO={destpath}
)
)
endlocal
exit
[/code]

Does that DOS for-loop cope if the paths in {allfile} contain quotes?

I think your best best is to break the command down into something simpler, which just echos what it's trying to run, so that you can see what it outputs and note when that goes wrong.

FWIW, and just from my personal experience, I'd also recommend not using DOS batch scripts at all for anything like this. Every time I have tried to make DOS batch scripts do anything complex I've ended up spending several hours getting the arcane (to put it politely) DOS batch syntax to work properly with all the edge cases (like spaces, quotes or percent character in names), usually giving up in the end and re-writing it in VBScript. (Not that VBScript is great or the only option; it just a lot more predictable than DOS batch.)

@leo:

Thanks for your fast reply.

I looked the output of the command until I was sure it's fully working.
Now I realized that it doesn't work if the targets filenames contains spaces.
But the 20% response behaviour of the Button is always there even if there are no spaces.
Whenever the Button responds it's working without any error.

I would really prefer a VBScript but I don't know how to get the output of "shortcut.exe" (stripping the TargetPathExpanded=) as a list of paths which can be passed to DOpus to copy the files.
In the post I mentioned I suggested a VBScript that is doing half of the job. I couldn't make it fully working so I came to this Dos Version.

There's no need to use shortcut.exe because VBScript can extract the shortcut properties by itself:

tek-tips.com/viewthread.cfm?qid=850335

msdn.microsoft.com/en-us/library ... 85%29.aspx

Note that the API is called CreateShortcut but it "creates a new shortcut or opens an existing shortcut".

@leo:

I know about this and the Script I mentioned is using it but it's only working on Shortcuts to files.
Selecting Shortcuts to folders doesn't work.

How can I modify the Script to work with Folder-Shortcuts?

How to integrate the Script into the Buttoncode?
For now it needs to call "CreateShortcutTarget.vbs" which uses "dopusrt.exe" to do the Copy-job.
Integrating it in the Button means passing the Output of the Script to DOpus to do the copy.
How can I do that?

Here's the Script:

CopyShortcutTarget.vbs
[code]Option Explicit

Dim ARG()
Dim ARGS()
Dim i
Dim f
Dim FileName
Dim FilePath
Dim fExt
Dim ifExt
Dim oSHLink
Dim target
Dim WShell
Set WShell = Wscript.CreateObject("Wscript.Shell")

Dim fs
Set fs = CreateObject("Scripting.FileSystemObject")

For i = 0 to Wscript.Arguments.Count - 1
'Enumerate the collection and provide details of each item
Redim Preserve ARG(i)
ARG(i) = Wscript.Arguments(i)

 'Obviously there are various ways to handle looking at the filesystem object properties...
 Set f = fs.GetFile(ARG(i))
 FileName=f.Name
 FilePath=f.Path

 'Transform List-Item Links into their actual targets
 fExt = Fs.GetExtensionName(ARG(i))

 ifExt = StrComp(fExt, "LNK", vbTextCompare)
 IF ifExt = 0 THEN
   set oSHLink = Wshell.CreateShortcut(FilePath)
   target = oSHLink.TargetPath
   Set f = fs.GetFile(target)

 End If

 'Recreate a new collection containing all hard targets (no links)
 Redim Preserve ARGS(i)
 ARGS(i) = f

Next

' Now send this off to "dopusrt.exe"
WShell.Run """C:\Programme\Directory Opus\dopusrt.exe"" /cmd Copy """ & Join(ARGS,""" """)
'Next

Set oSHLink = Nothing
Set fs = Nothing
Set WShell = Nothing
Wscript.Quit[/code]

You're calling GetFile(target) on Microsoft's FileSystemObject. GetFile returns a File object so I expect that won't work when the path (target) is a folder. You'd need to use GetFolder instead (or don't call either of those things and just build a list of path strings instead of a list of File/Folder objects).

msdn.microsoft.com/en-us/library ... 85%29.aspx

[quote]How to integrate the Script into the Buttoncode?
For now it needs to call "CreateShortcutTarget.vbs" which uses "dopusrt.exe" to do the Copy-job.
Integrating it in the Button means passing the Output of the Script to DOpus to do the copy.
How can I do that?[/quote]

You're already calling Opus via dopusrt.exe and you'll still have to do that even if the script is integrated into a button since there is (currently) no other way for VBScript to all Opus commands. (Opus commands can call VBScript but not currently the other way around, except via dopusrt.exe).

All integrating the script into a button will do (at least in current versions of Opus) is remove the need to store the script in a separate file. (See here.)

@leo:

Thanks for your hints.
I now got it working although I couldn't get it working with the whole Script in the Button.
Simply adding the Standard Lines used to abuse Rename Scripts (Rename TO="*" and the Script-Function stuff) doesn't work.
It's good enough for me with the .vbs-file.

Here's the working Script:

CopyShortcutTarget.vbs[code] Option Explicit

   Dim ARG()
   Dim ARGS()
   Dim i
   Dim f
   Dim FileName   
   Dim FilePath
   Dim FolderName
   Dim FolderPath
   Dim fExt
   Dim fExtb
   Dim ifExt
   Dim oSHLink
   Dim target   
   Dim WShell
   Set WShell = Wscript.CreateObject("Wscript.Shell")

   Dim fs
   Set fs = CreateObject("Scripting.FileSystemObject")
   
   For i = 0 to Wscript.Arguments.Count - 1
   'Enumerate the collection and provide details of each item
   Redim Preserve ARG(i)
     ARG(i) = Wscript.Arguments(i)
	
   'Obviously there are various ways to handle looking at the filesystem object properties...
   fExt = Fs.GetExtensionName(ARG(i)) 
   IF fExt = "" THEN
     Set f = fs.GetFolder(ARG(i))
     FolderName=f.Name
     FolderPath=f.Path
   ELSE 
     Set f = fs.GetFile(ARG(i))
     FileName=f.Name
     FilePath=f.Path
   End IF
	 
   'Transform List-Item Links into their actual targets
   fExt = Fs.GetExtensionName(ARG(i)) 
   ifExt = StrComp(fExt, "LNK", vbTextCompare)
   IF ifExt = 0 THEN
     set oSHLink = Wshell.CreateShortcut(FilePath)
     target = oSHLink.TargetPath
   fExtb = Fs.GetExtensionName(oSHLink.TargetPath)
       IF fExtb = "" THEN
         Set f = fs.GetFolder(oSHLink.TargetPath) 
       ELSE
	     Set f = fs.GetFile(oSHLink.TargetPath)
       End IF
   End IF
   'Recreate a new collection containing all hard targets (no links)
   Redim Preserve ARGS(i)
   ARGS(i) = f
     
   Next

   ' Now send this off to "dopusrt.exe"
   WShell.Run """C:\Programme\Directory Opus\dopusrt.exe"" /cmd Copy TO={destpath} """ & Join(ARGS,""" """)
   'Next

   Set oSHLink = Nothing
   Set fs = Nothing
   Set WShell = Nothing
   Wscript.Quit

[/code]

To call the file from a Button use this:@nodeselect Yourpath\CopyShortcutTarget.vbs {filepath}

I got a new problem with the Script.

Using it with a selection that contains a Folder (not "Shortcut to Folder") it crashes DOpus.
So I had to rework it a little bit.
Now it seems to work without errors.

CopyShortcutTarget.vbs[code] Option Explicit

   Dim ARG()
   Dim ARGS()
   Dim i
   Dim f
   Dim g 
   Dim FileName   
   Dim FilePath
   Dim FolderName
   Dim FolderPath
   Dim fExt
   Dim fExtb
   Dim ifExt
   Dim oSHLink
   Dim target   
   Dim WShell
   Set WShell = Wscript.CreateObject("Wscript.Shell")

   Dim fs
   Set fs = CreateObject("Scripting.FileSystemObject")
   
   For i = 0 to Wscript.Arguments.Count - 1
   'Enumerate the collection and provide details of each item
   Redim Preserve ARG(i)
     ARG(i) = Wscript.Arguments(i)
	
   'Obviously there are various ways to handle looking at the filesystem object properties...
   fExt = Fs.GetExtensionName(ARG(i)) 
   IF fExt = "" THEN
     Set g = fs.GetFolder(ARG(i))
     FolderName=g.Name
     FolderPath=g.Path
   ELSE 
     Set f = fs.GetFile(ARG(i))
     FileName=f.Name
     FilePath=f.Path
   End IF
	 
   'Transform List-Item Links into their actual targets

   ifExt = StrComp(fExt, "LNK", vbTextCompare)
   IF ifExt = 0 THEN
     set oSHLink = Wshell.CreateShortcut(FilePath)
     target = oSHLink.TargetPath
   fExtb = Fs.GetExtensionName(oSHLink.TargetPath)
       IF fExtb = "" THEN
         Set f = fs.GetFolder(oSHLink.TargetPath) 
       ELSE
	     Set f = fs.GetFile(oSHLink.TargetPath)
       End IF
   End IF
   'Recreate a new collection containing all hard targets (no links)
   Redim Preserve ARGS(i)
   ARGS(i) = f & g
     
   Next

   ' Now send this off to "dopusrt.exe"
   WShell.Run """C:\Programme\Directory Opus\dopusrt.exe"" /cmd Copy TO={destpath} """ & Join(ARGS,""" """)
   'Next

   Set oSHLink = Nothing
   Set fs = Nothing
   Set WShell = Nothing
   Wscript.Quit

[/code]

Back to the Topic of this Thread:

I found a way to get the Dos-command from my first Post working without that "20% response behaviour".
Just writing the whole command in a single line and switching the Button to Standard Mode did it.
The Button is now also working if there is a space in the name of the Shortcut or its Target.
So both versions are fully working now.

Here's the working Code:

Copy Shortcut Target using shortcut.exe[code]@runmode hide
@nodeselect
Copy FILTER=NoShortcuts

cmd /k FOR %%a in ({allfile}) do for /f "Tokens=1* Delims==" %%b in ('C:\Programme\DopusTools\Shortcut\shortcut.exe /F:%%a /a:q^|find "TargetPathExpanded"') do "C:\Programme\Directory Opus\dopusrt.exe" /cmd copy "%%c" TO={destpath}
[/code]

To use it you'll have to create a Filter which excludes ".LNK"-Files with the Name "NoShortcuts" and to download "shortcut.exe" from here:
http://www.optimumx.com/download/#Shortcut

Can you give more detail on that? Is it an actual crash or just an error message?

If it is an actual crash, please collect and send the crash dump data to GPSoftware so they can pin it down.

I was only able to reproduce an error message, which I think is due to the script using the VBScript Join function in the wrong way. Running the script from a DOS prompt, and changing the WShell.Run into WScript.Echo, shows some invalid paths and incorrect quoting being generated:


The script also assumes that directories never have extensions and files always have them, both of which aren't always true.

I guess it doesn't really matter if the DOS version is working now, but if there was an actual crash (not just an error message) then it'd still be good to get the details to GPSoft so whatever is behind it can be fixed. (Even if the input is bogus, it shouldn't crash anything.)

The message was:

"Directory Opus detected a Program error. The error (0xC0000005) occured in the Thread 'dopus_function' at adress 0x7c80980F..."

My knowledge of VBScript is sill poor. I only puzzle things together until it's working for me.
So it can surely be done much better.

Can you find out which dopusrt.exe command-line was being run to trigger that crash?

(e.g. By changing the WShell.Run to WScript.Echo and then running the script on the same items you ran it on when it crashed.)

My testitems are some Shortcuts to files, a shortcut to a folder, a file and a folder.

The error occured only when the folder was selected together with others. Selecting only the folder worked.

The error is gone since I added "Dim g " and changed the lines "FolderName=f.Name" and "FolderPath=f.Path" to "FolderName=g.Name" and "FolderPath=g.Path"

Running the script from a dosprompt on a folder (folder), a File (file), a shortcut to a file (fileshort) and a shortcut to a folder (foldershort) gives this strange Output:

"C:Programme\dopurt.exe /cmd Copy TO={destpath} "D:\folder" "E:\foldershortD:\folder" "D:\file.txtD:\folder" "E:\fileshortD:\folder"

Running it from a Button outputs correct Paths of the files/folders to be copied.

Strange thing!

I got back to the version that produced the crash (not always) and tested it.
It gives correct Output when running from a dosprompt.

Now I can't reproduce the error any longer.
I tested it several times without getting an error.

Must have been something completely different that causes the crash.
Perhaps it's now working because I cleaned my Tempfolder before the last Test?