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

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.

Related

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

Creating a .zip backup using VBS, without hard-coded Wait timer (Windows 7) [duplicate]

This question already has an answer here:
Zipping a large folder fails
(1 answer)
Closed 5 years ago.
I'm having an issue populating a created .zip folder (used for backing up everything from C:\Source to a .zip located in C:\Destination). The issue arises in the ZipCMD.vbs file. I'll describe my whole process now, and at the end, in bold, I'll describe the issue, and my attempted (and failed) solutions.
There exists a folder containing test data, in C:\Source
In C:\Destination, create ZipCMD.vbs using the following code in Notepad (Credit to Gerhard Barnard)
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
objShell.NameSpace(ZipFile).CopyHere(source)
WScript.Sleep 3000
I've also created a Backups.bat in C:\Destination using the following code in Notepad
#echo off
for /f "delims=" %%a in ('wmic OS Get localdatetime ^| find "."') do set dt=%%a
set YYYY=%dt:~0,4%
set MM=%dt:~4,2%
set DD=%dt:~6,2%
set HH=%dt:~8,2%
set Min=%dt:~10,2%
set Sec=%dt:~12,2%
set stamp=%YYYY%%MM%%DD%%HH%%Min%
rem Parameters set for use later
ZipCMD.vbs "C:\Source" "C:\Destination\BackupTest1.zip"
rem This line copies all files and folders from the Source to the Destination into a named .zip, without a date, by utilising the VBS created earlier.
Del "C:\Destination\*_BackupTest1.zip"
rem This line deletes the old backup (All **final** backups are named using 'YYYYMMDDhhmm_BackupTest1.zip'). The '_' prevents this command deleting the newly-created zip from before.
Rename C:\Destination\BackupTest1.zip %Stamp%_BackupTest1.zip
rem Renames newly-created zip file with datestamp and underscore (for information, and so that it can be identified for deletion next time this is run).
Set File="*_BackupTest1.zip"
FOR /F "usebackq" %%A IN ('%file%') DO set size=%%~zA
rem These lines define a new parameter defined by the created .zip's size
Echo %stamp%%Sec% %stamp%_BackupTest1.zip %Size%>>BackupLog.log
rem This last line appends a line to a log file containing the time the zip was created, the name of the .zip created, and its' size.
The second section of the above .bat (after defining initial parameters) can be repeated for multiple folders, but changing 'Source' each time.
Lastly, I create a RunBackups.vbs in C:\Destination using the following code in Notepad
Set WshShell = CreateObject("WScript.Shell" )
WshShell.Run chr(34) & "C:\[SyncFolder]\Backups.bat" & Chr(34), 0
Set WshShell = Nothing
This runs the .bat without having the black CMD window appear (i.e. running in 'silent' mode), and is the file I call upon using Task Scheduler to automate the backup process.
Problem: The WScript.Sleep 3000 line in ZipCMD.vbs is a bodge. If the entire .zip file can be created in <3 seconds, great. Otherwise, we've got a non-functional backup. Extending this timer can prove problematic for larger or multiple backups.
Solution attempt #1: In ZipCMD.vbs, replacing the 3000 wait, start a loop that checks whether a .zip has been created with name=ZipFile. This creates a .zip with the correct name, but contains no data (i.e. The backup process has created a .zip, but vbs has closed before it had a chance to populate any data/files)
Solution attempt #2: In ZipCMD.vbs, replacing the 3000 wait, count the number of files in Source, and wait (loop) until the .zip contains that number of files, with a 500ms delay between each check. Problem: This works perfectly for all files except the last one to be copied. If the last file can be copied in <500ms, this works. Otherwise, the last file doesn't get copied. Extending this timer can prove problematic for backups containing very large files.
Question: What can I replace the 'Wait' timer with, to ensure that the .zip is created fully each time (without just setting a massive timer), without using any non-default-windows functionality? (i.e. non-third-party (e.g. 7zip))
I've heard that Java/Javascript (?) might get around this issue, but am unsure how/if this would work? (due to limited technical knowledge)
Try this modified ZipCMD.vbs
Set objArgs = WScript.Arguments
Set FS = CreateObject("Scripting.FileSystemObject")
InputFolder = FS.GetAbsolutePathName(objArgs(0))
ZipFile = FS.GetAbsolutePathName(objArgs(1))
CreateObject("Scripting.FileSystemObject").CreateTextFile(ZipFile, True).Write "PK" & Chr(5) & Chr(6) & String(18, vbNullChar)
Set objShell = CreateObject("Shell.Application")
Set source = objShell.NameSpace(InputFolder).Items
numfolderitems = objShell.NameSpace(InputFolder).Items.count
objShell.NameSpace(ZipFile).CopyHere(source)
' wait until number of items in zip file is the same as in the folder we are zipping up
' also sometimes gets errors when getting folder object for zip file, probably because it is in use? so ignore these
On Error Resume Next
Do while True
numitemsinzip = objShell.NameSpace(ZipFile).Items.count
If Err.Number = 0 and numitemsinzip = numfolderitems Then
Exit Do
ElseIf Err.Number <> 0 then
Err.Clear
End If
wScript.Sleep 10
Loop
On Error Goto 0
This is basically your solution #2 of waiting until the zip file has all the items in it except I had to make it ignore errors that it would get occasionally. I tested it a few times and it seems to work OK. The only potential issue would be if the zipping operation gets stopped for some reason then the wscript.exe process would just run forever because all the files would never be put in the zip file.

How can I update a text file using batch script which will be triggered by VB Script

The challenge here is, the batch script is triggered using Vb script and the text file is created using the same VBScript.
The text file name contains a variable in it. I am able to pass the variable from VBS to batch, but unable to append the same text file.
VBScript :
Dim wsh
Set wsh = Wscript.CreateObject("Wscript.Shell")
strinputa = "102590"
wsh.run "Test.bat " + chr(34) + strinputa + chr(34)
set wsh = nothing
Batch script :
Set Rid = %1
Xcopy "Location 1" "Location 2" /s /e /k /i >> %~dp0Logs\log_%Rid%.txt
pause
Keep in mind that there is already have a text file in "\Logs" folder with file name
'log_102590', which I want to update.

Reg not starting vbscript

I've got registry entries inside of a .reg file. The reg file is for making a URI Scheme. It worked when I was passing %1 argument to a .bat file, but I don't like viewing the .bat file, so I want to use the well known VBScript method of hiding the .bat file. How do I pass the arguments to the batch file?
Apps.reg
REGEDIT4
[HKEY_CLASSES_ROOT\Apps]
#="URL:Apps Protocol"
"URL Protocol"=""
[HKEY_CLASSES_ROOT\Apps\shell]
[HKEY_CLASSES_ROOT\Apps\shell\open]
[HKEY_CLASSES_ROOT\Apps\shell\open\command]
#="\"M:\\Apps\\Apps.vbs\" \"%1\""
Apps.vbs
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run chr(34) & "Apps.bat" & Chr(34), 0
Set WshShell = Nothing
The batch file just uses %1 argument. The problem is getting the argument to the batch file. Currently every time I try to use the URI Scheme with the VBScript, I get "apps://foo is not a valid Win32 application." Any help is appreciated!
This works:
WshShell.Run "Apps.bat /foo", 0
If you want to separate your program path which may include spaces from the command line you could try this:
WshShell.Run """Apps.bat"" /foo", 0

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

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

Resources