Accessing a global Module Variable in Classes?

I know this is probably an OO 101 question, but if you don't know...you don't know!

I have several Projects within my solution. They are actually Class Libraries. What I need to be able to do is access a specific variable that is defined as "Public" that resides in a Module File within my Main Project. Is this possible?

Thanks!
BlakeMcKennaAsked:
Who is Participating?
I wear a lot of hats...

"The solutions and answers provided on Experts Exchange have been extremely helpful to me over the last few years. I wear a lot of hats - Developer, Database Administrator, Help Desk, etc., so I know a lot of things but not a lot about one thing. Experts Exchange gives me answers from people who do know a lot about one thing, in a easy to use platform." -Todd S.

Kyle AbrahamsSenior .Net DeveloperCommented:
Yep.  A module is the equivalent of a static class.

You could access your module by saying:

MyModule.MyVariable
0
BlakeMcKennaAuthor Commented:
Well, I tried that and I get the following error:

"modMain is not declared. It may be inaccessible due to its protection level."
0
Kyle AbrahamsSenior .Net DeveloperCommented:
is the module declared as public?

eg:

public Module modMain
0
Cloud Class® Course: Microsoft Exchange Server

The MCTS: Microsoft Exchange Server 2010 certification validates your skills in supporting the maintenance and administration of the Exchange servers in an enterprise environment. Learn everything you need to know with this course.

BlakeMcKennaAuthor Commented:
Yes...
0
Kyle AbrahamsSenior .Net DeveloperCommented:
can you post the module and relevant code?

is the module in a different class or is an instance of it declared anywhere?
0
BlakeMcKennaAuthor Commented:
Here is the module itself (cut down version). It is not declared anywhere else. As I mentioned above, it resides within the main Project or the Startup Project. The variable I need to reference is the "strErr" variable. This is used for Error Handling purposes through out the application. It is used in the "Catch" of a Try Catch construct.

    Imports System.DirectoryServices
    Imports System.Collections

    Public Module modMain

        Public strErr As String = ""

        Public BL As New BusinessLayer.CalBusiness
        .
        .
        .
        'Program Constants
    End Module
0
Kyle AbrahamsSenior .Net DeveloperCommented:
try

Public Property strErr as String = ""

Can you access the BL or anything?
0
ArkCommented:
x = ProjectName.ModuleName.VariableName

or, better, use NameSpace
0
CodeCruiserCommented:
You would have to add reference to the main project in the DLL file but that would not work if you also want to reference the DLL in main project so simple answer to your question would be no.

A simple alternative would to be pass this variable to the DLL methods from main project.
0
ArkCommented:
May be I misunderstood smth, but IMHO it's trivial
Right click on every project, select Add Reference and add reference to MainProject
MainProject module
Public Module SharedItems
    Public x As String = "1"
End Module

Open in new window

Another project
Public Class Class1
    Public Property foo As String
        Get
            Return MainProject.SharedItems.x
        End Get
        Set(ByVal value As String)
            MainProject.SharedItems.x = value
        End Set
    End Property
End Class

Open in new window

0
BlakeMcKennaAuthor Commented:
I will give these suggestions a try tomorrow when I go back to work.

Thanks,
0
BlakeMcKennaAuthor Commented:
Well...I tried to add the MainProject to the other projects and got the following error. I understand why I got...just not sure how to tie them together. See below screen shot of error.
Screenshot.jpg
0
CodeCruiserCommented:
I pointed out that you would get this error if you try to add reference to main project in your DLL which is already referenced in your main project.
0
BlakeMcKennaAuthor Commented:
Code,

I see your post about this. Unfortunately, this variable is used in Error Handling throughout the entire application.  Passing this variable into the DLL Methods isn't an option unless I want to do a complete redesign...
0
CodeCruiserCommented:
You can add modules in DLL projects as well with this variable in and then initialize it in your main application. There would still be changes required but not as much.
0
BlakeMcKennaAuthor Commented:
I think I figured out a way. In my try catch construct, I'm returning the strRetVal (formerly strErr). I made the name more generic because it can also return a value in Functions. Here is what I mean:

The below function comes from the Business Layer.

    Public Function AddUpdateSystemSettings(cls As clsSystemSettings) As String
        Try
            strRetVal = DL.AddUpdateSystemSettings(cls)

        Catch ex As Exception
            strRetVal = "CalBusiness/AddUpdateSystemSettings() - " & ex.Message
        End Try

        Return strRetVal
    End Function

As you can see, if the call to the DataLayer (DL), which the try catch is coded the same way, is successful, the strRetVal, in this case will return either an "A" or a "C". If there is an error that occurs in the DL, it will populate the strRetVal with the error message, either way it returns a value. The logic in the UI will determine what the return value is and act accordingly.
0
ArkCommented:
Just add one more project as a storage for shared variables
0

Experts Exchange Solution brought to you by

Your issues matter to us.

Facing a tech roadblock? Get the help and guidance you need from experienced professionals who care. Ask your question anytime, anywhere, with no hassle.

Start your 7-day free trial
BlakeMcKennaAuthor Commented:
That still won't help the fact that I would have reference that in my main Project and I can't do that because my main Project would be referencing that new project. It's a double-whammy!
0
CodeCruiserCommented:
How would your above approach work with functions that return anything other than string? Or with subs?
0
BlakeMcKennaAuthor Commented:
I would have to put the variable along with a DataTable, Dataset, etc. into a collection and then parse it on the return. Not the best way I know...but viable.
0
ArkCommented:
SharedData.vbproj (contains SharedItems module or class with shared members)
===============
MainProject.vbproj -> reference to SharedData
Project1.vbproj -> reference to SharedData + MainProject
Project2.vbproj -> reference to SharedData + MainProject
Project2.vbproj -> reference to SharedData + MainProject

From any project:
SharedData.SharedItems.x = "I'm shared"
MsgBox("SharedData.SharedItems.x")
0
BlakeMcKennaAuthor Commented:
Now I think I see where your going. I will try this tomorrow when I get into work.

Thanks Ark,
0
ArkCommented:
Above sample is for child projects (Project1,2 etc) which calls mainproject's methods.
If instead your MainProject call child dlls then

SharedData.vbproj (contains SharedItems module or class with shared members)
===============
MainProject.vbproj -> reference to SharedData + Project1 + Project2 + Project3
Project1.vbproj -> reference to SharedData
Project2.vbproj -> reference to SharedData
Project2.vbproj -> reference to SharedData

i.e. all projects have reference to SharedData project plus another project(s) as needed. Note that circular references aren't allowed (Main->Project1 and Project1->Main)
0
BlakeMcKennaAuthor Commented:
Ark,

I've done what you said and so far it's working, however, I have an issue with a variable that I have declared as Public (it's a boolean variable) within this new Project, which is a Class Library. This particular variable is set one time when the program starts.

When the code executes that checks this value, the value is false when it should be true. I'm not sure what I'm doing wrong here. Below is the layout of the code and where it is called.

This is the new Class Library.

    Imports System.Windows.Forms
Imports System.Windows.Forms.VisualStyles

Public Class ErrorHandler

    Private gSBR As StatusStrip

    Public gSplashTimer As Integer = 0
    Public gElapsedTime As Integer = 0
    Public gMessageTimer As Integer = 0
    Public gFlashMessage As Integer = 0

    Public gblnMessageTimer As Boolean = False                              'Variable in question
    Public gblnPause As Boolean = False

    Public strRetVal As String = ""

    Private tmrMessage As New Timer

    Public Sub New()
        gblnMessageTimer = False
        gblnPause = False
    End Sub
    '
    '
    '
    Public Sub ProcessMessages(ByVal frm As Form, ByVal sbr As StatusStrip, ByVal strMsg As String)
        Dim arr() As String

        Try
            gSBR = sbr

            arr = Split(strMsg, "~")

            If arr(0).Length > 0 Then
                If gblnMessageTimer = True Then                               'Only place where variable is checked.
                    If arr(0) = "ESC - Close Form" Then
                        tmrMessage.Stop()
                        gblnPause = False
                        gSBR.Visible = True
                    Else
                        If gFlashMessage = True Then
                            tmrMessage.Start()
                            tmrMessage.Interval = gMessageTimer
                        End If
                        frm.Controls.Add(gSBR)
                        If gSBR.Items.Count = 0 Then
                            gSBR.Items.Add("")
                            gSBR.Items(0).TextAlign = ContentAlignment.Center
                        End If
                        Beep()
                    End If

                    If arr(1) = "I" Then
                        gSBR.Items(0).Text = "User Notification - " & arr(0)
                    ElseIf arr(1) = "E" Then
                        gSBR.Items(0).Text = "System Error - " & arr(0)
                    End If

                    Exit Sub
                Else
                    If arr(1) = "I" Then
                        MessageBox.Show(arr(0), "User Notification", MessageBoxButtons.OK, MessageBoxIcon.Exclamation)
                    ElseIf arr(1) = "E" Then
                        MessageBox.Show(arr(0), "System Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
                    End If
                End If
            Else
                If Not frm.Name = "frmMain" Then
                    If gSBR.Items.Count = 0 Then
                        gSBR.Items.Add(New ToolStripStatusLabel)
                    End If
                    gSBR.Items(0).Text = "ESC - Close Form"
                    gSBR.Items(0).TextAlign = ContentAlignment.Center
                    gSBR.Items(0).AutoSize = StatusBarPanelAutoSize.Spring
                    tmrMessage.Stop()
                    gblnPause = False
                    gSBR.Visible = True
                End If
            End If

        Catch ex As Exception
            strRetVal = "modMain/ProcessMessages() - " & ex.Message & "~E"
            MessageBox.Show(strRetVal, "System Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
        End Try
    End Sub
End Class


This is a SubProcedure within a Module file residing in the Main Project.
       
    Private EH As New ErrorHandling.ErrorHandler

        Public Sub ApplySysSettings()
        Try
            Dim strSysSettings As String = ""
            Dim arr() As String

            strSysSettings = BL.GetSysSettings
            arr = Split(strSysSettings, ",")

            If arr(0).Length > 0 Then
                gTimeOut = arr(0) * 60000       'Measured in minutes
                EH.gSplashTimer = arr(1) * 1000    'Measured in seconds
                EH.gMessageTimer = arr(3) * 100    'Measured in milliseconds
                EH.gblnMessageTimer = CBool(arr(4))                                  'Only time variable is set
                EH.gFlashMessage = CBool(arr(5))

                If CBool(arr(2)) = True Then
                    frmMain.ts1.Visible = False
                Else
                    frmMain.ts1.Visible = True
                End If
            End If

        Catch ex As Exception
            EH.strRetVal = "modMain/ApplySysSettings() - " & ex.Message & "~E"
        End Try
    End Sub
0
BlakeMcKennaAuthor Commented:
Any ideas on this?
0
CodeCruiserCommented:
Does it work if you make it static?
0
BlakeMcKennaAuthor Commented:
Thanks Ark...why I never thought of this is beyond me!
0
ArkCommented:
Glad I could help
If u'r using Class then declare your variable as Shared (aka static in C#). If u'r using module - leave it Public - module is smth like 'Shared' class.
0
BlakeMcKennaAuthor Commented:
I didn't know that...why shared?
0
ArkCommented:
You can access class members through instance or type. Ex1.
Public Class MyClass
      'Non-shared
      Public x As Double
      Public Property y As String
      Public Function z() As Integer
End Class
To access vars/props/methods you need an instance of class, ie:
Dim cls As New MyClass 'create a new instance of class
cls.x = 1.2345
cls.y = "Non shared class"

Ex2:
Public Class MyClass
      'Shared
      Public Shared x As Double
      Public Shared Property y As String
      Public Shared Function z() As Integer
End Class

In this case you don't need instance, just a type;
MyClass.x = 1.2345
MsgBox(MyClass.y)

Ex3:
Public Class MyClass
      'Shared vs Non-shared
      Public Shared x As Double
      Public Property y As String
End Class
MyClass.x = 1.2345
'but
Dim cls As New MyClass: cls.y="abc"

VB modules serve like 'shared' class - all module members are shared without explicit declaration.
0
It's more than this solution.Get answers and train to solve all your tech problems - anytime, anywhere.Try it for free Edge Out The Competitionfor your dream job with proven skills and certifications.Get started today Stand Outas the employee with proven skills.Start learning today for free Move Your Career Forwardwith certification training in the latest technologies.Start your trial today
Visual Basic.NET

From novice to tech pro — start learning today.