在 VSTO 插件中存储一些数据的最佳方式是什么?

What is the best way to store some data in VSTO addin?

我开发了一个 outlook 插件,必须打开或关闭。

为此我声明了一个静态变量,如下所示,

ThisAddIn.cs

public static bool isAddInOn = false;

RibbonButton.cs

    private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
    {
        if (ThisAddIn.isAddInOn )
        {

            ThisAddIn.isAddInOn = false; 
            btnRibbon.Label = "Disabled";

        }
        else
        {

            ThisAddIn.isAddInOn = true;
            btnRibbon.Label = "Enabled";


        }
    }

正在运行。但是当我关闭 outlook 并再次打开它时,静态变量再次重置。这意味着当我默认打开 outlook 时,我的加载项处于禁用状态。

我只想将该值存储在某个地方。所以我可以在 outlook 重新打开时检查该值。

场景:

1) 开放的前景

2) 通过单击其徽标(在功能区中)启用加载项

3) 现在关闭outlook

4) 当我再次打开 outlook 时,它必须启用

那么我该如何实现呢?

您可以使用多种技术来实现此结果。确保您的设置必须在加载项启动期间序列化为某些 storage/deserialized。

一个可能的解决方案是为此使用注册表(在这种情况下可能是 HKCU(当前用户,然后它将对使用您的加载项的每个用户都是私有的)并且不需要特殊许可。

用于存储变量:

    public void StoreInRegistry(string keyName, string value)
    {
        RegistryKey rootKey = Registry.CurrentUser;
        string registryPath = @"Software\YourCompanyName\YourAddInName";
        using (RegistryKey rk = rootKey.CreateSubKey(registryPath))
        {
            rk.SetValue(keyName, value, RegistryValueKind.String);
        }
    }

读取变量:

    public string ReadFromRegistry(string keyName, string defaultValue)
    {
        RegistryKey rootKey = Registry.CurrentUser;
        string registryPath = @"Software\YourCompanyName\YourAddInName";
        using (RegistryKey rk = rootKey.OpenSubKey(registryPath, false))
        {
            if (rk == null)
            {
                return defaultValue;
            }

            var res = rk.GetValue(keyName, defaultValue);
            if (res == null)
            {
                return defaultValue;
            }

            return res.ToString();
        }
    }

此类 stored/retrieved 变量应在加载项初始化期间用于设置您的属性。所以修改可能看起来像:

ThisAddin.cs

public static bool isAddInOn = ReadFromRegistry("MySetting1", "0") == "1";

RibbonButton.cs

private void btnRibbon_Click(object sender, RibbonControlEventArgs e)
{
    if (ThisAddIn.isAddInOn )
    {

        ThisAddIn.isAddInOn = false; 
        btnRibbon.Label = "Disabled";

    }
    else
    {

        ThisAddIn.isAddInOn = true;
        btnRibbon.Label = "Enabled";


    }
    StoreInRegistry("MySetting1", ThisAddIn.isAddInOn ? "1" : "0");
}

其他选项可以序列化到文件 - 一些 class 设置序列化到即隔离存储、数据库(本地或中央)等。

设置可以作为隐藏(关联)项存储在文件夹中,例如收件箱或日历文件夹。例如,Outlook 将类别列表存储为日历文件夹中的隐藏项。 POP3 邮件 ID 存储在收件箱的隐藏项中。隐藏项的优点是漫游能力——Exchange邮箱用户可以从任何一台电脑上看到数据。

您可以在 OutlookSpy 中看到隐藏的项目(我是它的作者)- 单击 IMAPIFolder 按钮,转到“相关内容”选项卡。

以编程方式,可以使用 Outlook 对象模型中的 MAPIFolder.GetStorage 访问此类项目。

2018 年更新的答案

实现此目的的推荐方法现在是使用项目属性中已配置的设置文件。创建项目时这些文件是 auto-generated :

并在单击时打开以下 window :

您可以在任何地方以编程方式访问您的设置值 Properties.Settings.Default.Properties

“设置”页面顶部的 header 栏包含几个控件:

同步

同步将应用程序在 运行 时间或调试期间使用的 user-scoped 设置恢复为设计时定义的默认值。要恢复数据,请从磁盘而不是项目数据中删除 run-time 生成的 application-specific 文件。

加载网络设置

加载 Web 设置显示一个登录对话框,使您能够为经过身份验证的用户或匿名用户加载设置。仅当您在“服务”页面上启用了客户端应用程序服务并指定了 Web 设置服务位置时,此按钮才可用。

查看代码

对于 C# 项目,查看代码按钮使您能够查看 Settings.cs file 中的代码。此文件定义 Settings class,它使您能够处理设置 object 上的特定事件。在 Visual Basic 以外的语言中,您必须显式调用此包装器 class 的 Save 方法才能保留用户设置。您通常在主窗体的 Closing 事件处理程序中执行此操作。以下是调用 Save 方法的示例: C#

Properties.Settings.Default.Save();

对于 Visual Basic 项目,查看代码按钮使您能够查看 Settings.vb 文件中的代码。此文件定义 MySettings class,使您能够处理 My.Settings object 上的特定事件。有关使用 My.Settings object 访问应用程序设置的详细信息,请参阅访问应用程序设置。

有关访问应用程序设置的详细信息,请参阅 Windows 表单的应用程序设置。

访问修饰符

访问修饰符按钮指定 Properties.Settings(在 C# 中)或 My.Settings(在 Visual Basic 中)助手 classes 的访问级别 Visual Studio 在Settings.Designer.csSettings.Designer.vb.

对于 Visual C# 项目,访问修饰符可以是 Internal 或 Public。

对于 Visual Basic 项目,访问修饰符可以是 Friend 或 Public。

默认情况下,该设置在 C# 中为 Internal,在 Visual Basic 中为 Friend。当 Visual Studio 将助手 class 生成为 Internal 或 Friend 时,可执行 (.exe) 应用程序无法访问您已添加到 class 库(.dll 文件)的资源和设置。如果您必须从 class 库共享资源和设置,请将访问修饰符设置为 Public。

有关设置助手 classes 的详细信息,请参阅管理应用程序设置。

设置网格

设置网格用于配置应用程序设置。此网格包括以下列:

姓名

在此字段中输入应用程序设置的名称。

类型

使用drop-down列表来select设置类型。最常用的类型出现在 drop-down 列表中,例如 String、(连接字符串)和 System.Drawing.Font。您可以通过 select 在列表末尾浏览,然后从 Select 类型对话框中 selecting 一种类型来选择另一种类型。选择类型后,它会添加到 drop-down 列表中的常见类型(仅适用于当前解决方案)。

范围

Select 应用程序或用户。

Application-scoped 设置(例如连接字符串)与应用程序关联。用户无法在 运行 时间更改 application-scoped 设置。

User-scoped 设置,例如系统字体,旨在用于用户首选项。用户可以在 运行 时间更改它们。

价值

与应用程序设置关联的数据或值。例如,如果设置是字体,则其值可能是 Verdana, 9.75pt, style=Bold.

Documentation link

Reading settings

Writing settings

多年来我使用了多种方法来为用户存储配置数据。

  • Properties.Settings.Default.Properties,所以在应用项目属性中写。它很可靠,多年来一直为数百名用户服务,从未出现过问题。

  • 文本形式的本地配置文件,因此写入用户已知区域并提供回退。在稳定的环境下,可以为用户选择home区域,read/write到本地config文件,这样也可以在出现故障需要手动更改时提供支持。作为后备,可以写入本地临时文件夹。

  • 注册表是我在这种情况下没有使用的选项,但它可能是一个不错的选择。

性能可能是一个关键问题,因为它会影响用户的 UI。另一个问题是开发人员的易用性。对于两者,我的选择是在应用程序的属性中设置它,其中读写非常简单并在代码中处理,而且可能非常快。

Properties.Settings.Default.PropertyName = propertValue;

阅读

var propertValue = Properties.Settings.Default.PropertyName;