我正在使用c#在Visual Studio 2010中创建一个控制台应用程序。我希望这个应用程序是独立的,因为你需要的只是exe,你可以从任何地方运行它。我还想使用app.config来存储连接字符串等。
我的问题是我似乎无法弄清楚如何将app.config数据包含到已编译的exe中。我确实看到它创建appname.exe.config,但我不希望人们在获取应用程序时不必担心抓取两个单独的文件。
我所做的谷歌搜索都没有想出任何东西。这甚至可能吗?
你不能。此类配置文件的一半要点是允许在应用程序本身之外更改应用程序的配置。
您只需修改程序,使其不依赖于应用程序配置文件 - 最简单的方法是将配置中的值粘贴到只读全局变量中。
以winform应用程序为例,在编译期间,将生成文件'xxx.EXE.config'以及输出EXE文件。它将包含'app.config'设置。也分发这个。
我可以看到你要去哪里,但答案可能比你想要的要复杂一些。
这样你有一些合理的默认值,你没有必要将app.config作为常量保持独立,你可以将你的应用程序作为一个exe运行,你仍然可以通过在app.config中添加回来在运行时修改它。 。
要记住的一件事是,从资源中读取app.config不会给你与普通app.config相同的行为。您基本上是在阅读并手动使用它。
你的意思是你需要将它作为资源添加到exe?好吧,首先你不能,app.config是基于文件而不是基于资源的。
另一方面,配置文件的唯一要点是您可以更改它。否则只需硬编码或使用常量。
正如其他人所指出的,配置文件背后的想法是避免使用硬编码值。
您可以做的替代方法是编写自定义配置部分,每个元素都是可选的,并且具有默认值。这样,任何可以使用默认值的人都不需要配置文件。但如果他们需要覆盖默认值,他们可以提供一个。
(对不起,只是一点头脑风暴。我没有可用的例子。)
通常,您不希望这样做,因为您的app.config提供了一种机制,通过该机制可以在运行时完成配置。至于你的具体目标(维护代码之外的配置,但让它遵循二进制),你有几个选择:
我相信还有其他更有创意的选择。我的建议是第二种选择。首次启动应用程序时,创建必要的密钥并从可执行文件中设置其默认值。这样,如果您需要在以后进行任何调试,您只需运行regedit并进行任何必要的更改,而无需重新编译。
最佳解决方法似乎是在应用程序启动时自己创建它。
示例代码:
Program.cs中
[STAThread]
static void Main()
{
CreateConfigIfNotExists();
}
private static void CreateConfigIfNotExists()
{
string configFile = string.Format("{0}.config", Application.ExecutablePath);
if (!File.Exists(configFile))
{
File.WriteAllText(configFile, Resources.App_Config);
}
}
请记住,它只会在构建时编写当前配置。部署新版本时,它不会自动更新。它将包括构建时的配置。但这可能就够了:)
请在上一篇文章的第一个答案 - Configuration File as Embedded Resource
就像人们在这里说的那样,配置文件的重点是修改应用程序之外的一些设置。您可以硬编码或使用常量,但如果需要,您也可以在Windows中使用注册表。这样您就可以对应用程序进行更改,但仍然只有一个exe文件。
代码项目有一些关于从注册表中读取,写入和删除的好信息。 http://www.codeproject.com/KB/system/modifyregistry.aspx但是在编辑注册表时要小心。很多应用程序都依赖于它,所以如果你做错了什么就可以破坏一些设置。我建议阅读然后再做。
public string Read(string KeyName) {
RegistryKey rk = baseRegistryKey;
// Open a subKey as read-only
RegistryKey sk1 = rk.OpenSubKey(subKey);
// If the RegistrySubKey doesn't exist -> (null)
if ( sk1 == null )
{
return null;
}
else
{
try
{
// If the RegistryKey exists I get its value
// or null is returned.
return (string)sk1.GetValue(KeyName.ToUpper());
}
catch (Exception e)
{
// AAAAAAAAAAARGH, an error!
ShowErrorMessage(e, "Reading registry " + KeyName.ToUpper());
return null;
}
}
}
public bool Write(string KeyName, object Value) {
try
{
// Setting
RegistryKey rk = baseRegistryKey ;
// I have to use CreateSubKey
// (create or open it if already exits),
// 'cause OpenSubKey open a subKey as read-only
RegistryKey sk1 = rk.CreateSubKey(subKey);
// Save the value
sk1.SetValue(KeyName.ToUpper(), Value);
return true;
}
catch (Exception e) {
// AAAAAAAAAAARGH, an error!
ShowErrorMessage(e, "Writing registry " + KeyName.ToUpper());
return false;
}
}
public bool DeleteKey(string KeyName) {
try
{
// Setting
RegistryKey rk = baseRegistryKey ;
RegistryKey sk1 = rk.CreateSubKey(subKey);
// If the RegistrySubKey doesn't exists -> (true)
if ( sk1 == null )
return true;
else
sk1.DeleteValue(KeyName);
return true;
}
catch (Exception e)
{
// AAAAAAAAAAARGH, an error!
ShowErrorMessage(e, "Deleting SubKey " + subKey);
return false;
}
}
当然这只适用于Windows。我假设您使用的是Visual Studio,因此您可能正在使用Windows。
快乐的编码和祝你好运!
IL Merge与wpf可执行文件有很多问题也很慢。我最终使用Cosura.Fody https://github.com/Fody/Costura并使用命令行参数传递我的app配置值。还使用iexpress http://en.wikipedia.org/wiki/IExpress创建最终可执行文件,命令行args和exe合并在一起