civic.sir
civic.sir

Reputation: 410

c# embed config file within exe

I have a console program 'A' that at a given point will run program 'B' and program 'C'. However I'm having an issue with the app.config associated with each of the programs. Basically program A is just a wrapper class that calls different console applications. It should not have any app.config but it should use the current running program's app config. So in theory, there should be only 2 app.config one for program B and another for program C.

So, if we run program A and program B gets executed, it should use program B's app.config to get the information and after when program C gets executed, it should use Program C's app.config.

Is there a way to do this? Currently I'm doing this:

var value =  ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings.Settings["ProgramBKey"].Value;

It does not seem to work. I've checked the debug on Assembly.GetExecutingAssembly().Location it's variable is the \bin\Debug\ProgramB.exe and 'ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings' has setting with Count=0 when there are key values as seen below.

sample code Program A:

static void Main(string[] args)
{
    if(caseB)
        B.Program.Main(args)
    else if(caseC)
        C.Program.Main(args)
}

sample app.config for Program B:

<?xml version="1.0"?>
<configuration>
  <appSettings> 
    <add key="ProgramBKey" value="Works" />
  </appSettings>
  <startup>
    <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0" />
  </startup>
</configuration>

Upvotes: 1

Views: 3806

Answers (4)

abdel khaleq karmi
abdel khaleq karmi

Reputation: 1

Here how you can do it:

  • Make App.config as "Embedded Resource" in the properties/build action

  • Copy to output Directory : Do not copy

  • Add this code to Program.cs Main

          if (!File.Exists(Application.ExecutablePath + ".config"))
          {
              File.WriteAllBytes(Application.ExecutablePath + ".config", ResourceReadAllBytes("App.config"));
              Process.Start(Application.ExecutablePath);
              return;
          }
    

Here are the needed functions:

    public static Stream GetResourceStream(string resName)
    {
        var currentAssembly = Assembly.GetExecutingAssembly();
        return currentAssembly.GetManifestResourceStream(currentAssembly.GetName().Name + "." + resName);
    }


    public static byte[] ResourceReadAllBytes(string resourceName)
    {
        var file = GetResourceStream(resourceName);
        byte[] all;

        using (var reader = new BinaryReader(file))
        {
            all = reader.ReadBytes((int)file.Length);
        }
        file.Dispose();
        return all;
    }

Upvotes: 0

egray
egray

Reputation: 390

You can have multiple application using the same config file. That way when you switch applications, they can both find their own parts of the config file.

The way I usually do it is... first let each application "do its own thing", then copy the relevant sections of config file A into config file B.

It will look like this:

<configSections>
    <sectionGroup>
         <sectionGroup name="applicationSettings"...A>
         <sectionGroup name="userSettings"...A>
         <sectionGroup name="applicationSettings"...B>
         <sectionGroup name="userSettings"...B>

<applicationSettings>
    <A.Properties.Settings>
    <B.Properties.Settings>

<userSettings>
    <A.Properties.Settings>
    <B.Properties.Settings>

Upvotes: 1

Dan Forbes
Dan Forbes

Reputation: 2824

Edit: the following answer pertains to this question from the original post, "Is it possible to compile the app.config for B and C within the exe of the program."

You can use the "Embedded Resource" feature. Here's a small example of using an XML file that's been included as an embedded resource:

public static class Config
{
    static Config()
    {
        var doc = new XmlDocument();
        using (var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("Fully.Qualified.Name.Config.xml"))
        {
            if (stream == null)
            {
                throw new EndOfStreamException("Failed to read Fully.Qualified.Name.Config.xml from the assembly's embedded resources.");
            }

            using (var reader = new StreamReader(stream))
            {
                doc.LoadXml(reader.ReadToEnd());
            }
        }

        XmlElement aValue = null;
        XmlElement anotherValue = null;

        var config = doc["config"];
        if (config != null)
        {
            aValue = config["a-value"];
            anotherValue = config["another-value"];
        }

        if (aValue == null || anotheValue == null)
        {
            throw new XmlException("Failed to parse Config.xml XmlDocument.");
        }

        AValueProperty = aValue.InnerText;
        AnotherValueProperty = anotherValue.InnerText;
    }
}

Upvotes: 3

Woozar
Woozar

Reputation: 1130

For me, the whole thing sounds like a "design issue". Why should you want to open Programm B with the config of Programm A?

Are you the author of all those Programms? You might want to use a dll-file instead. This will save you the trouble as all code runs with the config of the Programm running.

Upvotes: 0

Related Questions