WScript.Shell.run launching robocopy doesn't show destination parameters - vbscript

i'm trying to get a vbscript (cscript/vbs) to copy files from one network location (my tv show downloads folder) to another network location (my pvr).
i tried to use xcopy but ended up with "parse error" without any context. tried a few things like ensuring files that have spaces are quoted, etc. couldn't work it out.
i tried using scripting.filesystemobject's copyfile method, but this failed with a "bad file name or number" error and googling this one led to many, many dead ends.
i am currently trying to get robocopy to handle the copy since it's generally better than both of the above. but when run from within cscript using WScript.Shell's Run method, the destination, filename and parameters all "fall off".
So here's a snip of the copy part.
if dirmatch > "" then
fileFrom = quote(myloc) ' & fil.name) 'fil.name will not need to be quoted
fileTo = quote(dirmatch) ' puts double-quotes around things if they have spaces in the name
' copyCommand = "%comspec% /k xcopy " & fileFrom & " " & fileTo & " /C /D /Y" ' returns "parse error"
copyCommand = "%comspec% /k robocopy " & fileFrom & " " & fileTo & " " & fil.name & " /R:3 /W:10"' /MOV"
logmsg copyCommand
oShellApp.run copyCommand
else
logmsg "no matching directory found for: " & fil.name
end if
The fileFrom and fileTo are directories that I have previously calculated using filename parsing - just in the format of \\server\path\more path might have spaces\etc\etc. fil.name is the file and it never has spaces - is dot seperated. The spaces in folder names is a requirement for matching reasons in another app I use.
So a given file copy command should look like this:
00:19: %comspec% /k robocopy \\qnap\qdownload\transmission\completed \\pvr\e\tv\MythBusters Mythbusters.S11E03.Hail.Hijinx.HDTV.x264-FQM.mp4 /R:3 /W:10
but robocopy in the new command window (e.g. cmd.exe /k) throws up like this:
-------------------------------------------------------------------------------
ROBOCOPY :: Robust File Copy for Windows
-------------------------------------------------------------------------------
Started : Tue Oct 23 21:04:58 2012
Source : \\qnap\qdownload\transmission\completed\
Dest -
Files : *.*
Options : *.* /COPY:DAT /R:1000000 /W:30
------------------------------------------------------------------------------
ERROR : No Destination Directory Specified.
i launched it right, but it can't see past the first parameter. Performing the same command using copy might have been running into the same problem.
How can I get ALL the robocopy parameters to get handed across to the new cmd instance?
p.s. my whole script is here: http://pastebin.com/xgpGJYmU : feel free to optimise it!

Ok, so after stumbling about with this for ages I finally worked out that a character at the start of the destination had an ascii code less than zero. both filesystemobject and asp is funny like that and lets you have stupid scenarios like this. asp unicode implementation: you bastard!
it was there staring me in the face from the very beginning:
00:19: %comspec% /k robocopy \\qnap\qdownload\transmission\completed
\\pvr\e\tv\MythBusters Mythbusters.S11E03.Hail.Hijinx.HDTV.x264-FQM.mp4 /R:3 /W:10
a line break before \pvr\e .. etc I treated it as if it were a wrapping problem in the command prompt, but no a bit of "character by character" exploration of the strings revealed the problem.
In the end I was unable to cut a regex that could convert my wide bytes back to ascii, so had to do a letter-by-letter approach:
Function unicodeToAscii(sText)
Dim x, aAscii, ascval, l
l = len(sText)
If l = 0 Then Exit Function
redim aAscii(l)
For x = 1 To l
ascval = AscW(Mid(sText, x, 1))
If (ascval < 0) Then
ascval = 65536 + ascval ' http://support.microsoft.com/kb/272138
End If
aAscii(x) = chr(ascval)
Next
unicodeToAscii = join(aAscii,"")
End Function
which is a totally sucky hack.
anyay, problem not with robocopy or wsh, but with unicode file systems! solved.
p.s. here's the updated, optimised pastebin of the entire script: http://pastebin.com/s1XtzCGC

Related

A Vbscript question re filesystem detection output to Variable? (OS XPHome NTFS)

I am hoping that someone with Vbscripting experience will be able to help me with a Vbscript (My OS is XP Home with NTFS filesystem please I cannot use WMI within the Vbs code due to OS)
I have looked on the w.w.w & found two snippets of VBscript that will (1) find the current filesystem on C:\ (%systemdrive%) drive & the second snippet of code will identify the OS fileSystem however I am really wanting to combine the two parts of the code & (2) the output would preferably be a variable not a msgbox to be acquired later in a batch file. The code snippets are as follows.
set shell = createobject("wscript.shell")
set environ = shell.environment("process")
systemdrive = environ("systemdrive")
msgbox systemdrive
set fso = CreateObject("Scripting.FileSystemObject")
set drive = fso.GetDrive("C")
Wscript.Echo "FileSystem =", drive.FileSystem
The first set of code creates a variable called systemdrive & outputs to a message box. The second (within a message box) outputs the "Filesystem" in my case "NTFS".
My question is when I interchange the systemdrive info into the line
set drive = fso.GetDrive("C") - like so set drive = fso.GetDrive("systemdrive") instead of ("C")
I get error code messages. Also instead of a message box output I am looking for a %variable% output instead e.g. "FAT32, NTFS or whatever". I hope what I am trying to convey makes sense? In essence I am trying to use the systemdrive variable usually "C:" instead of the hard coded c: path find the OS filesystem & output that only to a variable?
From what I understand you want to detect the filesystem of a drive and store it in an environment variable for later use in a batch file.
This would mean you are planning to call the VBScript from within that batch file and can use the batch file to resolve any environment variables such as %SYSTEMDRIVE%, and there is no need to do that from within the VBS file (which would be possible, but it's going to be more flexible when we can pass in the drive letter as a parameter to the script).
Let's make a VBS that accepts one argument and looks up the filesystem type, if it can.
Option Explicit
Dim shell, fso, drive, driveletter
' we expect a single argument - a drive letter in the form X:
If WScript.Arguments.Unnamed.Count = 0 Then Die "Please specify drive letter."
driveletter = WScript.Arguments.Unnamed(0)
Set shell = CreateObject("WScript.Shell")
Set fso = CreateObject("Scripting.FileSystemObject")
' try to get the drive object for that drive letter, die on error
On Error Resume Next
Set drive = fso.GetDrive(driveletter)
If Err.Number <> 0 Then Die "Could not detect filesystem type for " + driveletter + " (" + Err.Description + ")"
Wscript.StdOut.Write drive.FileSystem
Sub Die(message)
WScript.StdErr.WriteLine message
WScript.Quit 1
End Sub
Now this can be called stand-alone (for command line purposes, use the command line script interpreter, cscript.exe):
cscript /nologo filesystem.vbs %SYSTEMDRIVE%
Or it can be called from a Batch file (we'll use a for loop to assign the script's output to a variable):
#echo off
for /f "usebackq delims=" %%s in (`cscript /nologo filesystem.vbs %SYSTEMDRIVE%`) do (
set FILESYSTEM=%%s
)
echo The filesystem in %SYSTEMDRIVE% is %FILESYSTEM%.
The above prints this for me:
The filesystem in C: is NTFS.

Printing PDF files using VBS

I am new to coding with VBS. This is my unfinished code to print documents in a folder containing documents with 3 distinct headers, "DN" "INV" and "PO". I've been searching around for the code/method to print out PDF documents. I tried using the invokeverb "&print" function but it doesn't seem to work. Can someone please teach me how to print it out? Thank you very much :)
"DN" needs to printed out once, " INV" needs to be printed out 6 times, "PO" needs to be printed out 2 times.
P.S. Thank you #kajkrow for solving this same problem using VBA. Reposting as I found out I was using VBS. Previous question can be found here. *EDIT : attached link solves my problem in both VBA and VBS and uses InvokeVerbEx to print files.
'' To set the path to the current folder
set shApp = CreateObject("shell.application")
currentPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
set shFolder = shApp.NameSpace( currentPath )
'' To set the items in the current folder as "files"
set files = shFolder.Items()
''Start of code''
'msgbox("Starting Script")
for each files in files
' If name contains "DN" '
if inStr(files, "DN") then
'print out 1 time'
end if
' if name contains "INV" '
if inStr(files, "INV") then
'print out 6 times'
end if
' if name contains "PO" '
if inStr(files, "PO") then
'print out 2 times'
end if
next
MsgBox("completed")
According to documentation (https://www.adobe.com/content/dam/acom/en/devnet/acrobat/pdfs/Acrobat_SDK_developer_faq.pdf) you could send a command to print a file, but there is no parameter for the number of copies.
You can display and print a PDF file with Acrobat and Adobe Reader
from the command line. These commands are unsupported, but have worked
for some developers. There is no documentation for these commands
other than what is listed below.
Note: All examples below use Adobe
Reader, but apply to Acrobat as well. If you are using Acrobat,
substitute Acrobat.exe in place of AcroRd32.exe on the command line.
AcroRd32.exe pathname — Start Adobe Reader and display the file. The
full path must be provided. This command can accept the following
options.
/n Start a separate instance of Acrobat or Adobe Reader, even if one is currently open.
/s Suppress the splash screen.
/o Suppress the open file dialog box.
/h Start Acrobat or Adobe Reader in a minimized window.
AcroRd32.exe /p pathname — Start Adobe Reader and display the Print dialog box.
AcroRd32.exe /t path "printername" "drivername" "portname" — Start Adobe Reader
and print a file while suppressing the Print dialog box. The path must be fully specified.
The four parameters of the /t option evaluate to path, printername, drivername, and portname (all
strings).
printername — The name of your printer.
drivername — Your printer driver’s name, as it appears in your printer’s properties.
portname — The printer’s port. portname cannot contain any "/" characters; if it does, output is
routed to the default port for that printer
For multiple copies of each pdf, you could use a loop.
Something like this:
set shApp = CreateObject("shell.application")
currentPath = CreateObject("Scripting.FileSystemObject").GetAbsolutePathName(".")
set shFolder = shApp.NameSpace( currentPath )
set files = shFolder.Items()
set oWsh = CreateObject ("Wscript.Shell")
dn = 1
inv = 6
po = 2
for each files in files
msgbox(files)
if inStr(files, "DN") then
for x = 1 to dn
oWsh.run """AcroRd32.exe"" /t /n /h /o /s" &files,,true
next
end if
if inStr(files, "INV") then
for x = 1 to inv
oWsh.run """AcroRd32.exe"" /t /n /h /o /s" &files,,true
next
end if
if inStr(files, "PO") then
for x = 1 to po
oWsh.run """AcroRd32.exe"" /t /n /h /o /s" &files,,true
next
end if
next
MsgBox("completed")
Note: tested only with XPS Document writer

How to copy o/p from cmd.exe and append it to a document only if it does not equal a particular value? in .VBS

I am really new to .vbs and am not sure how to build this out.
I am running a short script that runs a command in cmd.exe and copies/appends the output to a log file.
I would like to only append the o/p to the log file if the value does not match string"". How do I set this up? any help is much appreciated. I apologise if this question is off topic.
Dim oShell
Set oShell = WScript.CreateObject ("WScript.Shell")
oShell.run "cmd.exe /C cd " & str & ">> log.txt"
Set oShell = Nothing
The pseudo code for the if/else logic is shown below
if (o/p string = "A")
action: do not do anything and end script
else
copy string and append to file log.txt
Thank You
Have you tried looking into the command find?
It allows you to do that without using VBScript
dir | find "string_to_find" >> logfile.txt : copy only the text that matches
dir | find /I "string_to_avoid" >>logfile.txt : same as above but case insensitive
dir | find /v "string_to_avoid" >> logfile.txt : copy all strings that do not match
For more help on find type find /? in a command line.

vbs cmd path space

I would like to be able to call the following cmd command from within a vbs script:
cmd Client\setupclient.exe /q /targetdir "c:\program files\Microsoft CRM"
I came up with the following vbs script:
Set oShell = WScript.CreateObject ("WScript.Shell")
oShell.Run "cmd /c Client\setupclient.exe /q /targetdir c:\program files\Microsoft CRM", 1, true
As far as I am concerned, this would work properly if the targetdir had no spaces, e.g c:\bla. Then the app would be installed in that particular folder.
The obvious question is, how can I define the targetdir with spaces as the path location.
I tried to surround it with ' ' but that didn't work for me. Any suggestions?
Cheers
chris
Paths with spaces are typically enclosed in quote characters ("). In VBScript, to insert a quote character into a string you use double quotes (""). So, your code should look like this:
oShell.Run "cmd /c Client\setupclient.exe /q /targetdir ""c:\program files\Microsoft CRM""", 1, true
Also, I'm not sure if cmd /c is actually needed here, so it might work this way as well:
oShell.Run "Client\setupclient.exe /q /targetdir ""c:\program files\Microsoft CRM""", 1, true
I ended up with
AMPath = "E:\Program Files (x86)\Dropbox\Client\Dropbox.exe"
If FileSyst.Fileexists(AMPath) Then
AMPath = chr(34) & AMPath & chr(34)
OBJ_Shell.run (AMPath)
End If
1、If your OS supports 8.3 filename,you can try short filename:
cd c:\
dir /x
2017/04/17 20:53 <DIR> PROGRA~1 Program Files
2017/04/18 03:40 <DIR> PROGRA~2 Program Files (x86)
Then repalce C:\Program Files\ with PROGRA~1.
2、use two double-quotes within full path.
WScript.CreateObject("WScript.Shell").Run """C:\Program Files\DirName\FileName.exe"" /option1 value1 /option2 vaule2 argv3"
This is not exactly the problem described, in that the called program rather than a parameter contains a space. Googling "whshell.run does not work if filename contains blanks" got me here.
When the called program contains a space in its name, it needs to be triple quoted. (The starting and ending quotes define a string with blanks and the enclosed double quotes are mapped to single quotes within that string.) There are two working examples. The first uses triple quotes. The second effectively removes the blanks from the name. The non-working examples show what not to do (and what I tried first.)
' Drive D:\Program Files\Batch\Monitor.bat with no associated command window
Set WshShell = CreateObject("WScript.Shell")
' These methods work: (Select one)
Return = WshShell.Run("""D:\Program Files\Batch\Monitor.bat""", 0)
' Return = WshShell.Run("D:\.D-DISK\Monitor.bat", 0)
' Note: Here "D:\.D-DISK\Monitor.bat" is a symbolic link to
' "D:\Program Files\Batch\Monitor.bat"
' The following methods fail because of the space in the filename.
' WshShell.Run( chr(34) & D:\Program Files\Batch\Monitor.bat & Chr(34), 0 )
' Return = WshShell.Run("D:\Program Files\Batch\Monitor.bat", 0)
' Return = WshShell.Run(""D:\Program Files\Batch\Monitor.bat"", 0)
Set WshShell = Nothing

How can I run a program from a batch file without leaving the console open after the program starts?

For the moment my batch file look like this:
myprogram.exe param1
The program starts but the DOS Window remains open. How can I close it?
Use the start command to prevent the batch file from waiting for the program. Just remember to put a empty double quote in front of the program you want to run after "Start".
For example, if you want to run Visual Studio 2012 from a batch command:
Start "" "C:\Program Files (x86)\Microsoft Visual Studio 11.0\Common7\IDE\devenv.exe"
notice the double quote after start.
You can use the exit keyword. Here is an example from one of my batch files:
start myProgram.exe param1
exit
Look at the START command, you can do this:
START rest-of-your-program-name
For instance, this batch-file will wait until notepad exits:
#echo off
notepad c:\test.txt
However, this won't:
#echo off
start notepad c:\test.txt
From my own question:
start /b myProgram.exe params...
works if you start the program from an existing DOS session.
If not, call a vb script
wscript.exe invis.vbs myProgram.exe %*
The Windows Script Host Run() method takes:
intWindowStyle : 0 means "invisible windows"
bWaitOnReturn : false means your first script does not need to wait for your second script to finish
Here is invis.vbs:
set args = WScript.Arguments
num = args.Count
if num = 0 then
WScript.Echo "Usage: [CScript | WScript] invis.vbs aScript.bat <some script arguments>"
WScript.Quit 1
end if
sargs = ""
if num > 1 then
sargs = " "
for k = 1 to num - 1
anArg = args.Item(k)
sargs = sargs & anArg & " "
next
end if
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell.Run """" & WScript.Arguments(0) & """" & sargs, 0, False
This is the only thing that worked for me when I tried to run a java class from a batch file:
start "cmdWindowTitle" /B "javaw" -cp . testprojectpak.MainForm
You can customize the start command as you want for your project, by following the proper syntax:
Syntax
START "title" [/Dpath] [options] "command" [parameters]
Key:
title : Text for the CMD window title bar (required)
path : Starting directory
command : The command, batch file or executable program to run
parameters : The parameters passed to the command
Options:
/MIN : Minimized
/MAX : Maximized
/WAIT : Start application and wait for it to terminate
/LOW : Use IDLE priority class
/NORMAL : Use NORMAL priority class
/HIGH : Use HIGH priority class
/REALTIME : Use REALTIME priority class
/B : Start application without creating a new window. In this case
^C will be ignored - leaving ^Break as the only way to
interrupt the application
/I : Ignore any changes to the current environment.
Options for 16-bit WINDOWS programs only
/SEPARATE Start in separate memory space (more robust)
/SHARED Start in shared memory space (default)
You should try this. It starts the program with no window. It actually flashes up for a second but goes away fairly quickly.
start "name" /B myprogram.exe param1
How to solve "space problem" and local dependencies:
#echo off
cd "C:\Program Files\HeidiSQL"
start heidisql.exe
cd "C:\Program Files (x86)\Google\Chrome\Application"
start chrome.exe
exit
Loads of answers for this question already, however I am posting this to highlight something important:
Start "C:\Program Files\someprog.exe"
Ghe above might cause issues in some windows versions as Start actually expects the first set of quotation marks to be a windows title. So it is best practice to first double quote a comment, or a blank comment:
Start "" "C:\Program Files\someprog.exe"
or
Start "Window Title" "C:\Program Files\someprog.exe"
My solution to do this from the GUI:
Create a shortcut to the program you want to run;
Edit the shortcut's properties;
Change the TARGET field to %COMSPEC% /C "START "" "PROGRAMNAME"";
Change the RUN field to minimized.
Ready! See how you like it...
PS: Program parameters can be inserted in between the two final quotation marks; the PROGRAMNAME string can be either a filename, a relative or an absolute path -- if you put in an absolute path and erase the drive letter and semicolon, then this will work in a thumbdrive no matter what letter the host computer assigns to it... (also, if you place the shortcut in the same folder and precede the program filename in PROGRAMNAME with the %CD% variable, paths will always match; same trick can be used in START IN field).
If this batch file is something you want to run as scheduled or always; you can use windows schedule tool and it doesn't opens up in a window when it starts the batch file.
To open Task Scheduler:
Start -> Run/Search -> 'cmd'
Type taskschd.msc -> enter
From the right side, click Create Basic Task and follow the menus.
Hope this helps.
Here is my preferred solution. It is taken from an answer to a similar question.
Use a VBS Script to call the batch file:
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "C:\path\to\your\batchfile.bat" & Chr(34), 0
Set WshShell = Nothing
Copy the lines above to an editor and save the file with .VBS extension.

Resources