Link to home
Start Free TrialLog in
Avatar of gregasm
gregasm

asked on

non-traditional App.config needed

Hi,

I am deploying an assembly that is configured at runtime from an app.config file.

The app.config file is named after the entry point EXE like:  myexe.exe.config

I would like to do away with the current config file and either embed the config file as an embeded resource, or otherwise hide it. Does anyone know how this is done?

Thanks
Avatar of mmarinov
mmarinov

Hi gregasm,

i think that is will be much easy if you use registry,  isn't it ?

B..M
Avatar of gregasm

ASKER

No registry.

It is configuration information that I need to read from somewhere....

looks like this:

<configuration>
      <configSections>
            <section
                  name="uipConfiguration"
                  type="Microsoft.ApplicationBlocks.UIProcess.UIPConfigHandler,  Microsoft.ApplicationBlocks.UIProcess, Version=1.0.1.0,Culture=neutral,PublicKeyToken=null" />
    </configSections>
   
    <uipConfiguration>
        <objectTypes>
                  <iViewManager
                        name="WizardViewManager"
                        type="Microsoft.ApplicationBlocks.UIProcess.WizardViewManager, Microsoft.ApplicationBlocks.UIProcess, Version=1.0.1.0,Culture=neutral,PublicKeyToken=null"
                        />
            <state ....


I'd like this to not be appname.exe.config.. but rather... embedded in the dll or exe as a embedded resource?

Even put in sql server is better than being a file outside sitting in the deployment directory
i'm not sure it can be done as i've searched for this too
if there is a solution it will be helpfull to me aslo

B..M
Avatar of gregasm

ASKER

Look at this link:

http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnpag/html/uipab-ch04.asp

And in table 4.2, it says:

Attack techniques The attacker deploys malicious assemblies on the client and alters the configuration file to force UIP to load the malicious assemblies. The attacker can then take control of the workflow.  

Countermeasures Use the Configuration Management Application Block (CMAB) to increase the level of protection for the configuration file needs.

*****Specify another resource, such as the SQL Server computer, to provide the configuration information, instead of the traditional ExecutableAssemblyName.exe.config. *****


The line with the asterisks suggests that it IS possible, but afterwards, does not say how...
 
the CMAB is not embeded the config file, but what it is doing is to store the configuration properties not in web config but in the database, but you have to declared which will the assemblies that will catch those configuration properties

in my case use CMAB and it is working GREAT
download it and see the examples and help that is provided

B..M
Avatar of gregasm

ASKER

Well, I should have editied any reference to CMAB out of the previous post.  I read up on the CMAB documentation, and it is quite clear that CMAB is not necessary to store the config file and retrieve it from somewhere else, other than from within the same directory, named myexe.exe.config.

I am glad that I don't HAVE to use CMAB because that would introduce more dependencies to my project.

How can I do it without using CMAB? That is the question. Thanks,
ASKER CERTIFIED SOLUTION
Avatar of mmarinov
mmarinov

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 gregasm

ASKER

Hey thanks for writing in this thread! I will definitely let you know when I find out how it is done.
Dumb question, why not create a private class in your project full of configuration properties, and reference static constants from that class?   This way at least you'll have all config information in one place, and it'll be compiled into your application.
Avatar of gregasm

ASKER

The configuration file does more than store name value pairs. Please make sure you understand the question fully first.
If you do not want your config to be in a text file, you can use a database like MS Access, SQL Server or MSDE. You actually store the entire config to a single table field which uses a data type that supports the storage and retrieval of large amounts of data (like text, ntext, memo, image, blobs, etc.). You can encrypt the config when you store to your database then decrypt it when you retrieve from your database.

Since the traditional .config file is supported by the runtime, your config in your database must be manually loaded. That brings up some extra work but consider that it also means you can create your own XML schema for the config. You can more or less base the structure on the structure of the traditional .config if you like.

Of course, you must create your own config parser/loader class. The power of having your own config schema and parser/loader is that you can deploy configurations that are consumed by .exe and/or .dll assemblies (traditional .config does not support loading from .dll). This is important in my experience when working with .Net and COM+ where you deploy only .dll files.

After you've retrieved, decrypted and loaded the config from the database to say a text/stream object, process it using your config parser/loader. If memory permits, you can achieve all of these without having to write the config to a file. Also, if memory permits, you can store/cache the entire parsed/loaded config in memory during the entire application lifetime.

Caching is an important factor when optimizing for performance and resource utilization especially when you reach that point when some configurations may be shared by the many applications running on the same machine. You can follow the caching technique in CMAB, CAB or you can create your own.

Have fun.
Have a look at this sample that may give you some hints:
http://www.theserverside.net/discussions/thread.tss?thread_id=25076

If all you want is to store your own user settings, a suggestion is to simply use a DataSet (persisted as a simple .xml file) and then just add it as a resource to your assembly, and in runtime just read it.

Something like:
config.xml
<MyConfig>
  <IAmASetting>Set me</IAmASetting>
</MyConfig>

mylib.cs:
// compile with: csc /t:library mylib.cs /res:config.xml,config.xml
using System;
using System.Data;
using System.Diagnostics;

public class SomeClass
{
      private DataSet sett = null;

      public SomeClass()
      {
            sett = new DataSet();
            sett.ReadXml( System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream( "config.xml" ) );
      }

      public string GimmeTheSetting( string Setting )
      {
            return sett.Tables[ "MyConfig" ].Rows[0][ Setting ].ToString();
      }
}

myapp.cs
// compile: csc myapp.cs /r:mylib.dll
using System;

class App
{
      public static void Main()
      {
            SomeClass slc = new SomeClass();
            Console.WriteLine( slc.GimmeTheSetting( "IAmASetting" ) );
      }
}


If you want to get fancier, than just have a class xml serializable and use the XmlSerializer to deserialize it into an object.

Note that storing the config file in the assembly is a one way travel, you can read, but you cannot edit it, you'll need to recompile. (that's actually not totally correct, but you'll want to recompile)

hth

Vasco
Check the following tutorial where it is described how to embed .manfiest file in your .exe or DLL. The same logic you can apply for your app.config files.

http://www.codeproject.com/csharp/dotnetvisualstyles.asp

Best, Nauman.
I don't think that will work for config files.
Have you actually tried it and it worked ? (i'm not picking on you, but i would be really surprised (positively:) if it did)

I think that manifests are an XP OS feature. They have a schema of their own. Mostly, i believe it's used by the OS Loader (as it is when you want XP styles, which is effect redirects the loading of one dll to another) to do side-by-side config.

I would be interested to know if this works with your .config files.

Vasco
SOLUTION
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
SOLUTION
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
SOLUTION
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 gregasm

ASKER

I must not have explained myself clearly, or else the concept is fuzzy?

If I embed the app.config file into the assembly then how will that affect the built in .net parsing of the config file?
Unfortunately i don't think the resource will be picked up at all, meaning that your config file won't be parsed.

Avatar of gregasm

ASKER

As I suspect, vascov. So how can I put the xml in the app.config into a different place, and tell the runtime, "hey, this isn't what you normally expect, but I want you to look here and treat this xml like the way you treat app.config"
You can specify a different config file name when creating a new app domain, but i think that it still has to be a file somewhere, which at the end of the day doesn't help much.
If you're only interested in appSettings (or your own config sections) stuff, you can use other mechanisms.
SOLUTION
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 gregasm

ASKER

Thanks vascov and ihenry.

The last posting is interesting, and I'd like to read up more on it. Can you point me to where you got this information, iHenry?
Oops sorry, pasted wrongly. I mean this one

      #region IConfigurationSectionHandler Members
      public object Create( object parent, object configContext, XmlNode section )
      {
            section = LoadXmlFromResourceAssembly();
            ...
            ...
            // continue parsing here
      }
      #endregion
Tell you frankly, I stole the idea from CMB :o)
Ok, what you need to do with my suggestion is actually similar with creating a simple custom handler. But in the Create method, section parameter return value is myCustomConfig XmlNode (see my previous post) that's nothing to do with your actual configuration settings. So replace this value with XmlNode returned from a function (LoadXmlFromResourceAssembly) that gets the config settings from resource assembly.

In case you need information on how to create a custom configuraiton handler you can read this article,
Creating Custom Configuration Settings in ASP.NET
http://www.devx.com/dotnet/Article/16927/0/page/1

And to retrieve xml file from resource assembly using ResourceManager class or in CMAB you can find one internal class named Resource, it's pretty useful class to load resource from assembly (need some modification).

And something similar with my suggestion
Custom ConfigurationSettings through configuration resource embedding
http://www.codeproject.com/csharp/nemeserc.asp
iHenry, great links.
Note that thay do essentially what i posted earlier (http://www.theserverside.net/discussions/thread.tss?thread_id=25076) (wraps data in some format as a resource and then unwraps it during runtime), and still only applies to custom settings. (.NET settings like system.diagnostics, etc... will NOT be picked up).

Greg, exactly which settings are you trying to "embed" ?

Vasco
Which all points to the fact that if you want a non-traditional .config, you can create your own schema and empower it with your own configuration parser/loader.

So far, the direction is to suggest a place to store the .config but how you access it is the same: you'll load it with your own configuration parser/loader class.

Have fun.
Avatar of gregasm

ASKER

I am trying to embed settings like this:

<configuration>
     <configSections>
          <section
               name="uipConfiguration"
               type="Microsoft.ApplicationBlocks.UIProcess.UIPConfigHandler,  Microsoft.ApplicationBlocks.UIProcess, Version=1.0.1.0,Culture=neutral,PublicKeyToken=null" />
    </configSections>
   
    <uipConfiguration>
        <objectTypes>
               <iViewManager
                    name="WizardViewManager"
                    type="Microsoft.ApplicationBlocks.UIProcess.WizardViewManager, Microsoft.ApplicationBlocks.UIProcess, Version=1.0.1.0,Culture=neutral,PublicKeyToken=null"
                    />
            <state ....


Those are much more complicated than

<add key="crud" value="myvalue"/>

Well at any rate, I am thinking I am gonna drop the UIP block and make my own. UIP is great, but I don't need all the features it provides... and plus, this configuration stuff is driving me cragee.

UIP has its own configuration handler, why don't just use it?
Avatar of gregasm

ASKER

I am using it.

The UIP config handler is great, except that it expects the config file to be named myexe.exe.config

I want to point the config handler to either another file, or another source while still retaining the UIP config handler functionality.

Forget it. I appreciate everyone's help, but this is going nowhere.

If you have already code that loading xml file from resource assembly, the next would be a little step, I believe. Anyway, you are giving up...
Avatar of gregasm

ASKER

Here is the solution to my question:

Create an xml file and embed it as a resource. In the application Main method, read the xml into an xml document, then get a reference to the xml node that contains the configuration information.

Pass the xml node to the constructor of the UIPConfigSettings object...
~Voila~.... Now I did away with the unsightly App.Config and packed it as a resource. This method would also work if I put it anywhere else, db, secure location, from a web service even... anything.

Here's the code.

---------------------------------

Private Sub LoadConfigXml()
      Try
         'Dim configFilePath As String = System.Reflection.Assembly.GetExecutingAssembly().Location & ".config"
         Dim strXml As String =Utils.GetConfigXml()
         Dim xmldoc As New Xml.XmlDocument
         xmldoc.LoadXml(strXml)
         Dim xmlNode As Xml.XmlNode = xmldoc.SelectSingleNode("/configuration/uipConfiguration")
         Microsoft.ApplicationBlocks.UIProcess.UIPConfiguration.Config = New UIPConfigSettings(xmlNode)
      Catch ex As Exception
         Throw New Exception("Could not read Config Xml", ex)
      End Try
   End Sub

   Friend Shared Function GetConfigXml() As String
      Dim strm As IO.Stream
      Dim reader As IO.StreamReader
      Try
         Dim strResource As String = "some.namespace.Config.xml"
         Dim ass As Reflection.Assembly = System.Reflection.Assembly.GetExecutingAssembly()
         strm = ass.GetManifestResourceStream(strResource)
         reader = New IO.StreamReader(strm)

         Return reader.ReadToEnd()

      Catch ex As Exception
         Throw ex
      Finally
         If Not reader Is Nothing Then
            reader.Close()
         End If
      End Try

   End Function