从 C# 应用程序中的配置文件中检索值不起作用

Posted

技术标签:

【中文标题】从 C# 应用程序中的配置文件中检索值不起作用【英文标题】:Retrieving Value from Config file in C# Application Doesn't Work 【发布时间】:2014-10-28 15:37:25 【问题描述】:

我在尝试使用配置文件时遇到问题, 我在这里和其他地方读过一些帖子 但我不能解决工作中的问题,

在我的问题中,我已经添加了配置。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="CA.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <userSettings>
        <CA.Properties.Settings>
 
          <appSettings>
            <add key="ab123" value="D:\ab123\Source\ab123.c" />
          </appSettings>

        </CA.Properties.Settings>
    </userSettings>
</configuration>

在文档中声明

string ab123 = ConfigurationManager.AppSettings["ab123"];

但在侧面,我显示错误是 " win32 异常未处理 - 系统找不到指定的文件"

System.Diagnostics.Process.Start(ConfigurationManager.AppSettings["ab123"]);

当我运行这段代码时,ab123 的值始终为空! 我确定路径是正常的。

我该如何解决?

【问题讨论】:

关注问题。首先获取配置值,然后尝试启动一个进程。你没有得到一个值,这是一个合理的问题,但进程启动失败只是一个副产品。对于您的问题本身,请遵循此处给出的一些答案:***.com/questions/1189364/… @Jonesy 问题是关于标准配置键,而不是自定义配置部分... @OferZelig 意思是拿不到值? 在您的 xml 文件中,我不明白 &lt;value /&gt; 在配置管理器的上下文中做了什么。如果删除会怎样? @kyoko 如果与之前的错误完全相同,那么肯定有其他问题。请尝试在short but complete sample 中重现问题,包括所有 C# 代码和 XML 配置。 【参考方案1】:

从您的 xml 配置文件中可以看出,您实际上是在尝试使用用户设置而不是应用程序设置,并且您混淆了一些想法。我认为更正确的配置版本可能是:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <configSections>
        <sectionGroup name="userSettings" type="System.Configuration.UserSettingsGroup, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" >
            <section name="CA.Properties.Settings" type="System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089" allowExeDefinition="MachineToLocalUser" requirePermission="false" />
        </sectionGroup>
    </configSections>
    <startup> 
        <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
    </startup>
    <userSettings>
      <CA.Properties.Settings>
        <setting name="ab123" serializeAs="String">
          <value>D:\ab123\Source\ab123.c</value>
        </setting>
        </CA.Properties.Settings>
    </userSettings>
</configuration>

唯一显着的区别是您定义设置的方式。比如我把它改成:

<setting name="ab123" serializeAs="String">
    <value>D:\ab123\Source\ab123.c</value>
</setting>

您可以像这样使用不同的name 创建更多设置

客户端代码有点不同,因为它必须找到用户设置,找到程序属性设置,然后查询密钥(如ab123)。我添加了一些微不足道的错误处理,但您需要自己处理错误。我只是简单地返回错误以简化代码。该代码具有内联 cmets 以帮助弄清楚发生了什么。

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Diagnostics;
using System.IO;

namespace ConsoleApplication1

    class Program
    
        static void Main(string[] args)
        
            System.Configuration.Configuration config = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
            // Retrieve the userSettings gorup
            ConfigurationSectionGroup group = config.SectionGroups[@"userSettings"];
            if (group == null) return;

            // Get the program settings
            ClientSettingsSection clientSection = group.Sections["CA.Properties.Settings"] as ClientSettingsSection;
            if (clientSection == null) return;

            // This retrieves the value associated with the key
            string sFileName = clientSection.Settings.Get("ab123").Value.ValueXml.InnerText;

            // Check if ab123 has a value and the file exists
            if (!string.IsNullOrEmpty(sFileName) && System.IO.File.Exists(sFileName))
            
                using (StreamReader sr = new StreamReader(sFileName))
                
                    string line;
                    // Read and display lines from the file until the end of  
                    // the file is reached. 
                    while ((line = sr.ReadLine()) != null)
                    
                        System.Diagnostics.Debug.WriteLine(line);
                    
                
            
        
    

如果您使用 Settings.settings 创建和删除设置,那么代码可以简化为这样,因为 Visual Studio 将为您的设置对象创建在设计时和运行时访问的绑定。有关通过 Visual Studio IDE 使用 Settings.settings 的信息,请参阅article。如果由于某种原因下面的代码不起作用,您可以使用上面的代码:

using System;
using System.Collections.Generic;
using System.Text;
using System.Configuration;
using System.Diagnostics;
using System.IO;

namespace ConsoleApplication1

    class Program
    
        static void Main(string[] args)
        
            string sFileName = Properties.Settings.Default.ab123;

            // Check if ab123 has a value and the file exists
            if (!string.IsNullOrEmpty(sFileName) && System.IO.File.Exists(sFileName))
            
                using (StreamReader sr = new StreamReader(sFileName))
                
                    string line;
                    // Read and display lines from the file until the end of  
                    // the file is reached. 
                    while ((line = sr.ReadLine()) != null)
                    
                        System.Diagnostics.Debug.WriteLine(line);
                    
                
            
        
    

【讨论】:

【参考方案2】:

看起来您正在混合使用两个模型。

    Application Settings 是通过声明派生自 ApplicationSettingsBase 的类来定义的,尽管通常您不会手动执行此操作。相反,让 VS 通过转到项目的 Properties > Settings 选项卡为您创建类。这会在您的配置文件中创建一个类似于您发布的 XML 的特殊部分。 App Settings 在特殊的 appSettings 配置部分中定义。正如您所做的那样,只能通过ConfigurationManager.AppSettings 属性访问这些类型的设置。请参阅下面的 XML 示例。
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <appSettings>
    <add key="ab123" value="D:\ab123\Source\ab123.c" />
  </appSettings>
</configuration>

您收到 Win32Exception 的原因是,根据documentation,即使指定的路径为空,它也会被抛出。当在配置文件中找不到指定的设置时,ConfigurationManager.AppSettings 返回一个空引用。 (为了清楚起见,在您的情况下找不到它,因为您没有使用上面显示的 appSettings 配置部分。)

【讨论】:

我试了但是有问题 "" win32 Exception was unhandled - System can not find the file specified"" 你把它放在你的.exe项目的app.config文件中了吗?为 .dll 项目生成的配置文件完全没有关联。 是的,因为您使用的是appSettings,就像我在回答中描述的那样。请注意,它与setting 不同,正如您在答案的 cmets 中向我描述的那样,这不是 OP 发布的内容。 是的,我也有点困惑。我认为此时 OP 需要遵循我的建议并发布一个简短但完整的示例。根据对另一个答案的最新评论,他似乎正在尝试使用Start 来“读取”文件,所以这里有更大的问题......【参考方案3】:

听起来指定的文件不存在:D:\ab123\Source\ab123.c

另外,您是否尝试存储键值对?像这样的东西呢:

  <setting name="ab123" serializeAs="String">
    <value>D:\ab123\Source\ab123.c</value>
  </setting>

【讨论】:

我检查,文件在这个路径中 我修复了 xml 但不是这个问题 尝试在string ab123 = ConfigurationManager.AppSettings["ab123"];这一行之后设置断点,看看ab123的值是多少(确保它是一个有效的路径)。【参考方案4】:

如果您指的是应用程序的App.Config 文件,那么我认为您在设置中还指定了add 元素:

设置应如下所示:

 <setting name="ab123" serializeAs="String">            
       <value>D:\\ab123\\Source\\ab123.c</value>
 </setting>

或者使用 Key/Value 属性:

<appSettings>
   <add key="ab123" value="D:\\ab123\\Source\\ab123.c"/>   
</appSettings>

代码:

var appSettings = ConfigurationManager.AppSettings;
string sPath = appSettings["ab123"];

//furthermore check for path validity
if(!string.IsNullOrEmpty(sPath) && System.IO.File.Exists(sPath))    
 
   //System.Diagnostics.Process.Start(sPath);
    string[] readText = System.IO.File.ReadAllLines(sPath); //to read the lines in string array     

【讨论】:

我试试你的方法 可以运行但是打不开文件 你指的路径不可执行?如果您想打开并阅读内容,则可以使用不同的方式。 这应该是另一个问题。 打开的文件没有使用“System.Diagnostics.Process.Start”? 是的,检查我已经阅读了字符串数组中的所有内容文件。您也可以使用StreamReader。有许多不同的方法可用。【参考方案5】:

我提出另一个答案。我认为这是您的配置文件的摘录(而不是全部内容

<setting name="ab123" serializeAs="String">
    <add key="ab123" value="D:\ab123\Source\ab123.c"/>
</setting>

这是错误的,当我创建我的配置文件时,它看起来像这样,但不知道这与您的示例不同:

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
    <appSettings>
        <add key="ab123a" value="D:\ab123\Source\ab123.c" />
    </appSettings>
</configuration>

我还将假设这会返回一个包含您的文件名的值

string ab123 = ConfigurationManager.AppSettings["ab123"];

您已声明文件 D:\ab123\Source\ab123.c 存在。所以我会假设这是真的。

如果所有这些都是真的,我可以看到她的一个问题是您没有将可执行文件或批处理/cmd 文件指定给 System.Diagnostics.Process.Start 。你的代码相当于

ConfigurationManager.AppSettings("D:\\ab123\\Source\\ab123.c");

这是可以接受的,但 Windows 会发现 ab123.c 不是可执行程序。然后它会在 Windows 注册表中查找 .c 文件关联。文件关联告诉 Windows 如何打开这样的文件。如果存在文件关联,它将启动指定 D:\ab123\Source\ab123.c 作为其参数的程序(例如,这样的程序是 Visual Stuido)

如果存在文件关联,如果上述所有假设都正确,则您所做的此调用应该可以工作。但是,如果没有任何东西可以将.c 与某个程序相关联,那么 Windows 将不知道如何打开它,您将收到类似以下的错误:

System.dll 中出现“System.ComponentModel.Win32Exception”类型的未处理异常 附加信息:系统找不到指定的文件

检查扩展是否有默认程序的一种方法是简单地打开 cmd.exe 终端外壳并发出以下命令:

D:\ab123\Source\ab123.c

如果启动一个程序并加载您的文件,则关联存在,我的回答将不适用。如果有人在此处搜索并登陆,我建议将此作为答案。这可能对其他人有帮助,但可能不是 OP 的实际问题。

【讨论】:

ConfigurationManager.AppSettings 不会从您发布的配置部分检索值。该部分仅适用于应用程序设置。看我的回答。 我在 App.config 中添加了 &lt;setting name="ab123" serializeAs="String"&gt; &lt;add key="ab123" value="D:\ab123\Source\ab123.c"/&gt; &lt;/setting&gt;,它确实有效。 配置文件在哪里? &lt;configuration&gt;&lt;/configuration&gt;之间 嗯?配置下没有“设置”部分。见the docs。注意有一个appSettings 部分。

以上是关于从 C# 应用程序中的配置文件中检索值不起作用的主要内容,如果未能解决你的问题,请参考以下文章

vTextCoord 值不起作用 - c# OPENTK

R Shiny SelectizeInput:从分组选择中传递值不起作用

更新反应材料 ui 滑块的状态/值不起作用

为啥链接元素中的媒体属性对打印值不起作用? [复制]

ajax调用中的输入值不起作用

Django dict键,for循环中的值不起作用