VBScript FTP Login with Username and Password - vbscript

I am trying to update a VBScript (very little experience with this, I do a lot of VB.NET), that reads an FTP directory and moves certain files to a new local directory on a daily basis. I have old code that works on an FTP site that uses anonymous logins, but I now need it to access an FTP site that requires username and password.
Here is my current code -
Sub MoveNSPurolatorFile()
Dim NSPurolatorFTPSite, NSPurolatorMoveFilePath, NSPurolatorFTPFolder, NSPurolatorFTPFileName
Dim folder, files
Dim fso
set fso = CreateObject("Scripting.FileSystemObject")
NSPurolatorFTPSite="\\xxx.xxx.x.xx\"
NSPurolatorMoveFilePath = "F:\TestDirectory"
NSPurolatorFTPFolder = "TestFolder"
NSPurolatorFTPFileName = "MAN0201.CSV"
If InStr(NSPurolatorFTPFileName, "_processed") = 0 and InStr(NSPurolatorFTPFileName, ".CSV") > 0 Then
If fso.FolderExists(NSPurolatorFTPSite & NSPurolatorFTPFolder) Then
If fso.FileExists(NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName) Then
objfile.writeline "NS Purolator File Found: " & NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName
fso.copyFile NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName, NSPurolatorMoveFilePath & "\"
Else
objfile.writeline "File does not exist: " & NSPurolatorFTPSite & NSPurolatorFTPFolder & NSPurolatorFTPFileName
End If
End If
End If
Next
End Sub
It says the folder does not exist, but I know it does and when I run this code against an ftp site that does not require username and password it works fine. I guess my question is - How do I pass in the username and password using VBScript to the ftp site before trying to access folders, etc?
Thanks.

This really is an incredibly bad way to do this. You can't just treat folders on a remote FTP site as local folders.
You really should be using InetCtrls.Inet.1
Here's an example I lifted from somewhere else that does not do what you want, but contains all the parts you need - you need to pick it apart to suit your needs.
'Option Explicit
'const progname="FTP upload script by Richard Finegold"
'const url = "ftp://ftp.myftpsite.com"
'const rdir = "mydir"
'const user = "anonymous"
'const pass = "myname#mymailsite.com"
'This is an example of ftp'ing without calling the external "FTP" command
'It uses InetCtrls.Inet.1 instead
'Included is a "hint" for simple downloading
'Sources:
'http://msdn.microsoft.com/library/partbook/ipwvb5/loggingontoftpserver.htm
'http://msdn.microsoft.com/library/partbook/egvb6/addinginternettransfercontrol.htm
'http://cwashington.netreach.net/ - search on "ftp" - inspiration only!
'Insist on arguments
dim objArgs
Set objArgs = Wscript.Arguments
If 0=objArgs.Count Then
MsgBox "No files selected for operation!", vbOkOnly + vbCritical, progname
WScript.Quit
End If
'Force console mode - csforce.vbs (with some reorganization for efficiency)
dim i
if right(ucase(wscript.FullName),11)="WSCRIPT.EXE" then
dim args, y
For i = 0 to objArgs.Count - 1
args = args + " " + objArgs(i)
Next
Set y = WScript.CreateObject("WScript.Shell")
y.Run "cscript.exe " & wscript.ScriptFullName + " " + args, 1
wscript.quit
end if
'Do actual work
dim fso, ftpo
set fso = WScript.CreateObject("Scripting.FileSystemObject")
set ftpo = WScript.CreateObject("InetCtls.Inet.1") 'Msinet.ocx
ftpo.URL = url
ftpo.UserName = user
ftpo.Password = pass
WScript.Echo "Connecting..."
ftpo.Execute , "CD " & rdir
do
' WScript.Echo "."
WScript.Sleep 100 'This can take a while loop while ftpo.StillExecuting
for i = 0 to objArgs.Count - 1
dim sLFile
sLFile = objArgs(i)
if (fso.FileExists(sLFile)) then
WScript.Echo "Uploading " & sLFile & " as " & FSO.GetFileName(sLFile) & " "
ftpo.Execute , "Put " & sLFile & " " & FSO.GetFileName(sLFile)
'ftpo.Execute , "Get " & sRemoteFile & " C:\" & sLFile
do
'WScript.Echo "."
WScript.Sleep 100 'This can take a while
loop while ftpo.StillExecuting
else
MsgBox Chr(34) & sLFile & Chr(34) & " does not exist!", _
vbOkOnly, progname
end if
next
WScript.Echo "Closing"
ftpo.Execute , "Close"
WScript.Echo "Done!"

Here's a pretty nice way to do it - I'm sure this could be improved upon, but I just got it going.. :-)
Dim fso, folder1, folder2, folder2a
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder2a = fso.GetFolder("C:\temp")
ftpFolderString = "ftp://username:password#ftp.ftpsite.com/folderpath"
targetFoldder = "C:\temp"
fileSearchStr = "searchstring"
Dim SH, txtFolderToOpen, thing
Set SH = CreateObject("Shell.Application")
'SH.Open txtFolderToOpen
Set folder1 = SH.NameSpace(ftpFolderString)
Set folder2 = SH.NameSpace(targetFoldder)
For Each item In folder1.items
If InStr(LCase(item.Name),fileSearchStr) > 0 Then
Debug.WriteLine item.Name
folder2.CopyHere item,4
WScript.Sleep(200)
For Each item2 In folder2a.Files
If item2.Name = item.Name Then
While item2.Size < item.Size
WScript.Sleep(200)
Wend
End If
Next
WScript.Sleep(200)
End If
Next
Set SH = Nothing
Debug.WriteLine "Done"

How is the script being run? Manually, automatically? By a service?
Mapped-letter drives are not always available when running as a service.
Experiment with the script to ensure that it even able to see the F:\ drive, and then see what else is visible.

Is the FTP site accessed by a UNC path (looks like it is)? If it is just a standard FTP address then you can incorporate the username / password in the URL e.g. ftp://user:pass#myftpsite.com. If it is a UNC path that you are trying to access using different credentials then the easiest way would probably be to map a drive, do the work and then unmap the drive. 2 different approaches can be found here

Related

VB SCRIPT The system can not find the file specified ON SOME COMPUTERS/USERS

Good day! I have this script that opens up an access application.
This script works on several users but one. This user is getting this error
"Error 80070002: The system can not find the file specified".
I'm quite sure there is nothing wrong with my script as only one person is encountering this issue.
Could there be a computer setting or update that is causing this problem?
Everything works except for the Open File part.
And this is for some computers/user only. Most of the Computer/users can execute this without any problem.
Thanks in advance!
Here's the script
'*******************************************************************************
'Find user name
'*******************************************************************************
Set WshNetwork = CreateObject("WScript.Network")
userName = WshNetwork.UserName
Set WshNetwork = Nothing
'*******************************************************************************
'Find version of master file
'*******************************************************************************
Set folder = objfso.GetFolder(folderPath)
For Each file In folder.Files
If InStr(file.Name, "AMSDshbd_M") = 1 Then
masterVersion = Mid(file.Name, 11, (InStrRev(file.Name, ".") - 11))
Exit For
End If
Next
'*******************************************************************************
'Find version of user file, if it exists
'*******************************************************************************
isUserFile = 0
For each file In folder.Files
If InStr(file.Name, "AMSDshbd_" & userName) = 1 Then
isUserFile = 1
userVersion = Mid(file.Name, (Len(userName) + 10), (InStrRev(file.Name, ".") - (Len(userName) + 10)))
Exit For
End If
Next
'*******************************************************************************
'Copy the file if no user file exists or if the user version is not current
'*******************************************************************************
sourceFile = folderPath & "AMSDshbd_M" & masterVersion & ".accde"
targetFile = folderPath & "AMSDshbd_" & userName & "_M" & masterVersion & ".accde"
isCopyNeeded = 1
if isUserFile = 1 then
if userVersion = masterVersion then
isCopyNeeded = 0
end if
end if
if isCopyNeeded = 1 then
objFSO.CopyFile sourceFile, targetFile, True
end if
'*******************************************************************************
'Open the file
'*******************************************************************************
sComTxt = Chr(34) & microsoftAccessFile & Chr(34) & " " & Chr(34) & targetFile & Chr(34)
'objShell.Run sComTxt
objShell.Run sComTxt,,true
Set objFSO = Nothing
Set objShell = Nothing
I figured out what happened. the variable "microsoftAccessFile" is the path to the MS Access EXE, some of the users have a different path to this Access EXE that's why it doesn't work for them. I identified the path where their Access EXE is stored and changed the script for them and it works now. Thanks for pointing out the variable

Copy file names at Recycle Bin

I'm trying to copy all filenames list on the Recycle Bin in Windows 10.
I go to Command Prompt:
C:\>cd C:/$Recycle.Bin
C:\$Recycle.Bin>dir S-1-5-21-2370250818-2711005194-4184312249-1165
$R8CQG1I.txt
$IURO2ZD.txt
$RV2TEJ7.txt
I have 3 files I want to copy the real file names not the names like this result.
After some search I found this VBScript. I run the code and I get this error:
Expected end of statement
Option Explicit
DIM g_objWshShell, g_objFSO, g_sLogFile, g_objWshNetwork, g_sScriptName, g_sComputerName, g_sUserName Dim g_sVer, g_objLogFile, g_sLogDir
'Setup main variables and objects Set g_objWshShell = WScript.CreateObject("WScript.Shell") 'Create a Shell Object Set g_objFSO = CreateObject("Scripting.FileSystemObject") 'create a File System Object Set g_objWshNetwork = WScript.CreateObject("WScript.Network") 'Create Network Object g_sComputerName
= g_objWshNetwork.Computername 'Gets machine Computer name g_sUserName = g_objWshNetwork.UserName 'Gets logged-on username g_sScriptName=UCase(WScript.ScriptName) '
*** Name of the script
' *** START LogFile Information - use Delete or Append info below; don't use both *** Const FORREADING = 1, FORWRITING = 2, FORAPPENDING
= 8 'Setup constants for writing, appending, etc g_sLogDir = "C:\TEMP" If Not (g_objFSO.FolderExists(g_sLogDir)) Then g_objFSO.CreateFolder(g_sLogDir) End If g_sLogFile = g_sLogDir & "\" & Left(g_sScriptName,len(g_sScriptName)
- 3) & "LOG" 'Makes log file the SCRIPTNAME.Log g_sVer = "1.0"
'To delete a logfile and create a new one each time script is ran If g_objFSO.FileExists(g_sLogFile) Then g_objFSO.DeleteFile(g_sLogFile) 'Delete logfile if it exists. End If Set g_objLogFile = g_objFSO.CreateTextFile(g_sLogFile, FORWRITING) 'Setup the logfile for writing
Call Main() Call ExitScript()
'Start main script HERE *** Sub Main() Dim objRecycleBin, objFolderItems, objItem, strSpecialFolderName strSpecialFolderName = "Recycle Bin" 'Call WriteLine("Starting " & g_sScriptName & " at " & Date & " " & Time, g_objLogFile) Set objRecycleBin
= GetSpecialFolderObject(strSpecialFolderName) 'Get Special Folder based upon input name Set objFolderItems = objRecycleBin.Items() 'Get items within Recycle Bin For Each objItem In objFolderItems 'Delete all items within Special Folder If (objItem.Type = "File Folder") Then 'Check for file type g_objFSO.DeleteFolder(objItem.Path) 'Delete Folders Else g_objFSO.DeleteFile(objItem.Path) 'Delete Files End If WScript.Echo "Deleted " & objItem.Name Next End Sub
'*-*-*-*-*- Start Subroutines here
*-*-*-*-*- 'Returns SpecialFolder based upon name of folder Function GetSpecialFolderObject(NameOfFolder) Dim objShellApp, i, objSpecialFolder Set objShellApp = CreateObject("Shell.Application") On Error Resume Next For i=0 To 40 '40 is highest value for special folders Set objSpecialFolder = objShellApp.NameSpace(i) If (StrComp(objSpecialFolder.Title,NameOfFolder,vbTextCompare)=0) Then Set GetSpecialFolderObject = objSpecialFolder Exit For End If Next Err.Clear End Function
'Closes logfile and exits script Sub ExitScript() 'Call WriteLine(Date & " " & Time & "; Completed " & g_sScriptName, g_objLogFile) If IsObject(g_objLogFile) Then
g_objLogFile.Close End If Wscript.Quit End Sub
Sub EndOnError(sErrorString) WScript.Echo sErrorString & vbcrlf & "Check " & chr(34) & g_sLogFile & Chr(34) & " for details" Call WriteLine (sErrorString, g_objLogFile) WScript.Quit() End Sub
'Shows usage if input is wrong sub ShowUsage() WScript.Echo g_sScriptName & " v" & g_sVer & " Empties Recycle Bin for logged on user" & vbcrlf _ & vbcrlf & "USAGE: [CSCRIPT] " & g_sScriptName WScript.Quit end sub
'Writes to log Sub WriteLine(ByVal strMessage, ByVal objFile)
On Error Resume Next
If IsObject(objFile) then 'objFile should be a file object
objFile.WriteLine strMessage
Else
Call Wscript.Echo( strMessage )
End If End Sub
The VBScript version of #boxdog answer:
Set objShellApp = CreateObject("Shell.Application")
Set objSpecialFolder = objShellApp.NameSpace(10) '10 = Recyle Bin
For Each objFolder In objSpecialFolder.Items
WScript.Echo "FileName = " & objFolder.Name & vbTab & "Original Path = " & objFolder.ExtendedProperty("{9B174B33-40FF-11D2-A27E-00C04FC30871} 2")
Next
Answering this in case anyone is looking for VBS only solution.
In PowerShell, you can list the current path and original name/location of the Recycle Bin contents like This:
$shell = New-Object -ComObject Shell.Application
$shell.NameSpace(0x0a).Items() |
Select-Object #{Label="OriginalLocation";Expression={$_.ExtendedProperty("{9B174B33-40FF-11D2-A27E-00C04FC30871} 2")}},Name, Path
To copy the items, you can do this:
$shell.NameSpace(0x0a).Items() |
Copy-Item -Destination "C:\RecoveredFiles\$($_.Name)" -Recurse -Force
Note that this doesn't take into account any name-clashes - you'll need to test for that and adjust accordingly.

VBS zipping script

I found (apparently working for everybody) script which only needs to be modified (paths):
Sub NewZip(pathToZipFile)
'WScript.Echo "Newing up a zip file (" & pathToZipFile & ") "
Dim fso
Set fso = CreateObject("Scripting.FileSystemObject")
Dim file
Set file = fso.CreateTextFile(pathToZipFile)
file.Write Chr(80) & Chr(75) & Chr(5) & Chr(6) & String(18, 0)
file.Close
Set fso = Nothing
Set file = Nothing
WScript.Sleep 500
End Sub
Sub CreateZip(pathToZipFile, dirToZip)
'WScript.Echo "Creating zip (" & pathToZipFile & ") from (" & dirToZip & ")"
Dim fso
Set fso= Wscript.CreateObject("Scripting.FileSystemObject")
pathToZipFile = fso.GetAbsolutePathName(pathToZipFile)
dirToZip = fso.GetAbsolutePathName(dirToZip)
If fso.FileExists(pathToZipFile) Then
'WScript.Echo "That zip file already exists - deleting it."
fso.DeleteFile pathToZipFile
End If
If Not fso.FolderExists(dirToZip) Then
'WScript.Echo "The directory to zip does not exist."
Exit Sub
End If
NewZip pathToZipFile
dim sa
set sa = CreateObject("Shell.Application")
Dim zip
Set zip = sa.NameSpace(pathToZipFile)
'WScript.Echo "opening dir (" & dirToZip & ")"
Dim d
Set d = sa.NameSpace(dirToZip)
' Look at http://msdn.microsoft.com/en-us/library/bb787866(VS.85).aspx
' for more information about the CopyHere function.
zip.CopyHere d.items, 4
Do Until d.Items.Count <= zip.Items.Count
Wscript.Sleep(200)
Loop
End Sub
Can anybody give example how this script should look like with
real paths? I'm trying but it's not working for me.
This script consists solely of two subroutines and thus will never execute anything.
Add the following line to the bottom of the file and it should work (given that the code in the subs is sound, I have not tested):
CreateZip "c:\output\test.zip" "c:\input\"
This will do the following, in order:
Check to see if the output file exists. If it does, it will delete it.
Check to see if the input folder exists, if it does not, the script will exit.
Call the NewZip sub which just creates an "empty" .zip file.
Copy files to the zip file.
Pause for a while, probably to ensure you don't try to access the ZIP before it's done copying.
The contents of the input folder will now be in the zip file in the output folder.

How to change certain code inside a VBScript with another VBScript?

I have made the script FindAndReplace.vbs which simply watches a folder and finds any desired string in the filenames and replaces that string with a desired string.
Now, What I´m trying to create is a VBScript (ConfigureFindAndReplace.vbs) that will easily configure the following 3 things in the FindAndReplace.vbs code:
Browse and select which folder to watch (targetPath)
Which text string to search for in the filenames of the files inside this folder (strFind)
Which string to replace with (strReplace)
I want the script to be user friendly for users with no programming skills.
And I want the main executable script FindAndReplace.vbs to automatically be updated EVERY time the ConfigureFindAndReplace.vbs is run.
To better help you understand here is th
e link to a .zip file containing both of the above mentioned files. This is as far as I can get and I´ve been stuck for 2 days now:
https://www.dropbox.com/s/to3r3epf4ffyedb/StackOverFlow.zip?dl=0
Hope I explained it properly. If not, let me know whatever you need to know.
Thanks in advance:)
And here are the codes from the files:
ConfigureFindAndReplace.vbs:
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objShell = CreateObject ("Shell.Application")
Set objTFolder = objShell.BrowseForFolder (0, "Select Target Folder", (0))
targetPath = objTFolder.Items.Item.Path
Dim oFSO
Set oFSO = CreateObject("Scripting.FileSystemObject")
sScriptDir = oFSO.GetParentFolderName(WScript.ScriptFullName) & "/"
strFind = InputBox("Add string to find.","String to Find", "")
If strFind = "" Then
Wscript.Quit
End If
strReplace = InputBox("Add string to replace with.","Replace with", "")
Dim VarFind
Dim VarReplace
Dim VarPath
VarFind = strFind
VarReplace = strReplace
VarPath = targetPath
Dim WshShell
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfind:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strreplace:" & VarPath
FindAndReplace.vbs:
'Written by Terje Borchgrevink Nuis on 15.12.2014
Set objFSO = CreateObject("Scripting.FileSystemObject")
Dim strFind
Dim strReplace
Dim strFolderPath
strFolderPath = WScript.Arguments.Named("strfolderpath")
targetPath = strFolderPath
'Max number of times to replace string
strCount = 999
'Comparison type: 0 = case sensitive, 1 = case insensitive
strCompare = 1
If targetPath = "" Then
Wscript.Quit
End If
strFind = WScript.Arguments.Named("strfind")
If strFind = "" Then
Wscript.Quit
End If
strReplace = WScript.Arguments.Named("strreplace")
Set objFolder = objFSO.GetFolder(targetPath)
fileRename objFolder
Sub fileRename(folder)
Do
Wscript.sleep 10000
'Loop through the files in the folder
For Each objFile In folder.Files
filename = objFile.Name
ext = objFSO.getExtensionName(objFile)
safename = Left(filename, Len(filename) - Len(ext) - 1)
strStart = 1
safename = Replace(safename, strFind,strReplace,strStart,strCount,strCompare)
safename = trim(safename)
On Error Resume Next
'Terminate if filename stop.txt is found
If filename="STOP.txt" Then
result = MsgBox ("Are you sure you want to terminate the following VBScript?" & vbNewLine & vbNewLine & "FindAndReplace.vbs", vbOKCancel+vbSystemModal , "Terminate VBScript")
Select Case result
Case vbOK
WScript.quit
Case vbCancel
MsgBox "FindAndReplace.vbs is still running in the background.",,"Information"
End Select
End If
'Only rename if new name is different to original name
If filename <> safename & "." & ext Then
objFSO.MoveFile objFile.Path, objFile.ParentFolder.Path & "\" & safename & "." & ext
End If
If Err.Number <> 0 Then
WScript.Echo "Error renaming: " & filename.path & "Error: " & Err.Description
Err.Clear
End If
Next
Loop
End Sub
You think you want ConfigureFindAndReplace to change the other script, this is a bad idea.
You don't know it yet, but what you actually want is for FindAndReplace to read those items from a configuration file.
If the config file is well formed and easy to read, then your users can directly update the config file, so you may not even need the ConfigureFindAndReplace script.
How?
Have a text file with 3 lines
Target Folder=c:\DataFolder
String to find=a string
Replace with=Replace a string with this string
Then in FindAndReplace, before doing any work, you open this file and read in the three lines.
Split the lines on the '=' sign. The left half is the setting and the right half is the value.
Math these up to three variables in the script
If configLineLeft = "Target Folder" then REM Each of these should be case insensitive match
REM e.g. lcase(configLineLeft) = lcase("Target Folder")
TargetFolder = configLineRight
else if configLineLeft = "String to find" then
FindString = configLineRight
else if configLineLeft = "Replace with" then
ReplaceString = configLineRight
else
REM REPORT A PROBLEM TO THE USER AND EXIT
EXIT SUB
end if
You'd do the above in a while loop (while not end of file), reading each line and testing to see which setting it is.
As I can't find any VBScript in your .Zip, some general advice. If you want a not-to-be-edited script to do different things
let the script access parameters/arguments and specifying the differences by calling the script with different arguments: cscript FindAndReplace.vbs "c:\some\folder" "param" "arg"
let the script access config data (from a .txt, .ini, .xml, .json, ... file; from a database; from the registry; ...) and use the config script to set these data
use a template/placeholder file to generate (different version of) the script
I would start with the first approach.
After reading your edit:
Instead of calling your script trice with bad args:
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfind:" & VarPath
WshShell.Run sScriptDir & "FindAndReplace.vbs /strreplace:" & VarPath
execute it once with proper args:
WshShell.Run sScriptDir & "FindAndReplace.vbs /strfolderpath:" & VarPath & " /strfind:" & VarFind & "/strreplace:" & VarReplace
(untested; you need to check the names and take care of proper quoting; cf here)

Enumerating Sub-Folder Properties with VBscript

This is somewhat related to Microsoft System Center Configuration Manager 2007, but it's really about an issue with VBScript, the FileSystemObject API and reading sub-folder properties.
I am trying to run a script to enumerate the folders and folder sizes on one of our Distribution Points (every folder beneath the Package Share). I'm using the FileSystemObject API, with VBscript, I can crawl about 60% of the sub-folders, and get their names and sizes, but then the rest return "error 70 / Permission Denied". It doesn't matter what account I execute the script as, and I've tried adding a Sleep() delay between each sub-folder object reference. It still won't get them all.
If I manually explore the folders, I can view their properties without any problem. Is this a known issue with FSO or maybe Windows Scripting Host? I've attached the script code below. TIA!
'****************************************************************
' Filename..: fso_subfolder_sizes.vbs
' Author....: skatterbrainz
' Date......: 02/10/2013
' Purpose...: enumerate package folders and tally disk space
'****************************************************************
Option Explicit
Const rootFolder = "\\SERVER123\ShareName$"
Dim time1, folderCount, totalSpace
Dim objFSO, objFolder, objSub
Dim GBsize, folderName, folderSIze
time1 = Timer
Set objFSO = CreateObject("Scripting.FileSystemObject")
folderCount = 0
totalSpace = 0
On Error Resume Next
Set objFolder = objFSO.GetFolder(rootFolder)
If err.Number = 0 Then
wscript.echo "<folders>"
For each objSub in objFolder.SubFolders
folderName = objSub.Name
folderSize = objSub.Size
GBsize = FormatNumber(Bytes2Gbytes(folderSize), 2) & " GB"
wscript.echo "<folder name=""" & folderName & """ size=""" & GBsize & """/>"
folderCount = folderCount + 1
totalSpace = totalSpace + folderSize
Next
Set objFolder = Nothing
wscript.echo "</folders>"
wscript.echo "--------------------------"
wscript.echo "sub-folders: " & folderCount
wscript.echo "total space: " & FormatNumber(Bytes2GBytes(totalSpace),2) & " GB"
Else
wscript.echo "root folder not found"
End If
Set objFSO = Nothing
wscript.echo "runtime: " & FormatNumber(Timer - time1, 2) & " Msecs"
Function Bytes2Gbytes(n)
If n > 0 Then
Bytes2Gbytes = (n / 1024 / 1024 / 1024)
Else
Bytes2Gbytes = 0
End If
End Function
Yes this is a known issue, on folders with security issues (like eg your c:\windows folder) you get errors when you use .count of .size on folder. Instead enumerate each file and sum the count and size.
I had the same problem when trying to get profile size of each UserProfile from a share. I used excel and was looping through rows with usernames that I knew had a profile in the share, like this:
strUserName = ActiveCell.Value
objP = "\\SERVER\SHARE$\" & strUserName & "\UPM_Profile"
ActiveCell.Offset(0, 1).Value = (FormatNumber(objFSO.GetFolder(objP).Size, 0, , , 0) / 1024) / 1024
Just some of the thousands folders gave "Path Not Found"
It all worked when I instead mapped the Share to a driveletter:
objP = "Z:\" & strUserName '& "\UPM_Profile"
I found an interesting, yet reproducible behavior with this topic. At least in our production environment: If I specify the root path as the root hidden share (i.e. "\SERVER\Share$") it gets really bogged down. But if I go one level deeper, such as "\SERVER\Share$\Apps") it seems to run much better. I also modified the script to print the sub-folder name first, and THEN query the .Size property, and that seems to point to the performance bottleneck. Note the change in statement ordering in the updated example below...
For each objSub in objFolder.SubFolders
folderName = objSub.Name
wscript.echo vbTab & "<folder>"
wscript.echo vbTab & vbTab & "<folderName>" & folderName & "</folderName>"
folderSize = objSub.Size
GBsize = FormatNumber(Bytes2Gbytes(folderSize), 2) & " GB"
wscript.echo vbTab & vbTab & "<folderSize>" & GBsize & "</folderSize>"
wscript.echo vbTab & "</folder>"
folderCount = folderCount + 1
totalSpace = totalSpace + folderSize
Next

Resources