Can I keep reusing a file system object or do I need to create multiple objects? (1 Viewer)

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
So, I'm working on my App launch script and trying to streamline things. I would like to use one file system object for everything but I have no idea if that will cause problems or not. Here is some sample code. Not all variables are defined within this codeblock.

JavaScript:
Dim oFSO
Set oFSO = CreateObject("Scripting.FileSystemObject")

If Not oFSO.FileExists(sLocalLog & "\errorlog.txt") Then
    Dim f
    Set f = oFSO.CreateTextFile(sLocalLog & "\errorlog.txt", True)
    f.WriteLine strError
    f.Close
Else
    Dim f
    Set f = oFSO.OpenTextFile(sLocalLog & "\errorlog.txt", ForAppending, TristateFalse)
    f.WriteLine strError
    f.Close
End If
 

theDBguy

I’m here to help
Staff member
Local time
Today, 01:39
Joined
Oct 29, 2018
Messages
21,473
I believe you can reuse objects (check out self-healing objects), just be careful you don't step over your toes when using them in several places. I think, as much as you can, you should try to isolate each process from one another. Just my 2 cents...
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
just be careful you don't step over your toes when using them in several places
That's what I'm trying to do! :)

How might one trip over one's toes?

The original code I'm referencing sets a new object inside of each clause of the If/Then statement.
 

theDBguy

I’m here to help
Staff member
Local time
Today, 01:39
Joined
Oct 29, 2018
Messages
21,473
The original code I'm referencing sets a new object inside of each clause of the If/Then statement.
Yes, but those lines are setting different objects, not the same one to be reused. The oFSO variable is for an FSO object, and the f variable is for File object.
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
Sorry, i didn't post the original code :)

Here's a sample:

JavaScript:
    If Not oFSO.FileExists(sLocalLog & "\startuplog.txt") Then        'Check if log file exists
        Dim fs, f
        Set fs = CreateObject("Scripting.oFSOtemObject")
        Set f = fs.CreateTextFile(cLocalFE & \errorlog.txt", True)
        f.WriteLine strError
        f.Close
    Else
        Const ForReading = 1, ForWriting = 2, ForAppending = 3
        Dim fs, f
        Set fs = CreateObject("Scripting.oFSOtemObject")
        Set f = fs.OpenTextFile(cLocalFE & "\startuplog.txt", ForAppending, TristateFalse)
        f.WriteLine strError
        f.Close
    End If

Both file system and file objects are created with each of the clauses. In my code I took out the redundant object setting.
 

theDBguy

I’m here to help
Staff member
Local time
Today, 01:39
Joined
Oct 29, 2018
Messages
21,473
Sorry, i didn't post the original code :)

Here's a sample:

JavaScript:
    If Not oFSO.FileExists(sLocalLog & "\startuplog.txt") Then        'Check if log file exists
        Dim fs, f
        Set fs = CreateObject("Scripting.oFSOtemObject")
        Set f = fs.CreateTextFile(cLocalFE & \errorlog.txt", True)
        f.WriteLine strError
        f.Close
    Else
        Const ForReading = 1, ForWriting = 2, ForAppending = 3
        Dim fs, f
        Set fs = CreateObject("Scripting.oFSOtemObject")
        Set f = fs.OpenTextFile(cLocalFE & "\startuplog.txt", ForAppending, TristateFalse)
        f.WriteLine strError
        f.Close
    End If

Both file system and file objects are created with each of the clauses. In my code I took out the redundant object setting.
Okay, thanks for clarifying that. However, that code is still not setting the same object multiple times, since those lines are in a separate branch of an If/Then/Else statement. Based on the result of the If check, only one of those lines will execute; therefore, only creating one object.

By the way, is that VBA or JavaScript. I don't think you can have multiple Dim statements to declare the same variable more than once.
 

cheekybuddha

AWF VIP
Local time
Today, 09:39
Joined
Jul 21, 2014
Messages
2,280
is that VBA or JavaScript.
It's not javascript - you don't use Dim in js.

It looks like a mess of copy/paste VBA or VBS!

I don't think it's actual code (that would compile/work)

@JMongi,

You would really want to boil it down to something like:
Code:
  Dim fs As Object, f As Object
  Set fs = CreateObject("Scripting.FileSystemObject")
  Const ForReading As Integer = 1, _
        ForWriting As Integer = 2, _
        ForAppending As Integer = 3, _
        TristateFalse As Integer = 0

  If Not fs.FileExists(sLocalLog & "\startuplog.txt") Then        'Check if log file exists
    Set f = fs.CreateTextFile(cLocalFE & "\errorlog.txt", True)
  Else
    Set f = fs.OpenTextFile(cLocalFE & "\startuplog.txt", ForAppending, TristateFalse)
  End If
  f.WriteLine strError
  f.Close
(Obviously you will have needed to have declared and assigned values to variables/constants sLocalLog and cLocalFE beforehand too
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
Everyone, Thanks for the updates (and the rewrite)! I can understand the basics of object oriented programming but any time I run into a question the doubts spring up.
Sorry for the copy/paste errors. I also had a find/replace issue that you pointed out that had been corrected but not before I apparently used it in this thread! I'll paste the whole section for clarity tomorrow.

But, you did basically answer my question with your rewrite. You can use various properties of the object (fs) even if you are actually referring to different real files for those properties. In this script I was basically trying to eliminate all of the redundant file system object instantiations that seemed unnecessary. The idea being to have one piece of code near the beginning of my script...

Code:
Dim oFSO
Set oFSO = CreateObject("Scripting.FileSystemObject")

...and then use oFSO everywhere I want to use a file system object. I'm trying to review/streamline my code, especially the code blocks I reused from the internet. They often can be simplifed as you did.
 

cheekybuddha

AWF VIP
Local time
Today, 09:39
Joined
Jul 21, 2014
Messages
2,280
What about using the Property/function that you were looking at before (in this thread)?

If you have that in a module somewhere, then you need never instantiate the FileSystemObject again.

Just use FSO, so the re-written code becomes:
Code:
  Dim f As Object
  Const ForReading As Integer = 1, _
        ForWriting As Integer = 2, _
        ForAppending As Integer = 3, _
        TristateFalse As Integer = 0

  If Not FSO.FileExists(sLocalLog & "\startuplog.txt") Then        'Check if log file exists
    Set f = FSO.CreateTextFile(cLocalFE & "\errorlog.txt", True)
  Else
    Set f = FSO.OpenTextFile(cLocalFE & "\startuplog.txt", ForAppending, TristateFalse)
  End If
  f.WriteLine strError
  f.Close
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
@cheekybuddha - That is because this code is part of a script written using VB Script that will be run to launch the database, not part of the database module code itself.

It is that property/function that got me thinking about how many times objects were defined in my script. It got put together modularly, so I'm reviewing it, cleaning it up, commenting, trying to be consistent and streamline any redundant code.
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
Before I post my full script in all its ugly glory....
@cheekybuddha - Why did you add the "TristateFalse as Integer = 0" line in defining the constants? That wasn't in the sample code I saw even if the help files and whatnot list all the various enumerations.
 

cheekybuddha

AWF VIP
Local time
Today, 09:39
Joined
Jul 21, 2014
Messages
2,280
Why did you add the "TristateFalse as Integer = 0" line in defining the constants?
That's the value of that constant.

See here under 'Settings'

If this is a vbScript, then you will need to lose the As Object from the variable declarations.

You can mimic the FSO property as a function in your vbScript too.

Before I post my full script in all its ugly glory....
It would be helpful to see (y)
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
That's the only sample I've seen that enumerates everything in their sample code. Thanks for the link. I'm cleaning up the last bits we've been talking about.
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
This did work at some point but I haven't tested it after the modifications:

Rich (BB code):
'====================================================================
' Project: Company Operations Database (Office365 - Access 2019)
' Title: Company Operations Launch Script
' Filename: CompanyOpLaunch.vbs
' Creation Date: 06/10/2021
' Revision Date: 09/22/2022
' Author: jmongi
' Purpose: Launches the Company Operations Application
' Acknowledgments: Thanks to the users of AccessWorld Forums at www.access-programmers.co.uk for help with
'                    development and testing.  Users include but are not limited to theDBguy, Isaac, isladogs,
'                    gasman, cheekybuddha, arnelgp, Minty
' Module List
' --ScriptSetup:    Initialize constants, objects and variables used throughout the script
' --LocationChk:    Verify and create directory locations
' --RuntimeChk:        Checks that MS Access runtime is installed
' --WiFiChk:        Check if WiFi is in use and provide prompts
' --FileXfer:        Copy files from server location to local user
' --LaunchApp:        Launch the application automatically
' --WriteLog:        Writes a string to a specified text log file
' --ErrHandler:        Manage errors that occur
'==================================================================================================================================
Option Explicit
OnError Resume Next                                    'errors will not halt script, see ErrHandler sub
Dim sModuleName                                        'Used with ErrHandler
sModuleName = "Main Script"

Call ScriptSetup
Call LocationChk
Call FileXfer
'Call RuntimeChk
'Call WiFiChk
Call LaunchApp
Call WriteLog (sLogfile, sStartLog)

Exit Script

' Subroutine Modules
'==================================================================================================================================
Sub ScriptSetup' Script Initialization
sModuleName = "Script Initialization"

'Set Constants
Const cFE = "test.txt"                                'Front End filename
Const cIcon = "MainApp.ico"                            'Icon name
Const cServerPath = "\\XXXXX\testfolder"     'Front End Server Path
Const cLocalApp = "\CompanyOp"                        'Local App Folder Name
Const cLocalFE = "\FE"                                'Front End Local Folder Name
Const cLocalLog = "\Log"                            'Application Log Local Folder Name
Const cLocalArchive = "\Archive"                    'Applicaton Archive Local Folder Name
Const cSCName = "Company Operations"                'Shortcut name
Const cScriptName = "CompanyOpLaunch.vbs"             'Name of this script

'Scriptwide varirables

Dim sLocalApp
Dim sLocalUser
Dim sLocalFE
Dim sLocalLog
Dim sLocalArchive
Dim sStartText

'Instantiate various objects for use throughout the script
Dim oShell
Set oShell = CreateObject("WScript.Shell")
Call ErrHandler(sModuleName)

Dim oFSO
Set oFSO = CreateObject("Scripting.FileSystemObject")
Call ErrHandler(sModuleName)

'Set user variables
sLocalUser = oShell.ExpandEnvironmentStrings("%USERPROFILE%")
sLocalApp = sLocalUser & cLocalApp
sLocalFE = sLocalUser & cLocalApp & cLocalFE
sLocalLog = sLocalUser & cLocalApp & cLocalLog
sLocalArchive = sLocalUser & cLocalApp & cLocalArchive
sStartLog = Now() & " Database Launch Successful"
End Sub
'==================================================================================================================================
Sub LocationChk ()  ' Check if installation folders exist and create them if they do not exist
sModuleName = "LocationChk"

Dim aNewFolder
Dim i

aNewFolder = Array(sLocalApp, sLocalFE, sLocalLog, sLocalArchive)
For i = 0 to UBound(aNewFolder)
    If Not oFSO.FolderExists(aNewFolder) Then
        oFSO.CreateFolder (aNewFolder)
        call ErrHandler (sModuleName)
    End If
Next

End Sub
'==================================================================================================================================
Sub RuntimeChk ()  ' Checks if the appropriate Access runtime exists
'Check if Microsoft 365 Access Runtime is installed
End Sub
'==================================================================================================================================
Sub WiFiChk () ' Check if WiFi is the main connection
'Script taken from randlotech.blogspot.com/2015/05/vbscript-to-check-wireless-or-wired.html
' NAME:  Check Connection Type
' AUTHOR: Mark Randol
' DATE  : 4/29/2015
' COMMENT: this script will return
'          1 if both are in use (shouldn't happen, but can)
'          2 if wired LAN adapter is in use
'          3 if wireless LAN adapter is in use
'          4 if none of the LAN adapters are in use.
'
'Modified/updated 06/21/2021 by jmongi

Dim strComputer, strOut
Dim objWMIService, objWifi, objLAN
Dim colWiFi, colLAN
Dim state, wireStatus, wifiStatus
Dim intOutput

' Initialize Variables
sModuleName = "WiFiChk"
intOutput = 4
state = ""
strComputer = "."
Set objWMIService = GetObject("winmgmts:\\" & strComputer & "\root\CIMV2")
Call ErrHandler (sModuleName)

Set colLAN = objWMIService.ExecQuery("Select * From Win32_NetworkAdapter Where NetConnectionStatus = 2 and PhysicalAdapter = 'True'")
Call ErrHandler (sModuleName)

' Enumerate the wired adapters in WMI.  Add 1 to output if wired adapter is in use.

For Each objLAN in colLAN
    strOut = objLAN.NetConnectionID & " " & objLAN.Name & " " & objLAN.PhysicalAdapter
    if instr(lcase(objLAN.Name),"virtual") = 0 and instr(lcase(objLAN.Name),"multiplex") = 0 and  instr(lcase(objLAN.Name),"bridge") = 0 then
    ' Above line (if statement) is there to eliminate other extraneous adapters that
    ' still show up even though we are eliminating all but "physical" adapters.  Some
    ' virtual adapters are still there, Microsoft being the biggest offender.
    ' Add to the line if necessary to remove other non-physical adapters.

        if instr(lcase(objLAN.NetConnectionID),"wireless") > 0 or instr(lcase(objLAN.NetConnectionID),"wi*fi") > 0 then
            intOutput = intOutput - 2
            Call ErrHandler (sModuleName)
            Wscript.Echo(strOut & " connected.  Output is now " & intOutput)
        end if
        if instr(lcase(objLAN.NetConnectionID),"wireless") = 0 and instr(lcase(objLAN.NetConnectionID),"wi*fi") = 0 Then
            intOutput = intOutput - 1
            Call ErrHandler (sModuleName)
            Wscript.Echo(strOut & " connected.  Output is now " & intOutput)
        end if
    end if
Next


Select Case intOutput
Case 1
    Dim MboxPrompt, MboxTitle, MboxButton
    MboxPrompt = "Please disconnect from WiFi before using this application."
    MboxTitle = "WARNING - WiFi In Use"
    MboxButton = 16
    MsgBox (MboxPrompt, MboxButton, MboxTitle)
    'Log Startup Code
    Wscript.quit
Case 2
    'Do nothing and continue script
Case 3
    Dim MboxPrompt, MboxTitle, MboxButton
    MboxPrompt = "Please disconnect from WiFi and connect via ethernet cable to the local network before using this application."
    MboxTitle = "WARNING - WiFi In Use"
    MboxButton = 16
    MsgBox (MboxPrompt, MboxButton, MboxTitle)
    'Log Startup Code
    Wscript.quit
Case 4
'Code for cancel launch
'No network warning

End Sub
'==================================================================================================================================
Sub FileXfer ()        'Transfer new files from shared network location to local user
sModuleName = "FileXfer"
oFSO.CopyFile cServerPath & "\*.*", sLocalFE & "\", True        'The true flag suppresses the user prompt for overwrite
Call ErrHandler (sModuleName)

End Sub
'==================================================================================================================================
Sub LaunchApp ()    'Launch the Access Database
sModuleName = "LaunchApp"
WScript.Sleep 5000 'Pause to make sure MSAccess does not open before filecopy is finished.
Call ErrHandler (sModuleName)

WSHShell.Run cLocalFE & "\" & cSCName & ".lnk"
Call ErrHandler (sModuleName)
End Sub
'==================================================================================================================================
Sub WriteLog (ByVal LogName, ByVal WriteText)
Const ForReading = 1, ForWriting = 2, ForAppending = 8
Const TristateFalse = 0, TristateTrue = -1, TristateUseDefault = -2
Dim f
Set f=oFSO.OpenTextFile(LogName, For Appending, TristateFalse, True)
f.WriteLine WriteText
f.Close
End Sub
'==================================================================================================================================
Sub ErrHandler (ByVal ErrModule)    'Custom error handler for VBScript
If Err.Number <> 0 Then
    Const ForReading = 1, ForWriting = 2, ForAppending = 8
    Const TristateFalse = 0, TristateTrue = -1, TristateUseDefault = -2
    Dim sError, f, sLinetext, sLogfile

    'Store the error
    sError = "Error No:" & Err.Number & " - " & Err.Description & " occurred in module " & ErrModule
    Err.Clear
   
    'Notify the user of the error.
    MsgBox "An error has occurrred launching the program.  The program will attempt to recover. " _
        & "If the error occurs again, please contact your system administrator."
   
    'Log the error
    sLinetext = Now() & " " & sError
    sLogfile = cLocalLog & "\startuplog.txt"
    Call WriteLog(sLogfile, sLinetext)
End If
'==================================================================================================================================
 

cheekybuddha

AWF VIP
Local time
Today, 09:39
Joined
Jul 21, 2014
Messages
2,280
Have only skimmed a bit, but this jumps out as not quite right:
Code:
' ...
aNewFolder = Array(sLocalApp, sLocalFE, sLocalLog, sLocalArchive)
For i = 0 to UBound(aNewFolder)
    If Not oFSO.FolderExists(aNewFolder) Then
        oFSO.CreateFolder (aNewFolder)
        call ErrHandler (sModuleName)
    End If
Next
' ...
Souldn't it be:
Code:
' ...
For i = 0 to UBound(aNewFolder)
    If Not oFSO.FolderExists(aNewFolder(i)) Then
        oFSO.CreateFolder (aNewFolder(i))
' ...
Otherwise use For Each aNewfolder In Array(sLocalApp, sLocalFE, sLocalLog, sLocalArchive) and forget the counter variable.

Will check the rest later (well, it is Friday night!)
 

JMongi

Active member
Local time
Today, 04:39
Joined
Jan 6, 2021
Messages
802
No worries! That does look right. My first time using a variable array. I used that to replace a bunch of If/Else If statements.
There's some bugs in there too I've debugged through (mostly) before quitting time. Hopefully, I'll see everyone Monday. I'll probably need an assist with the last one anyway. I'ts a syntax error. I believe its on this line of code (going from memory at home...risky)

Set f=oFSO.OpenTextFile(LogName, For Appending, TristateFalse, True)
 

Gasman

Enthusiastic Amateur
Local time
Today, 09:39
Joined
Sep 21, 2011
Messages
14,301
There is no space in ForAppending ? :(

Code:
Const ForReading As Integer = 1, _
        ForWriting As Integer = 2, _
        ForAppending As Integer = 3, _
        TristateFalse As Integer = 0
 

cheekybuddha

AWF VIP
Local time
Today, 09:39
Joined
Jul 21, 2014
Messages
2,280
Ah OK, I've spotted it now!
Code:
Sub WriteLog (ByVal LogName, ByVal WriteText)
' ...
Set f=oFSO.OpenTextFile(LogName, For Appending, TristateFalse, True)
' ...

More coffee required! :coffee:
 

Users who are viewing this thread

Top Bottom