First, you need a <configSections> to identify your sections and the
types and assemblies that know how to read your sections, something
like this:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section
name="features"
type="MySample.FeatureSection, MyAssembly" />
</configSections>
You could have multiple <section> definitions.
That is followed by instances of the sections, like this:
<features>
<feature
name="Client"
title="My Sample Client"
description="An example"
status="Installing Client tools"
productcode="{345BC2AA-A7C1-44c8-9653-AC355E744D8E}"
command="msiexec"
arguments="-i SetupClient.msi "TARGETDIR={0}"" />
<feature
name="Server"
title="My Sample Server"
description="This is a sample"
status="Installing Server"
productcode="{BCD2C3AA-78CB-4662-ABCF-33D53CAADF58}"
command="msiexec"
arguments="-i SetupScheduler.msi "TARGETDIR={0}"
DEFQUAL="/INSTANCE={1}""
requiresmsmq="true"
requiressql="true"/>
</features>
</configuration>
In your "MyAssembly" assembly, you have to define the section, like
this:
using System;
using System.Collections;
using System.Configuration;
using System.Text;
namespace MySample
{
/// <summary>
/// The FeatureSection class is the starting point for the
features section of
/// our application configuration file. This is a very simple
class because it just
/// needs to identify and return the default collection which is a
FeatureCollection.
/// </summary>
public sealed class FeatureSection : ConfigurationSection
{
public FeatureSection()
{
}
[ConfigurationProperty("", IsDefaultCollection = true)]
public FeatureCollection Features
{
get
{
return (FeatureCollection)base[""];
}
}
}
}
Then, you have to define the FeatureCollection (or PluginCOllection
etc.), like this:
using System;
using System.Collections;
using System.Configuration;
using System.Text;
namespace MySample
{
public sealed class FeatureCollection :
ConfigurationElementCollection
{
public override ConfigurationElementCollectionType CollectionType
{
get
{
return ConfigurationElementCollectionType.BasicMap;
}
}
protected override ConfigurationElement CreateNewElement()
{
return new FeatureElement();
}
protected override ConfigurationElement
CreateNewElement(string elementName)
{
return new FeatureElement(elementName);
}
protected override object GetElementKey(ConfigurationElement
element)
{
return ((FeatureElement)element).Name;
}
protected override string ElementName
{
get
{
return "feature";
}
}
}
}
And finally, define the Feature element, like this:
using System;
using System.Collections;
using System.Configuration;
using System.Text;
namespace MySample
{
/// <summary>
/// The FeatureElement class defines the syntax and options that
can be specified in the
/// <Feature> element in the application configuration file.
/// Each <Feature> element defines one feature that the user
can select to install.
/// </summary>
public sealed class FeatureElement : ConfigurationElement
{
public FeatureElement()
{
}
public FeatureElement(string newName)
{
Name = newName;
}
public FeatureElement(string newName, string newDescription,
string newCommand)
{
Name = newName;
Description = newDescription;
Command = newCommand;
}
/// <summary>
/// The name attribute is required and must be unique within
the collection.
/// </summary>
[ConfigurationProperty("name", IsRequired = true, IsKey = true)]
public string Name
{
get
{
return (string)this["name"];
}
set
{
this["name"] = value;
}
}
/// <summary>
/// The title attribute specifies the text that is in the
feature selection list box.
/// </summary>
[ConfigurationProperty("title", IsRequired=true)]
public string Title
{
get
{
return (string)this["title"];
}
set
{
this["title"] = value;
}
}
/// <summary>
/// The status attribute specifies the text that is displayed
when the feature
/// is being executed. If the text isn't defined, the title
is used.
/// </summary>
[ConfigurationProperty("status", IsRequired = false)]
public string Status
{
get
{
string returnString = (string)this["status"];
if (returnString.Length == 0)
{
returnString = (string)this["description"];
}
return returnString;
}
set
{
this["status"] = value;
}
}
/// <summary>
/// The description attribute specfies the text that is
displayed under the feature
/// selection list box when the feature is the selected
(checked or not).
/// </summary>
[ConfigurationProperty("description", IsRequired = false)]
public string Description
{
get
{
return (string)this["description"];
}
set
{
this["description"] = value;
}
}
/// <summary>
/// The command attribute specifies the command that is
executed to install the feature.
/// You specify either the command or the download URL.
/// </summary>
[ConfigurationProperty("command", IsRequired = false)]
public string Command
{
get
{
return (string)this["command"];
}
set
{
this["command"] = value;
}
}
/// <summary>
/// The arguments attribute specifies the arguments passed to
the command.
/// You can use "{0}" where you want the target directory
substituted.
/// </summary>
[ConfigurationProperty("arguments", IsRequired = false)]
public string Arguments
{
get
{
return (string)this["arguments"];
}
set
{
this["arguments"] = value;
}
}
/// <summary>
/// The sourcefile attribute is used when the command is "copy"
/// </summary>
[ConfigurationProperty("sourcefile", IsRequired = false)]
public string SourceFile
{
get
{
return (string)this["sourcefile"];
}
set
{
this["sourcefile"] = value;
}
}
/// <summary>
/// The destinationfile attribute is used when the command is
"copy"
/// and when downloading a file.
/// </summary>
[ConfigurationProperty("destinationfile", IsRequired = false)]
public string DestinationFile
{
get
{
return (string)this["destinationfile"];
}
set
{
this["destinationfile"] = value;
}
}
/// <summary>
/// The overwrite attribute is used when the command is "copy"
/// </summary>
[ConfigurationProperty("overwrite", DefaultValue = false,
IsRequired = false)]
public bool Overwrite
{
get
{
return (bool)this["overwrite"];
}
set
{
this["overwrite"] = value;
}
}
/// <summary>
/// The productcode is used when the command is msiexec. The
product code is the GUID
/// that identifies this product and we need it to determine
if the product is already installed.
/// If the product is already installed, we add REINSTALL=ALL
and REINSTALLMODE=vomus to the
/// msiexec command.
/// </summary>
[ConfigurationProperty("productcode", IsRequired = false)]
public string ProductCode
{
get
{
return (string)this["productcode"];
}
set
{
this["productcode"] = value;
}
}
/// <summary>
/// The services attribute is used to specify a code that
identifies the services
/// that this feature installs.
/// </summary>
[ConfigurationProperty("services", IsRequired = false)]
public string Services
{
get
{
return (string)this["services"];
}
set
{
this["services"] = value;
}
}
/// <summary>
/// If this is set to true, we will make check for SQL Server.
/// </summary>
[ConfigurationProperty("requiressql", DefaultValue = false,
IsRequired = false)]
public bool RequiresSql
{
get
{
return (bool)this["requiressql"];
}
set
{
this["requiressql"] = value;
}
}
/// <summary>
/// If this is set to true, we will check for MSMQ.
/// </summary>
[ConfigurationProperty("requiresmsmq", DefaultValue = false,
IsRequired = false)]
public bool RequiresMsmq
{
get
{
return (bool)this["requiresmsmq"];
}
set
{
this["requiresmsmq"] = value;
}
}
/// <summary>
/// The checked attribute defines the default checked state of
this feature.
/// If any of the features is already installed, the checked
features are the
/// ones that are already installed. If none of the features
are installed,
/// we get the checked state from this attribute.
/// </summary>
[ConfigurationProperty("checked", DefaultValue = true,
IsRequired = false)]
public bool Checked
{
get
{
return (bool)this["checked"];
}
set
{
this["checked"] = value;
}
}
/// <summary>
/// Specifies a delay after the command completes.
/// </summary>
[ConfigurationProperty("delay", DefaultValue = 0, IsRequired =
false)]
public int Delay
{
get
{
return (int)this["delay"];
}
set
{
this["delay"] = value;
}
}
public bool IsInstalled
{
get
{
return m_IsInstalled;
}
set
{
m_IsInstalled = value;
}
}
private bool m_IsInstalled;
public override string ToString()
{
return Title;
}
}
}
Now that it is all defined, you can use it like this:
FeatureSection featureSection =
ConfigurationManager.GetSection("features") as FeatureSection;
Thanks for listening!
John Vottero
http://www.JAMSScheduler.com
Hello.
I would extend the app.config with the fallowing configSection:
<plugins>
<Test1 active="1" />
<Test2 active="0" />
</plugins>
Now, I don't now, how does I have declare the section and after read
the values with the ConfigManager.
Can anybody help me?
Thanks.
Best Regards, Thomas