2

我需要知道应用程序设置(连接字符串)的存储位置和方式,以便在运行时更改并保存它们。

我知道在 VS 中,您可以在 Project>Properties 下配置设置,这些设置存储在应用程序安装目录下的 appname.exe.config 文件中。但是“应用程序范围”在运行时不是读/写的,如果您更改了这些设置在用户范围内,配置文件的副本在用户目录下创建,并且不会被应用程序的其他用户访问。

我需要有一种方法,以便用户可以根据应用程序中的需要配置存储在通用配置文件中的连接字符串,然后让所有其他用户(在该机器上)也可以使用它。我怎样才能做到这一点?

4

6 回答 6

9

最简单、最快的解决方案是在普通用户有权读取/写入的共享位置创建配置文件。

为您的配置数据创建一个具有公共属性的类,然后在此共享位置将其序列化为 xml。

public class Configuration
{
  // config filename
  private static _name = Path.Combine(
      System.Environment.GetFolderPath(
         Environment.SpecialFolder.CommonApplicationData),
      @"MyApp\MyConfig.xml");

  // the connection string
  public string ConnectionString {get;set;}

  // load the configuration from disk
  public static Configuration Load()
  {
    using (var f = File.OpenRead(name))
    {
      var x = new System.Xml.Serialization.XmlSerializer(typeof(Configuration));
      return x.Deserialize(f) as Configuration;
    }
  }

  // save the configuration to disk
  public static Save(Configuration config)
  {
    using (var f = File.OpenWrite(name))
    {
      var x = new System.Xml.Serialization.XmlSerializer(typeof(Configuration));
      x.Serialize(f, config);
    }
  }
}
于 2009-07-16T14:06:16.080 回答
5

应用程序范围的连接字符串是可写的,但您必须以不同的方式处理它,而不仅仅是获取字符串以供使用。例如:

Configuration c = ConfigurationManager
   .OpenExeConfiguration(ConfigurationUserLevel.None);

c.ConnectionStrings.ConnectionStrings["myConnectionString"]
   .ConnectionString = "theConnectionString";
c.Save();

您还应该刷新该部分,以便正确检索更改。紧接着:

string sectionName = c.ConnectionStrings.SectionInformation.SectionName;
ConfigurationManager.RefreshSection(sectionName);
于 2009-07-16T13:54:37.920 回答
2

正如其他人指出的那样,您需要在计算机上创建一个可由您的应用程序的所有用户写入的共享位置。该位置可以是文件夹、文件或注册表。但是,Windows 实际上有一个位置。您可以在MSDN上阅读有关此内容的更多信息。您需要的文件夹用于存放常见的应用程序数据:

CSIDL_COMMON_APPDATA

此文件夹应用于非用户特定的应用程序数据。例如,应用程序可以在 CSIDL_COMMON_APPDATA 文件夹中存储拼写检查字典、剪贴画数据库或日志文件。此信息不会漫游,任何使用计算机的人都可以使用。默认情况下,此位置对于普通(非管理员、非电源)用户是只读的。如果应用程序要求普通用户对 CSIDL_COMMON_APPDATA 的应用程序特定子目录具有写访问权限,则应用程序必须在应用程序设置期间显式修改该子目录的安全性。修改后的安全必须记录在供应商问卷中。

您可以通过调用获取此文件夹的位置

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

在您的 .NET 应用程序中。在 Vista 上,这个文件夹通常是C:\ProgramData.

You have to create your own vendor and application specific folder inside the shared folder and this should be done by an install program running with elevated privileges. This install program should also make sure that users have the necessary privileges to get write access as seen in the quote above.

于 2009-07-16T14:22:19.547 回答
1

我这样做的方法是保存一个 XML 文件,该文件从具有 SQL 连接信息的 POCO 对象序列化到隔离存储中。由于可以从那里读取和写入的用户帐户没有真正的限制,因此您不必担心用户权限。

然后我修改了设置事件,以便在从应用程序设置文件中读取连接字符串属性时,我改为在隔离存储中反序列化 XML 文件,构建连接字符串,然后将其放入应用程序设置连接字符串属性中。由于我在设置类本身中执行此操作,因此我能够写入它(但不能保存回文件)。

当我的应用程序运行时,如果它无法连接到服务器,我只会弹出一个窗口询问 sql server 信息,然后他们将其输入并将其保存到隔离存储中,永远不会再次询问他们(即使通过升级)。

如果您有客户端应用程序(WPF 或 WinForms),其他机器上的用户将无法使用它,坦率地说,您可能找不到解决方案,除非您研究 .Net Remoting 或类似性质的东西。但是,如果您在 WinForms 应用程序中的同一台计算机上有多个用户,则可以使用 IsolatedStorage,它将适用于所有用户。

在设置类中,添加此事件处理程序:

VB:

Private Sub MySettings_SettingsLoaded(ByVal sender As Object, ByVal e As System.Configuration.SettingsLoadedEventArgs) Handles Me.SettingsLoaded   
  Me.Item("MyAppConnectionString") = MyLibrary.BuildConnectionString()   
End Sub 

C#:

protected override void OnSettingsLoaded(object sender, System.Configuration.SettingsLoadedEventArgs e)
{
  base.OnSettingsLoaded(sender, e);
  this["MyAppConnectionString"] = MyLibrary.BuildConnectionString();
}
于 2009-07-16T14:20:26.273 回答
0

读取和写入注册表曾经是存储用户设置的推荐方式,您仍然可以轻松地执行此操作(使用 Microsoft.Win32.Registry),但这种方法存在问题(主要是由于用户之间的权限级别不同- 某些用户不允许写入注册表的某些部分或创建新密钥)。

于 2009-07-16T13:53:45.020 回答
0

您的问题中有一些相互矛盾的元素:

可以存储应用程序设置(连接字符串),以便可以在运行时更改并保存它们。

.

应用程序范围”的那些在运行时不是读/写的,如果您在用户范围下更改配置文件的副本,则会在用户目录下创建配置文件的副本,并且不会被应用程序的其他用户访问。

最佳实践规定,您要应用于系统的每个用户的设置(如连接字符串)不应由系统任何随机用户更改。这种设置只能由有资格管理系统的人更改。

因此,您描述的行为正是预期的。如果您真的想允许用户更改此设置,请将其设置为用户设置,这样如果用户搞砸了,他们只会为自己的帐户搞砸。

于 2009-07-16T14:07:06.063 回答