Want to make a directory inaccessible with vb6 - vb6

I'm working on a program that will disable access to shared folders on a document server if the hard drive is getting close to being full. Currently, I am just renaming them to something different to prevent the app server from being able to send more documents over. I'm wondering if there is a way to somehow lock down a folder programmatically, either setting it to read only, or disable its share status. From what I've seen, changing a folder to read-only directly in windows doesn't prevent new files from being copied into it. Anyone have any ideas on how to do this? My current code looks like this:
Private Function MoveShares(ByVal strOldLocation As String, ByVal strNewLocation As String) As Boolean
Dim objFSO As New FileSystemObject
If objFSO.FolderExists(strOldLocation) Then
LogAction "Moving " & strOldLocation & " to " & strNewLocation
objFSO.MoveFolder strOldLocation, strNewLocation
End If
Set objFSO = Nothing
End Function
Pretty basic, but I'm hoping I can do this in a subtler way.

googled this and found something similar on Daniweb, this is not my code so no warranties. I pasted the code below. Assuming this works try modifying permissions to deny the account(s) that are used by the apps. Deny permissions will override allowed permissions. You can look at the source here.
Dim strHomeFolder, strHome, strUser
Dim intRunError, objShell, objFSO
strHomeFolder = "C:\Test"
strUser="srikanth"
Set objShell = CreateObject("Wscript.Shell")
Set objFSO = CreateObject("Scripting.FileSystemObject")
If objFSO.FolderExists(strHomeFolder) Then
intRunError = objShell.Run("%COMSPEC% /c Echo Y| cacls " & strHomeFolder & " /t /c /g everyone:F ", 2, True)
wscript.echo "The File " & strHomeFolder & ". Permissions changed to Every One."
If intRunError <> 0 Then
Wscript.Echo "Error assigning permissions for user " & strUser & " to home folder " & strHomeFolder
End If
End If

For the shared folder, I ended up editing the registry to "rename" the share itself, not the folder. I did this by reading the registry entry data, deleting the entry, and writing the data to a new entry. I also had to restart the computer browser and server services in order for the server to acquire the new share name. This prevents the app server from sending documents because it can't find a share with the old name. I also had to convert the security entry values from decimal back to hexadecimal before writing them to the new entry, and wait between stopping and restarting services to make sure they had finished before moving on the to next service.
Private Function RenameShare(ByVal strOldName As String, ByVal strNewName As String) As Boolean
Dim objRegAccess As Object
Dim varValues() As Variant
Dim varItem As Variant
Dim strSharePath As String
Dim strSecurityPath As String
Dim strValues As String
Dim strCmd As String
Set objRegAccess = CreateObject("Wscript.Shell")
strSharePath = "HKLM\SYSTEM\CurrentControlSet\services\LanmanServer\Shares\"
strSecurityPath = strSharePath & "Security\"
strValues = ""
varValues = objRegAccess.RegRead(strSharePath & strOldName)
strValues = ""
For Each varItem In varValues
strValues = strValues & varItem & "~"
Next
RunCommand "REG ADD " & strSharePath & " /v " & strNewName & " /t REG_MULTI_SZ /s ~ /d " & strValues & " /f", False
RunCommand "REG DELETE " & strSharePath & " /v " & strOldName & " /f", False
strValues = ""
varValues = objRegAccess.RegRead(strSecurityPath & strOldName)
For Each varItem In varValues
strValues = strValues & varItem & "~"
Next
strValues = ConvertDecToHex(strValues)
RunCommand "REG ADD " & strSecurityPath & " /v " & strNewName & " /t REG_BINARY /d " & strValues & " /f", False
RunCommand "REG DELETE " & strSecurityPath & " /v " & strOldName & " /f", False
RunCommand "NET STOP ""Computer Browser"" ", True
RunCommand "NET STOP ""Server"" ", True
RunCommand "NET START ""Server"" ", True
RunCommand "NET START ""Computer Browser"" ", False
End Function

Related

Searching the registry with vbs to find an unknown part of the path

I use a path to locate pieces of information that contains a guid that can change. I had the guid value hard coded, but when it changes it doesn't function. I need to discover that guid dynamically. I know a value on the other side of the guid and have a REG Query that finds the entire path, but I can't figure out how to capture that path.
Here's the REG Query:
REG Query HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products /D /V /F "Microsoft Office Professional Plus 2010" /S /E
It returns the Value "DisplayName" and it's contents "Microsoft Office Professional Plus"
When run from a batch file it also displays the entire path that includes the elusive guid. I would like to do this from a vb script.
Also the newer Windows Scripting Host Shell object also makes registry access easy.
Set wshshell = CreateObject("WScript.Shell")
wshshell.RegDelete(strName)
wshshell.RegRead(strName)
wshshell.RegWrite(strName, anyValue [,strType])
See https://msdn.microsoft.com/en-us/library/293bt9hh(v=vs.84).aspx
Also WMI can access registry. Unlike both above methods it can ennumerate, so you can see what is there without having to know in advance.
Dim proglist()
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
ret = oReg.EnumKey(&H80000002, "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall", proglist)
If err.num =0 then
For each prog in proglist
msgbox prog
Next
Else
Msgbox err.num & " " & err.description & " " & err.source
err.clear
End If
https://msdn.microsoft.com/en-us/library/aa390387(v=vs.85).aspx
It can also check security and monitor changes to keys.
This monitors changes to Windows Uninstall key.
Set objWMIService = GetObject("winmgmts:root/default")
Set objEvents = objWMIService.ExecNotificationQuery("SELECT * FROM RegistryTreeChangeEvent WHERE Hive='HKEY_LOCAL_MACHINE' AND RootPath='SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Uninstall'")
Do
Set objReceivedEvent = objEvents.NextEvent
msgbox objReceivedEvent.GetObjectText_()
Loop
https://msdn.microsoft.com/en-us/library/aa393041(v=vs.85).aspx‎
Recursion is used to walk each node in a tree. The function calls itself every time it comes across a node. Start below program using cscript to avoid a few thousand msgboxs - cscript //nologo c:\folder\RecurseReg.vbs.
Set wshshell = CreateObject("WScript.Shell")
EnumReg "SOFTWARE\CLASSES"
Sub EnumReg(RegKey)
On Error Resume Next
wscript.echo "---------------------------------------"
wscript.echo "HKLM\" & RegKey & " = " & wshshell.RegRead("HKLM\" & RegKey & "\")
err.clear
Dim KeyList()
Dim ValueNameList()
Dim ValueList()
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
If err.number <> 0 then
wscript.echo err.number
err.clear
End If
ret = oReg.EnumValues(&H80000002, RegKey, ValueNameList, ValueList)
If err.number = 0 then
For each valuename in ValueNameList
If valuename <> "" then
Value = wshshell.RegRead("HKLM\" & RegKey & "\" & valuename)
err.clear
wscript.echo valuename & " - " & Value
End If
Next
Else
Msgbox err.num & " " & err.description & " " & err.source
err.clear
End If
ret = oReg.EnumKey(&H80000002, RegKey, Keylist)
If err.number =0 then
For each key in keylist
EnumReg RegKey & "\" & key
Next
Else
Msgbox err.num & " " & err.description & " " & err.source
err.clear
End If
End Sub
Putting both together (this does VC 2008 Runtime which should be on all computers)
Dim proglist()
Set wshshell = CreateObject("WScript.Shell")
On Error Resume Next
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
ret = oReg.EnumKey(&H80000002, "SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products", proglist)
If err.num =0 then
For each prog in proglist
' msgbox prog
If wshshell.RegRead("HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Products\" & Prog & "\InstallProperties\DisplayName") = "Microsoft Visual C++ 2008 Redistributable - x64 9.0.30729.17" then
Msgbox "Found " & Prog
End If
Next
Else
Msgbox err.num & " " & err.description & " " & err.source
err.clear
End If
For V6 or VBA
The registry is simple in VBA. It's is very limited and uses ini file concepts.
There's a few of them such as (from Object Browser [F2] in VBA editor)
Function GetAllSettings(AppName As String, Section As String)
Member of VBA.Interaction
Sub SaveSetting(AppName As String, Section As String, Key As String, Setting As String)
Member of VBA.Interaction
Sub DeleteSetting(AppName As String, [Section], [Key])
Member of VBA.Interaction
Function GetSetting(AppName As String, Section As String, Key As String, [Default]) As String
Member of VBA.Interaction
Also the Windows API calls can be used.
RegOpenKeyEx
The RegOpenKeyEx function opens the specified registry key.
LONG RegOpenKeyEx(
HKEY hKey, // handle to open key
LPCTSTR lpSubKey, // subkey name
DWORD ulOptions, // reserved
REGSAM samDesired, // security access mask
PHKEY phkResult // handle to open key
);

create folder(trusted), copy of MDE and shortcut

I have put together a script that I think will work, but the only code I know is some VBA. Never tried to create a vbscript before, so my apologies if some errors are obvious, but pointers and corrections would be appreciated.
I am hoping I can give users in my company a link to this script and have them run it. It will create a folder on their C Drive, make it a trusted location, copy a database frontend from the server into it and create a shortcut on their desktop linking to the new file. (I'm hoping the file will auto-update when a new version is made - I think that bit works though).
The code comes from various sources, including my own addled mind but would I need to download Visual Studio to test this? Slightly concerned as it includes creating a registry key and I don't know how to stop the code if it all goes horribly wrong. I don't even know how to break a loop (although I think I read somewhere you need to hit Esc twice). Any tips on how to signify which sub is the main one to run on start would be good too.
EDIT : Code has been amended to my end result incase it is of use to others. Please use with caution. The 'update' vbs deletes the folder created on the local drive.
'FrontEnd Setup
call CreateTrustedFolder
'Const HKEY_CLASSES_ROOT = &H80000000
Const HKEY_CURRENT_USER = &H80000001
'Const HKEY_LOCAL_MACHINE = &H80000002
'Const HKEY_USERS = &H80000003
'Const HKEY_CURRENT_CONFIG = &H80000005
Dim lclFolder
Dim blnUpdate
Sub CreateTrustedFolder()
On error resume next
Call RunAdmin
Call FolderFileShortcut
Call CreateReg
if err then
MsgBox "The following error has occurred " & Err & " " & Err.Description
exit Sub
end if
End Sub
'Run as Administrator
Sub RunAdmin()
On error resume next
If Not WScript.Arguments.Named.Exists("elevate") Then
CreateObject("Shell.Application").ShellExecute WScript.FullName _
, WScript.ScriptFullName & " /elevate", "", "runas", 1
WScript.Quit
End If
if err then
MsgBox "The following error has occurred " & Err & " " & Err.Description
exit Sub
end if
End Sub
'Check if folder exists, add file and desktop shortcut
Sub FolderFileShortcut()
On error resume next
Dim oWS
Dim FSO
Dim svrFolder
Dim myShortcut
Dim strLocalDB
Dim strServerDB
Dim strUpdate
Dim strIcon
Dim objFile
Dim counter
Set oWS = WScript.CreateObject("WScript.Shell")
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
svrFolder = "\\192.168.1.2\DeptFolder\DatabaseFolder\Auto-Update"
lclFolder = "C:\Program Files\Orrible Database"
If (FSO.FolderExists(lclFolder)) Then
oWS.run "icacls """ & lclFolder & """ /reset /grant:r Users:(W) /t" '/T required for existing folders
FSO.DeleteFolder lclFolder
blnUpdate = True
end if
If Not (FSO.FolderExists(svrFolder)) Then
msgbox "Unable to connect to Location Server", vbCritical, "Installation Failed"
WScript.Quit
End If
For Each objFile in FSO.Getfolder(svrFolder).Files
if LCase(FSO.GetExtensionName(objFile.name)) = LCase("mde") then
counter = counter + 1
strServerDB = FSO.GetFileName(objFile)
end if
Next
If strServerDB = "" or counter <> 1 then
msgbox "Unable to locate the Front End" & strServerDB & "-" & counter, vbCritical, "Installation Failed"
wScript.Quit
end if
strLocalDB = "Co Database.mde"
strUpdate = "DB_UpdateCheck.vbs"
strIcon = "Frontend Update.ico"
FSO.CreateFolder(lclFolder)
oWS.run "icacls """ & lclFolder & """ /grant Users:(OI)(CI)F /t" '/T required for existing folders
FSO.CopyFile svrFolder & "\" & strUpdate, lclFolder & "\" & strUpdate, True
FSO.CopyFile svrFolder & "\" & strServerDB, lclFolder & "\" & strLocalDB, True
FSO.CopyFile svrFolder & "\" & strIcon, lclFolder & "\" & strIcon, True
strDesktop = oWS.SpecialFolders("Desktop")
set myShortcut = oWS.CreateShortcut(strDesktop + "\New Database.lnk")
myShortcut.TargetPath = lclFolder & "\" & strUpdate
myShortcut.WindowStyle = 1
myShortcut.IconLocation = lclFolder & "\" & strIcon
myShortcut.WorkingDirectory = strDesktop
myShortcut.Save
if err then
MsgBox "The following error has occurred " & Err & " " & Err.Description
exit Sub
end if
End Sub
Sub CreateReg()
On error resume next
Dim objRegistry 'registry object
Dim strDescription 'Description of the Trusted Location
Dim strParentKey 'Registry location of Application
Dim strNewKey 'strParentKey and myFolder
Dim oWS 'WSH shell object
strDescription = "DB Folder"
strParentKey = "Software\Microsoft\Office\15.0\Access\Security\Trusted Locations"
strNewKey = strParentKey & "\" & strDescription & "\"
Set objRegistry = GetObject("winmgmts:\\.\root\default:StdRegProv")
'objRegistry.GetStringValue HKEY_CURRENT_USER, strParentKey & "\" & strDescription
If Not objRegistry.EnumKey(HKEY_CURRENT_USER, strNewKey) = 0 then '0=true
objRegistry.CreateKey HKEY_CURRENT_USER, strNewKey
objRegistry.SetStringValue HKEY_CURRENT_USER, strNewKey, "Path", lclFolder
objRegistry.SetStringValue HKEY_CURRENT_USER, strNewKey, "Description", strDescription
End if
If not blnUpdate = True then
msgbox "The Database is now available from your desktop", vbInformation, "Setup Complete"
Else
msgbox "The update is now complete."
End if
if err then
MsgBox "The following error has occurred " & Err & " " & Err.Description
exit Sub
end if
End Sub
There is also a separate Update vbs which is what runs when the link is clicked. This checks to see if the 'created date' of the database on the server is newer than that on the local drive. The new DB name MUST NOT be the same as the one it is replacing. It might run a little fast, but this is as far as I have taken this.
Call CheckForUpdate
Sub CheckForUpdate()
On Error Resume Next
Dim FSO
Dim oWS
Dim svrFolder
Dim lclFolder
Dim svrFail
Dim strLocalDB
Dim strServerDB
Dim lclDate
Dim svrDate
Dim strFileName
Dim intDBcount
Dim fCheck
Set oWS = WScript.CreateObject("WScript.Shell")
Set FSO = WScript.CreateObject("Scripting.FileSystemObject")
svrFolder = "\\192.168.1.2\DeptFolder\DatabaseFolder\Auto-Update"
lclFolder = "C:\Program Files\Orrible Database"
strLocalDB = "Co Database.mde"
If Not (FSO.FolderExists(svrFolder)) Then
msgbox "Unable to connect to Location Server", vbCritical, "Update Check Failed"
svrFail = True
End If
If Not svrFail = True Then
For Each fCheck in FSO.GetFolder(svrFolder).Files
If Ucase(Right(fCheck.Name, 3)) = "MDE" Then
intDBcount = intDBcount + 1
strServerDB = fCheck.name
End If
Next
If Not intDBcount = 1 Then
MsgBox "Please inform the Administrator that there is a problem with the Automated Update System.", _
vbCritical, "Update Failed (" & intDBcount & ")"
svrFail = True 'not quit - need to see if old version available
End If
End If
If Not (FSO.FolderExists(lclFolder)) Then
If svrFail = True Then 'If no lcl folder or server
If Not intDBcount = 1 then WScript.Quit
msgbox "You are unable to use the Database." & vbcrlf & _
"Please try again when you have access to the Location Server.", _
vbcritical, "Database Not Installed"
WScript.Quit
Else 'If no lclfolder, get it from svr
'Do normal initial install
oWS.Run svrFolder & "\" & "DB_Install.vbs", 1, True
WScript.Quit
End If
Else
If svrFail = True Then 'If lcl folder, but no svr
'open db
oWS.Run CHR(34) & lclFolder & "\" & strLocalDB & CHR(34)
WScript.Quit
Else 'If lcl folder and svr access, check for update.
lclDate = fso.getfile(lclFolder & "\" & strLocalDB).DateCreated
svrDate = fso.getfile(svrFolder & "\" & strServerDB).DateCreated
If lclDate < svrDate Then 'Update available
intMsg = MsgBox("An update is available - Do you wish to update now?", vbQuestion + vbYesNo, "Update Found")
If intMsg = vbYes Then
oWS.Run svrFolder & "\" & "DB_Install.vbs", 1, True ',1,true should pause the code until install closes
oWS.Run CHR(34) & lclFolder & "\" & strLocalDB & CHR(34)
WScript.Quit
Else
oWS.Run CHR(34) & lclFolder & "\" & strLocalDB & CHR(34)
WScript.Quit
End If
Else
oWS.Run CHR(34) & lclFolder & "\" & strLocalDB & CHR(34)
WScript.Quit
End If
End If
End If
If err Then
MsgBox "The following error has occurred " & Err & " " & Err.Description
Exit Sub
End If
End Sub

"Less than" statements not evaluating

Running into this problem. Trying to uninstall all previous version of a program using the less than statement and installing new version. It doesn't recognize the less than and will keep uninstalling and reinstalling the newest version everytime.
Option Explicit
Const HKEY_LOCAL_MACHINE = &H80000002
Dim Msg, MsgBoxStyle, RegKey, NAMProductKey, NAMProductName, NAMVersion
'=== START Check for Cisco AnyConnect Network Access Manager < 3.1.05170
Sub GetNAMKey()
Dim oReg, sPath, aKeys, sName, sKey, sVersion
Set oReg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")
sPath = "SOFTWARE\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall"
oReg.EnumKey HKEY_LOCAL_MACHINE, sPath, aKeys
For Each sKey in aKeys
oReg.GetStringValue HKEY_LOCAL_MACHINE, sPath & "\" & sKey, "DisplayName", sName, "DisplayVersion", sVersion
If Not IsNull(sName) Then
If (sName = "Cisco AnyConnect Network Access Manager") Then
NAMProductKey = sKey
NAMProductName = sName
NAMVersion = sVersion
End If
End If
Next
End Sub
'=Start Uninstall Reference==
Sub UninstallUNI(key, name)
Dim cmd, objShell, iReturn, oshell
cmd = "%SystemRoot%\System32\msiexec.exe /q/x " & key
Set objShell = wscript.createObject("wscript.shell")
objShell.LogEvent 0, "Removing the program [" & name & "] under Product Key [" & key & "]" & vbCrLf & "Executing command: " & vbCrLf & cmd
iReturn=objShell.Run(cmd,1,TRUE)
If (iReturn = 0) Then
objShell.LogEvent 0, "Program [" & name & "] was successfully removed"
Else
objShell.LogEvent 0, "Failed to remove the program [" & name & "]."
End If
Set objShell = Nothing
End Sub
'=== START CALLs (This is the script's logic.)
Dim objWSH
Set objWSH = CreateObject("WScript.Shell")
NAMProductKey = ""
NAMProductName = ""
NAMVersion = ""
Call GetNAMKey()
If Not (NAMProductKey = "") Then
If (NAMVersion < "3.1.05170") Then
Call UninstallUNI
NAMProductKey = ""
NAMProductName = ""
NAMVersion = ""
Call GetNAMKey()
If (NAMProductKey = "") Then
'Now we need to produce "msiexec.exe /a "Msi file.msi" /quiet /norestart" for a silent MSI install
objWSH.Run "msiexec.exe /i " + Chr(34) + "C:\Users\sek\Music\Cisco ISE\AnyConnect Network Access Manager\anyconnect-nam-win-3.1.05170-k9.msi" + Chr(34) + " /quiet /norestart"
End If
End If
Else
'Now we need to produce "msiexec.exe /a "Msi file.msi" /quiet /norestart" for a silent MSI install
objWSH.Run "msiexec.exe /i " + Chr(34) + "C:\Users\sek\Music\Cisco ISE\AnyConnect Network Access Manager\anyconnect-nam-win-3.1.05170-k9.msi" + Chr(34) + " /quiet /norestart"
End If
Unless you have very specific knowledge about how Cisco names it's versions you can not compare them like this.
The method you are using is a string compare which follows some lexicographic standard rules.
Because of that a version umber like 3.2 will be considered greater than 3.10.
In order to fix this you will have to split the string with '.' as delimiter and compare the subversion numbers independently.
However this is more a general observation and not the direct reason for the wrong evaluation.
I think the reason for that lies within your GetStringValue call.
According to the API this method can not return 2 values at once, so I am a bit puzzled how this is even executed without error. It explains however why the version number is not returned correctly. You would need a second GetStringValue call for that.

Convert A Robocopy Command to VB Script

I used to use a line in Robocopy that would allow me to copy all folders in a folder INCLUDING the parent folder, I.E all files/folders in the Blackberry folder INCLUDING the Blackberry folder itself, else without it it would just copy the files within and dump them in the backup location...
The code used was;
for %%a in ("%source%") do SET destination="Backups\%date%\%%~nxa"
Now in VB Script I've got;
sSource = Chr(34) & objFolder.self.Path & Chr(34) & " "
So how would I go about having VB Script (which still calls Robocopy) use the above so that when it backs up it will include the PARENT folder as well?
This was the code I had; Converting Robocopy Batch To VB Script
Thanks in advance!
EDIT: The current content of my script file;
Dim BrowseBackupSource
Set objShell = CreateObject("Shell.Application")
Set objFolder = objShell.BrowseForFolder(0, "Please browse to the folder you would like to backup.", 1, "C:\")
If objFolder Is Nothing Then
Wscript.Quit
End If
wscript.Echo "folder: " & objFolder.title & " Path: " & objFolder.self.path
Dim BrowseBackupLocation
Set objShell = CreateObject("Shell.Application")
Set objDest = objShell.BrowseForFolder(0, "Please browse to the folder you would like to save the backup to.", 1, "C:\")
If objDest Is Nothing Then
Wscript.Quit
End If
wscript.Echo "folder: " & objDest.title & " Path: " & objDest.self.path
sCmd = "%windir%\System32\Robocopy.exe "
sDate = Day(Now) & "-" & Month(Now) & "-" & Year(Now)
sTime = Hour(Now) & "-" & Minute(Now) & "-" & Second(Now)
sSource = Chr(34) & objFolder.self.Path & Chr(34) & " "
sDestination = Chr(34) & objDest.self.Path & Chr(34) & " "
sSwitches = "/E /Log:"& sTime &".txt"
Set objShell = CreateObject("Wscript.Shell")
objShell.Run(sCmd & sSource & sDestination & sSwitches)
Well, if you need the path to the parent folder to set as root of copy:
dim parentFolderPath
parentFolderPath = WScript.CreateObject("Scripting.FileSystemObject").GetFolder(objFolder.self.Path).ParentFolder.Path
EDIT
You need the name of the selected source directory added to the path of the selected destination so
Set fso = WScript.CreateObject("Scripting.FileSystemObject")
sSourceFolderName = fso.GetFolder(objFolder.self.Path).Name
sDestination = Chr(34) & objDest.self.Path & "\" & sSourceFolderName & Chr(34)
Robocopy will handle the target directory creation
If you want to create a copy of a particular folder for backup, why don't you simply copy that folder to the backup destination and be done with it?
Set fso = CreateObject("Scripting.FileSystemObject")
Set app = CreateObject("Shell.Application")
dst = "C:\backups\" & Year(Now) & "\" & Month(Now) & "\" & Day(Now)
CreatePath dst
Set fldr = app.BrowseForFolder(0, "Example", 1, "c:\Programs")
fso.CopyFolder fldr.Self.Path, dst & "\", True
Sub CreatePath(p)
If Not fso.FolderExists(p) Then
CreatePath fso.GetParentFolderName(p)
fso.CreateFolder p
End If
End Sub

VBScript FTP Login with Username and Password

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

Resources