Link to home
Start Free TrialLog in
Avatar of ShineOn
ShineOnFlag for United States of America

asked on

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

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!
Avatar of ste5an
ste5an
Flag of Germany image

Well, add a LoadConfiguration(string fileName) method to load an arbitrary settings file using the ConfigurationManager class.
Avatar of ShineOn

ASKER

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.
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
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

Avatar of ShineOn

ASKER

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.
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?
"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.
Avatar of ShineOn

ASKER

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?
You should already have a class in your library code, otherwise you have nothing to use.
Avatar of ShineOn

ASKER

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.
ASKER CERTIFIED SOLUTION
Avatar of ste5an
ste5an
Flag of Germany image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of ShineOn

ASKER

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?
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.
Avatar of ShineOn

ASKER

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!