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
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
ASKER
No registry.
It is configuration information that I need to read from somewhere....
looks like this:
<configuration>
<configSections>
<section
name="uipConfiguration"
type="Microsoft.Applicatio nBlocks.UI Process.UI PConfigHan dler, Microsoft.ApplicationBlock s.UIProces s, Version=1.0.1.0,Culture=ne utral,Publ icKeyToken =null" />
</configSections>
<uipConfiguration>
<objectTypes>
<iViewManager
name="WizardViewManager"
type="Microsoft.Applicatio nBlocks.UI Process.Wi zardViewMa nager, Microsoft.ApplicationBlock s.UIProces s, Version=1.0.1.0,Culture=ne utral,Publ icKeyToken =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
It is configuration information that I need to read from somewhere....
looks like this:
<configuration>
<configSections>
<section
name="uipConfiguration"
type="Microsoft.Applicatio
</configSections>
<uipConfiguration>
<objectTypes>
<iViewManager
name="WizardViewManager"
type="Microsoft.Applicatio
/>
<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
if there is a solution it will be helpfull to me aslo
B..M
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...
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
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
in my case use CMAB and it is working GREAT
download it and see the examples and help that is provided
B..M
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,
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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.
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.
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 .GetExecut ingAssembl y().GetMan ifestResou rceStream( "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
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
}
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.
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
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
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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?
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.
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.
If you're only interested in appSettings (or your own config sections) stuff, you can use other mechanisms.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
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?
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 IConfigurationSectionHandl er Members
public object Create( object parent, object configContext, XmlNode section )
{
section = LoadXmlFromResourceAssembl y();
...
...
// continue parsing here
}
#endregion
#region IConfigurationSectionHandl
public object Create( object parent, object configContext, XmlNode section )
{
section = LoadXmlFromResourceAssembl
...
...
// 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 (LoadXmlFromResourceAssemb ly) 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
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
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.
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.
ASKER
I am trying to embed settings like this:
<configuration>
<configSections>
<section
name="uipConfiguration"
type="Microsoft.Applicatio nBlocks.UI Process.UI PConfigHan dler, Microsoft.ApplicationBlock s.UIProces s, Version=1.0.1.0,Culture=ne utral,Publ icKeyToken =null" />
</configSections>
<uipConfiguration>
<objectTypes>
<iViewManager
name="WizardViewManager"
type="Microsoft.Applicatio nBlocks.UI Process.Wi zardViewMa nager, Microsoft.ApplicationBlock s.UIProces s, Version=1.0.1.0,Culture=ne utral,Publ icKeyToken =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.
<configuration>
<configSections>
<section
name="uipConfiguration"
type="Microsoft.Applicatio
</configSections>
<uipConfiguration>
<objectTypes>
<iViewManager
name="WizardViewManager"
type="Microsoft.Applicatio
/>
<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?
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.
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...
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 .GetExecut ingAssembl y().Locati on & ".config"
Dim strXml As String =Utils.GetConfigXml()
Dim xmldoc As New Xml.XmlDocument
xmldoc.LoadXml(strXml)
Dim xmlNode As Xml.XmlNode = xmldoc.SelectSingleNode("/ configurat ion/uipCon figuration ")
Microsoft.ApplicationBlock s.UIProces s.UIPConfi guration.C onfig = 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 .GetExecut ingAssembl y()
strm = ass.GetManifestResourceStr eam(strRes ource)
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
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
Dim strXml As String =Utils.GetConfigXml()
Dim xmldoc As New Xml.XmlDocument
xmldoc.LoadXml(strXml)
Dim xmlNode As Xml.XmlNode = xmldoc.SelectSingleNode("/
Microsoft.ApplicationBlock
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
strm = ass.GetManifestResourceStr
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
i think that is will be much easy if you use registry, isn't it ?
B..M