【问题标题】:c# embed config file within exec#在exe中嵌入配置文件
【发布时间】:2016-11-08 15:18:54
【问题描述】:

我有一个控制台程序“A”,它将在给定点运行程序“B”和程序“C”。但是,我遇到了与每个程序关联的 app.config 的问题。基本上程序A只是一个调用不同控制台应用程序的包装类,它不应该有任何app.config,但它应该使用当前正在运行的程序的应用程序配置。所以理论上应该只有2个app.config,一个用于程序B,另一个用于程序C。

所以如果我们运行程序 A 并且程序 B 被执行,它应该使用程序 B 的 app.config 来获取信息,并且当程序 C 执行后它应该使用程序 C 的 app.config。

有没有办法做到这一点?目前我正在这样做:

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

它似乎不起作用。我检查了Assembly.GetExecutingAssembly().Location 上的调试,它的变量是 \bin\Debug\ProgramB.exe 和 'ConfigurationManager.OpenExeConfiguration(Assembly.GetExecutingAssembly().Location).AppSettings' 当有键值时设置为 Count=0下面。

示例代码程序A:

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

程序 B 的示例 app.config:

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

【问题讨论】:

  • 您如何启动这些其他.exe 程序?
  • 都是控制台应用
  • 这么简单的Applicaton.Run() 电话?
  • 我不需要在同一目录中的 app.config 文件吗?目前我只是从程序 A 调用 main 方法
  • 这就是我要问的,复制粘贴你如何从program1打开program2的代码行。

标签: c# console-application app-config


【解决方案1】:

编辑:以下答案与原始帖子中的这个问题有关,“是否可以在程序的 exe 中为 B 和 C 编译 app.config。”

您可以使用“Embedded Resource”功能。下面是一个使用作为嵌入式资源包含的 XML 文件的小示例:

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

【讨论】:

  • 更新了问题..这个答案在之前的上下文中是正确的......但我想这个问题不够清楚
【解决方案2】:

您可以有多个应用程序使用同一个配置文件。这样,当您切换应用程序时,它们都可以找到自己的配置文件部分。

我通常这样做的方式是……首先让每个应用程序“做自己的事”,然后将配置文件A的相关部分复制到配置文件B中。

看起来像这样:

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

【讨论】:

  • 唯一的问题是,如果程序 B 的配置文件有任何更改,我们还必须更新程序 A 的配置文件以更新被更改的部分,不是吗?因此,每次任何程序发生变化时,都需要更新 app.config(对于 ProgramA)
【解决方案3】:

对我来说,整个事情听起来像是一个“设计问题”。为什么要使用 Programm A 的配置打开 Programm B?

您是所有这些程序的作者吗?您可能想改用 dll 文件。这将为您省去麻烦,因为所有代码都在运行程序配置的情况下运行。

【讨论】:

  • 之所以从 A 运行,是因为程序 B 本身可以是一个独立的控制台应用程序。这就是为什么我不能使它成为一个dll。但是如果我把它们变成了一个 dll(是的,我是所有程序的作者),那会解决 app.config 的问题吗?
  • 例如,用户可以独立运行程序 B。程序 A 只是帮助确定 B 是否需要运行或 C 是​​否需要运行或两者兼而有之。
【解决方案4】:

这里是如何做到的:

  • 在属性/构建操作中将 App.config 设为“嵌入式资源”

  • 复制到输出目录:不要复制

  • 将此代码添加到 Proram.cs Main

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

以下是所需的功能:

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-04
    • 2014-04-03
    • 2020-10-05
    • 1970-01-01
    • 2014-05-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多