Solved

Need to read settings from a file in vb.net class lib

Posted on 2015-01-08
14
239 Views
Last Modified: 2015-01-16
I am modifying an existing program which is a standalone class library exposed to COM, for reference by MS-Access VBA.

The program has several hard-coded variables in the classes which I want to be able to load from a file.

Since it is a class library and not a start program, app.config can't be used, because class libraries defer to the app.config values from the calling exe.  

Since ms-access VBA doesn't have .net app.config capability, I need to be able to read from an external file that is not part of the managed-code world.

Can anyone point me to workable examples of code snippets to accomplish this file read from a class library process?  It has to read the file at the time the library is invoked, so the variables get set before the functions are called.

Thanks!
0
Comment
Question by:ShineOn
14 Comments
 
LVL 33

Expert Comment

by:ste5an
ID: 40540401
Well, add a LoadConfiguration(string fileName) method to load an arbitrary settings file using the ConfigurationManager class.
0
 
LVL 35

Author Comment

by:ShineOn
ID: 40540800
intellisense says that LoadConfiguration isn't a member of System.Configuration.ConfigurationManager.  Do you have a code snippet to show what you mean?

I read somewhere that if you use the office tools you can use a settings file, but I haven't found quick & easy documentation on that, and I haven't done any office-specific programming... and I also saw (but don't recall where) code samples of how to read settings from a not-managed-code-app.config file, which is what I'm shooting for seeing as Access VBA, as far as I'm aware, wouldn't invoke an app.config to load settings to a COM-enabled DLL it's referencing.
0
 
LVL 79

Expert Comment

by:David Johnson, CD, MVP
ID: 40541020
hard-coded variables in the classes which I want to be able to load from a file.


When a program is compiled a hard-coded variable is changed to a pointer to a location that holds the variable contents
0
Migrating Your Company's PCs

To keep pace with competitors, businesses must keep employees productive, and that means providing them with the latest technology. This document provides the tips and tricks you need to help you migrate an outdated PC fleet to new desktops, laptops, and tablets.

 
LVL 40
ID: 40541654
Define static (Shared) variables and initialize them in a static constructor.

Public Class YourClass

	Public Shared YourVariable As Integer

	Shared Sub New()
		YourVariable = 10    'Replace this by reading in a file where you defined the values of the variables
	End Sub

End Class

Open in new window


The static constructor is called automatically when you use the class in any way for the first time, so the following line is sufficient to retrieve your variable value. You do not even need to instantiate an object, simply call the variable on the class:

result = YourClass.YourVariable

Be careful however. If you do instantiate objects on the class, they all share the same variable. If you change the value of the variable from one of the objects, you change it for all the other objects.  To prevent that, you can declare the variable as private and define a ReadOnly property to access its value:

Public Class YourClass

	Private Shared YourVariable As Integer

	Shared Sub New()
		YourVariable = 10	'Replace this by reading in a file where you defined the values of the variables
	End Sub

	Public ReadOnly Property YourProperty As Integer
		Get
			Return YourVariable
		End Get
	End Property

End Class

Open in new window

0
 
LVL 35

Author Comment

by:ShineOn
ID: 40541665
What I am doing is taking a class lib which is used by an executable program, and chopping out just the one class that is needed to be referenced from an ms-access VBA to perform a few functions that cannot easily be written in vba, specifically the creation of an xml soap file to put to a web service to update a separate system.

The exe that uses the class lib accesses that system and pushes info into the postgreSQL linked tables in the ms-access app, in addition to running some evaluations on the postgreSQL tables and pushing automated updates to the external code.

The class lib the exe uses has variables which are set by the exe's app.config - connection string, web service url, login information for the web service, paths to work folders for the xml soap files which are built, to xml templates, to response files from the web service request, to the log writer, to the smtp server address for email notifications and the like.

Some of those values are not needed in the class I am creating for the outbound xml push functions for the vba app, but some are - and since ms-access vba doesn't play nice with .net (unless I missed the memo) unlike excel or word where you can put an app config file in the excel or word path and have that provide the app config to ConfigurationManager for the class lib, I am looking for an alternative to replace that for this particular scenario.  The reason for wanting to feed this info from a file is the usual - so testing can use test-environment values and production implementation can use production-environment values, without having to create both a test and prod version of the code and maintain a duplicate set of slightly different executables and libraries.

This application is not likely to be around forever, so I don't even want to look at reading configuration data from a database.

Oh, for the days of DLL hell and .ini files... ;)

The path I am currently exploring is using the project settings to set the variables' values, which should (if I can do it right) generate a dll-specific config file.
0
 
LVL 75

Expert Comment

by:käµfm³d 👽
ID: 40542253
intellisense says that LoadConfiguration isn't a member of System.Configuration.ConfigurationManager.
What version of .NET does your library target, and is it one of the Client Profiles?
0
 
LVL 33

Expert Comment

by:ste5an
ID: 40543939
"add a LoadConfiguration" means that you need to create a public method in the COM-visible code to tell your library what file it should load. In this method you can use the ConfigurationManager to use standard XML configuration files.
0
 
LVL 35

Author Comment

by:ShineOn
ID: 40544820
kaufmed, I am targeting .Net 4.5.1.  Client profiles have been discontinued starting with 4.5, according to devnet.

ste5an, do you have a code snippet or a devnet article you can point me to?  I'm not clear on how to implement a class that will make ConfigurationManager not expect the library to be inheriting the config file from an app.

Any thoughts on the use of settings.settings?
0
 
LVL 33

Expert Comment

by:ste5an
ID: 40544826
You should already have a class in your library code, otherwise you have nothing to use.
0
 
LVL 35

Author Comment

by:ShineOn
ID: 40545017
Of course I have a class in my library code.   I guess I misunderstood, because you're "speaking" in short bursts with background info omitted because you're assuming that everyone should know what you know.  That's why I'm asking - because I don't.  "Back in my day," Experts were expected to be more verbose and helpful  when giving their advice.

I thought you were saying I needed to create a class for this LoadConfiguration method.  Are you saying I just add a new com-exposed method to my existing class?  How will that method be called to bypass the normal, app-inherited config?  Why should it be COM-exposed?  Shouldn't it be declared shared?  Do you have any code examples to explain what you're trying to say?

I assumed "another class" because that's what some of the articles I've read have suggested, to create a "data reader" class in the same project.  Problem is, many of these articles are written for C# and not VB, so their examples don't necessarily apply, and I don't know enough C# to be able to translate the syntax even if they did.
0
 
LVL 33

Accepted Solution

by:
ste5an earned 500 total points
ID: 40546473
E.g.

Imports ClassLibrary1

Module Module1

    Sub Main()

        Const CONFIG_PATH As String = "C:\Temp\myClass1.config"

        Dim myClass1 As Class1 = New Class1

        Console.WriteLine("From Library: " & myClass1.DoSomething)

        myClass1.LoadConfiguration(CONFIG_PATH)
        Console.WriteLine("From Library: " & myClass1.DoSomething)

        Console.WriteLine("Done.")
        Console.ReadLine()

    End Sub

End Module

Open in new window


with

 
Imports System.Configuration

Public Class Class1

    Private someMember As String = "default"

    Public Function DoSomething() As String

        DoSomething = Me.someMember

    End Function

    Public Sub LoadConfiguration(configFile As String)

        Const SECTION_NAME As String = "MySection"

        Dim fileMap As ConfigurationFileMap = New ConfigurationFileMap(configFile)
        Dim configuration As Configuration = ConfigurationManager.OpenMappedMachineConfiguration(fileMap)
        Dim section As AppSettingsSection = CType(configuration.GetSection(SECTION_NAME), AppSettingsSection)

        someMember = section.Settings.Item("myKey").Value

    End Sub

End Class

Open in new window


and

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
	<configSections>
		<section  name="MySection" type="System.Configuration.AppSettingsSection" />
	</configSections>
	<MySection>
		<add key="myKey" value="myValue" />
	</MySection>
</configuration>

Open in new window

0
 
LVL 35

Author Comment

by:ShineOn
ID: 40550028
Thanks for the examples,  ste5an.

So I need to create a module in my class lib project, which will do the loadConfiguration event, and that module will call a subroutine in the class lib vb which defines the loadConfiguration method?  Or am I reading it wrong?

Can I assume that the sub main() in the new module means it will run whenever the class lib is invoked, forcing the reading of the configuration from file?
0
 
LVL 33

Expert Comment

by:ste5an
ID: 40550046
No, you don't create a new module. My Class1 is your COMVisible library class. You just add the LoadConfig method to load an arbitrary config file. The LoadConfig() method is called in VBA/Access.
0
 
LVL 35

Author Closing Comment

by:ShineOn
ID: 40554471
Thanks, ste5an!

The config is loaded from the external program call to the new method, not on class lib first use, so it's not exactly what I was looking for, but it should work!
0

Featured Post

Gigs: Get Your Project Delivered by an Expert

Select from freelancers specializing in everything from database administration to programming, who have proven themselves as experts in their field. Hire the best, collaborate easily, pay securely and get projects done right.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

A simple tool to export all objects of two Access files as text and compare it with Meld, a free diff tool.
Although it can be difficult to imagine, someday your child will have a career of his or her own. He or she will likely start a family, buy a home and start having their own children. So, while being a kid is still extremely important, it’s also …
In Microsoft Access, learn the trick to repeating sub-report headings at the top of each page. The problem with sub-reports and headings: Add a dummy group to the sub report using the expression =1: Set the “Repeat Section” property of the dummy…
In Microsoft Access, learn how to use Dlookup and other domain aggregate functions and one method of specifying a string value within a string. Specify the first argument, which is the expression to be returned: Specify the second argument, which …

776 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question