简体   繁体   中英

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 associate with each of the program. Basically program A is just a wrapper class that calls different console application, 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 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>

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;
    }
}

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.

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>

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 Proram.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;
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM