关于在 .NET Win 应用程序中存储应用程序设置的位置的困惑

发布于 2024-07-28 07:08:05 字数 300 浏览 4 评论 0原文

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

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

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

I need to know where and how application settings (connections string) could be stored so that they can be changed at run time and saved.

I know in VS you can configure settings under Project>Properties and these get stored in the appname.exe.config file under apps install directory.But the "application scope" ones are not read/write at run time and if you change the ones under user scope a copy of the config file is created under users directory and wont be accessed by other users of the application.

I need to have a way so that the user can configure connection string, stored in a common config file, as per their needs from within the app and then have all other users(on that machine) can use that too. how can I achieve this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

囚你心 2024-08-04 07:09:03

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

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

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

最佳实践规定设置(例如您想要应用于系统的每个用户的连接字符串应该不能被系统的任何随机用户更改。这种设置应该仅<。 /em> 由有资格管理系统的人更改。

因此,您所描述的行为正是您想要的,如果您确实希望允许用户更改此设置,则将其设置为用户设置,以便只有用户搞砸了。为了自己的利益搞砸了。

You have some conflicting elements in your question:

application settings (connections string) could be stored so that they can be changed at run time and saved.

.

application scope" ones are not read/write at run time and if you change the ones under user scope a copy of the config file is created under users directory and wont be accessed by other users of the application.

Best practices dictate that settings (like connection strings) that you want to apply to every user of a system should not be changeable by any random user of the system. That kind of setting should only be changed by someone qualified to administer the system.

Therefore, the behavior you describe is exactly what's intended. If you really want to allow users to change this, then make it a user setting so if a user screws it up they only screw it up for their own account.

墨落画卷 2024-08-04 07:08:54

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

Reading and writing to the Registry used to be the recommended way of storing user settings, and you can still do this easily (using Microsoft.Win32.Registry), but there are issues with this approach (mainly due to varying permissions levels among your users - some users aren't allowed to write to some parts of the registry or create new keys).

水波映月 2024-08-04 07:08:47

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

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

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

如果您有一个客户端应用程序(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();
}

The way I did it was I saved an XML file that was serialized from a POCO object that had the SQL Connection information into isolated storage. Since there are no real restrictions on the user account that can read and write from there, you don't have to worry about user permissions.

I then modified the settings events so that when the connection string property was read from the app settings file, I instead deserialized the XML file in isolated storage, built the connection string, and then put that into the app settings connection string property. Since I was doing this inside the settings class itself, I was able to write to it (but not save back to the file).

When my app runs, if it can't connect to the server I just pop up a window asking for the sql server info and they type it in and it saves it to the isolated storage, never to ask them for it again (even through upgrades).

If you have a client application (WPF or WinForms), users on other machines will not be able to use this and quite frankly you probably will not find a solution for that, unless you look into .Net Remoting or something of that nature. However, if you have multiple users on the SAME machine in a WinForms App, you can use the IsolatedStorage and it will work for all users.

In the settings class, add this event handler:

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();
}
往事随风而去 2024-08-04 07:08:37

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

CSIDL_COMMON_APPDATA

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

获取此文件夹的位置

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

您可以通过调用 .NET 应用程序来 。 在 Vista 上,此文件夹通常为 C:\ProgramData

您必须在共享文件夹中创建自己的供应商和应用程序特定文件夹,这应该通过以提升的权限运行的安装程序来完成。 此安装程序还应确保用户拥有必要的权限来获得写访问权限,如上面的引用所示。

As other have pointed out you need to create a shared location on the computer that is writable by all users of your application. This location can be a folder, a file or the registry. However, Windows actually have a location for this. You can read more about this on MSDN. The folder you need is for common application data:

CSIDL_COMMON_APPDATA

This folder should be used for application data that is not user specific. For example, an application may store a spell check dictionary, a database of clip-art or a log file in the CSIDL_COMMON_APPDATA folder. This information will not roam and is available to anyone using the computer. By default, this location is read-only for normal (non-admin, non-power) Users. If an application requires normal Users to have write access to an application specific subdirectory of CSIDL_COMMON_APPDATA, then the application must explicitly modify the security on that sub-directory during application setup. The modified security must be documented in the Vendor Questionnaire.

You can get the location of this folder by calling

Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData);

in your .NET application. On Vista this folder is normally 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.

缪败 2024-08-04 07:08:30

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

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

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

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

string sectionName = c.ConnectionStrings.SectionInformation.SectionName;
ConfigurationManager.RefreshSection(sectionName);

Application scope connection strings are writable, but you have to go about it differently from just getting the string for usage. For example:

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

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

You should also refresh the section so that the change is properly retrieved. Immediately afterward:

string sectionName = c.ConnectionStrings.SectionInformation.SectionName;
ConfigurationManager.RefreshSection(sectionName);
逆流 2024-08-04 07:08:24

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

为您的配置数据创建一个具有公共属性的类,然后在此共享位置将其序列化为 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);
    }
  }
}

Simplest, fastest solution is to create a configuration file in a shared location where normal users have rights to read/write.

Create a class with public properties for your configuration data, then serialize it to xml in this shared location.

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);
    }
  }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文