c# - 从自定义安装程序类操作更新 <appname>.config 文件

标签 c# .net windows-installer

我已尝试在安装程序期间更新应用程序的 .config 文件(通过 .NET 安装程序类操作)。但是,我似乎无法让 ConfigurationManager 列出任何属性或能够设置任何内容。

我从几篇 stackoverflow 帖子中了解到这种方法,这些帖子将我指向了本指南:http://raquila.com/software/configure-app-config-application-settings-during-msi-install/

我调查了我的项目和他的项目之间的差异,并注意到我的配置文件的格式不同。我相信这与我使用“设置”文件这一事实有关。

指南中格式化的配置文件如下所示:

<?xml version="1.0" encoding="utf-8" ?>     
<configuration>     
  <appSettings>      
    <add key="Param1" value="" />      
    <add key="Param2" value="" />      
    <add key="Param3" value="" />      
  </appSettings>      
</configuration> 

我的样子:

   <?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MyAppName.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
            <section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="MyAppName.Settings1" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <userSettings>
        <MyAppName.Properties.Settings>
            <setting name="TESTSETTING" serializeAs="String">
                <value>asdfasdfasdf</value>
            </setting>
        </MyAppName.Properties.Settings>
        <MyAppName.Settings1>
            <setting name="VerboseErrorMode" serializeAs="String">
                <value>False</value>
            </setting>
    <applicationSettings>
        <MyAppName.Settings1>
            <setting name="RunOnStartup" serializeAs="String">
                <value>True</value>
            </setting>
        </MyAppName.Settings1>
    </applicationSettings>
</configuration>

为了阐明正在发生的事情......我试着像这样打印出设置列表:

            Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);               

            // Try getting the Settings1 Section
            AppSettingsSection appSettings = (AppSettingsSection)config.GetSection("Settings1");  // Also tried myNamespace.Settings1
            if (appSettings != null)
            {
                valList = "Settings1: ";
                foreach (string key in appSettings.Settings.AllKeys)
                {
                    string value = appSettings.Settings[key].Value;
                    valList += ("Key: '" + key + "' = '" + value + "'\n");
                }
            }
            else
            {
                valList = "appSettings was null";
            }
            MessageBox.Show(valList);

        MessageBox.Show(valList);

我已经尝试了几种排列方式...并且在所有情况下输出都是“appSettings was null”。

我还尝试以几种不同的方式初始化配置管理器...

            Configuration config = ConfigurationManager.OpenExeConfiguration(exePath);

            MessageBox.Show("Section Count: " + config.Sections.Count);
            MessageBox.Show("Has File: " + config.HasFile);
            MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);

            config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            MessageBox.Show("Section Count: " + config.Sections.Count);
            MessageBox.Show("Has File: " + config.HasFile);
            MessageBox.Show("Namespace Declared: " + config.NamespaceDeclared);

对于它们中的每一个,返回的节数都是 20。(我不知道 20 来自哪里......我本以为它是 3)。
HasFile 对于第一种情况为真,对于第二种情况为假。
Namespace Declared 在这两种情况下都是错误的。

谢谢!

编辑 (6-18-09): 仍在研究这个问题。其他人有什么想法吗?谢谢。

搜索关键字:“对象引用未设置为未设置为实例”<-- 这发生在尝试写入属性时。

最佳答案

我遇到了同样的问题,经过深入调查,我发现了更新配置文件任何部分(例如 app.config)的最简单方法,那就是使用 XPath。 我们有一个连接到 web 服务的应用程序,在安装过程中,用户输入 web 服务的 URL,这应该保存在以下 app.config 文件中:

        <?xml version="1.0"?>
    <configuration>
      <configSections>
        <sectionGroup name="applicationSettings" type="System.Configuration.ApplicationSettingsGroup, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
          <section name="ApplicationServer.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" requirePermission="false" />
        </sectionGroup>
      </configSections>

      <applicationSettings>
        <ApplicationServer.Properties.Settings>
          <setting name="ApplicationServer_ApplicationServerUrl" serializeAs="String">
            <value>whatever comes from setup should go here</value>
          </setting>
        </ApplicationServer.Properties.Settings>
      </applicationSettings>
    </configuration>

这是在安装程序类中执行此操作的代码:

public override void Install(System.Collections.IDictionary stateSaver)
    {
        base.Install(stateSaver);

        string targetDirectory = Context.Parameters["targetdir"];
        string param1 = Context.Parameters["param1"];

        string path = System.IO.Path.Combine(targetDirectory, "app.config");

        System.Xml.XmlDocument xDoc = new System.Xml.XmlDocument();

        xDoc.Load(path);

        System.Xml.XmlNode node = xDoc.SelectSingleNode("/configuration/applicationSettings/Intellisense.ApplicationServer.Properties.Settings/setting[@name='ApplicationServer_ApplicationServerUrl']/value");
        node.InnerText = (param1.EndsWith("/") ? param1 : param1 + "/");

        xDoc.Save(path); // saves the web.config file  
    }

基本上,由于配置文件是基于 XML 的文档,我使用 XPath 表达式来定位特定节点并更改其值。

关于c# - 从自定义安装程序类操作更新 <appname>.config 文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/918565/

相关文章:

c# - 通过linq读取root中具有该属性的所有节点值

c# - 在 linq 编译查询上使用 union

WIX 烧录卸载?

installation - 如何从 InstallShield 迁移到 Visual Studio 安装程序项目

powershell - 使用 PowerShell 远程安装时获取 MSI 退出代码

c# - 将非终止流中的对象集合转换为 IObservable

c# - 如何让我的通用比较器 (IComparer) 处理空值?

.net - 如何对配置进行单元测试

.net - Azure 服务可以运行非托管代码吗?

c# - UDPClient Async BeginReceive 很慢