用 COBOL 编写的 WPF 应用程序(适用于 Visual Studio 扩展开发人员)





0/5 (0投票)
面向 VSX 开发人员的实用工具,或者面向希望了解 WPF 应用程序的 COBOL 开发人员
引言
在 Visual Studio 2010 中,Microsoft 推出了托管扩展框架,作为提供和使用 Visual Studio 服务的一种简便方法,使得扩展编辑器等核心 VS 组件变得非常容易。有一个小问题——在 VS\Common7\IDE\Extensions 子目录下安装的扩展组件,在使用 /rootsuffix exp 开关启动 Visual Studio 时不会被绕过。
Visual Studio 中的 EXP hive 提供了一种加载您正在开发的、不想安装到用于开发该扩展的生产版本 Visual Studio 中的扩展的方式。其示意图如下:

当您在 EXP hive 下加载一个包时,您不希望同时加载其生产环境的同类包。将两个相似的程序集加载到同一个进程中会导致各种不可预测的问题。Visual Studio 中较旧的基于 COM 的包加载机制通过创建一个单独的注册表 hive(其键名带有 exp 后缀)来确保这种情况不会发生。
Visual Studio 通过扫描几个已知位置的 extension.vsixmanifest 文件来查找 MEF 扩展。这些清单是 XML 文件,用于命名 Visual Studio 应加载的包和 MEF 扩展。其中一个已知位置是 \program files\Microsoft Visual Studio 2010\Common7\Ide\Extensions。在此位置下方子目录中找到的任何清单总是会被 Visual Studio 加载。
另一个已知位置是 C:\Users\user\AppData\Local\Microsoft\VisualStudio\10.0Exp\Extensions(这是 Windows 7 下的位置——在其他 Windows 版本下可能略有不同)。只有在使用 /rootsuffix exp 开关启动 Visual Studio 时,才会扫描此位置下的子目录。
问题在于——“program files\Visual Studio”下的清单中列出的任何 MEF 组件,即使有您实际感兴趣进行调试的开发组件在 AppData 下,当您使用 /rootsuffix exp 启动 Visual Studio 时,它们总是会被加载。您只能通过编辑“program files\Visual Studio”下的清单以删除对 MEF 组件的引用来阻止这种情况发生。
MEF Switch 提供了一种简单的方法来查看您的 extension.vsixmanifest 加载了哪些 MEF 组件,并轻松地启用或禁用它们。这是一个用 Visual COBOL 编写的简短 WPF 应用程序。您可以从这里获取 Visual COBOL 的试用版: http://vs2010.microfocus.com/visual-cobol.html。或者,如果您愿意,可以下载本文随附的 COBOL 代码并将其转换为 VB 或 C#。由于此实用工具仅使用标准的 .NET 框架功能,而不是 COBOL 易于处理的功能(如 38 位十进制算术或索引文件处理),因此这应该不难。
背景
extension.visxmanifest 文件看起来是这样的:
<?xml version="1.0" encoding="utf-8"?>
<Vsix xmlns:xsi=http://www.w3.org/2001/XMLSchema-instance
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns="http://schemas.microsoft.com/developer/vsx-schema/2010" Version="1.0">
<Identifier Id="67D5C168-3C41-41F3-A048-F82676A7143B">
<Name>Some Visual Studio Package</Name>
<Author>Sherlock Holmes</Author>
<Version>1.0</Version>
<Description>Detects Moriarty, edits clues</Description>
<Locale>1033</Locale>
<Icon>VSIXProject_small.png</Icon>
<PreviewImage>VSIXProject_large.png</PreviewImage>
<SupportedFrameworkRuntimeEdition MinVersion="4.0"></SupportedFrameworkRuntimeEdition>
<SupportedProducts>
<VisualStudio Version="10.0">
<Edition>VST_All</Edition>
<Edition>Pro</Edition>
</VisualStudio>
</SupportedProducts>
<InstalledByMsi>false</InstalledByMsi>
</Identifier>
<References />
<Content>
<VsPackage>Sherlock.Holmes.Package.pkgdef</VsPackage>
<ProjectTemplate>ProjectTemplates</ProjectTemplate>
<ItemTemplate>ItemTemplates</ItemTemplate>
<MefComponent>MF.COBOL.Editor.Mef.dll</MefComponent>
<MefComponent>MF.COBOL.Editor.dll</MefComponent>
</Content>
</Vsix>
MEF Switch 所做的就是查找 MefComponent
元素,并将其显示给您。如果您想禁用它们,它会将它们注释掉。它会通过取消注释来重新启用它们。在从事 MEF 扩展一段时间后,我发现将 MEF Switch 放在桌面上某个地方运行,比反复研究和编辑 XML 文件,是查看和更改扩展是否将从 Program Files\Visual Studio 加载的一种更简便的方法。由于它编辑的清单位于 program files 目录下,因此在 Vista/Windows 7 上,您需要以管理员权限启动编辑器才能保存更改。我通常在开发会话开始时以管理员权限启动 MEF Switch,并一直运行直到完成。它不会锁定文件,并且每次更改都会自动保存清单。更改项目状态对任何已运行的 Visual Studio 实例都没有影响——清单只在启动时读取。
Using the Code
MEFSwitch 运行时看起来是这样的:

它只读取一个 extension.vsixmanifest 文件,该文件基于相对于您的 Visual Studio 安装目录的路径。这个相对路径是硬编码的,因为我们的产品结构只有一个扩展目录,我假设这相当普遍。使其能处理单个清单意味着启动时一切都已准备就绪,但如果这对您不起作用,请随时修改代码。相对路径存储在 VsixManifest.cbl 文件中的一个级别 78 项(在 COBOL 中表示 const
)中,称为 VC-EXTENSION-PATH。
列表视图显示了清单中当前列出的所有 MEF 组件。True 表示它们将在下一个启动的 Visual Studio 实例中加载,False 表示它们在清单中被注释掉了,将被跳过。双击状态可更改它,或单击任一按钮可更改所有状态。无论哪种方式,更改都会立即保存到清单文件中。更改项目的状态不会影响任何已运行的 Visual Studio 实例——清单只在启动时读取。
MEF Switch 包含三个重要类:
VsixManifest
类代表 extension.vsixmanifest。它在启动时使用框架中的XmlDocument
类读取 XML 文件,并创建一个包含MefItems
的ObservableMefList
。MefItem
类描述了清单文件中的单个MefComponent
条目。它有一个名为 Enabled 的 WPF 依赖项属性,该属性会使应用程序窗口中的ListView
保持更新。ObservableMefList
定义在同一个源文件中——它只是继承自ObservableCollection
,并将泛型参数设置为MefItem
。- Window1 是 WPF 窗口,其中包含一个文本框显示已读取的清单的位置,以及显示项目的
ListView
。ctor
设置列表视图以显示网格,读取清单(使用VsixManifest
类),并将列表视图绑定到ObservableMefList
。它有一个事件处理程序,每次双击列表视图中的项目时会切换MefComponent
的状态,以及为两个按钮提供的事件处理程序。
关注点
我为什么要用 Visual COBOL 编写这个?主要是为了表明像这样的 WPF 应用程序可以用任何 .NET 语言编写,而且我厌倦了看到文章、博客等充斥着关于 COBOL 如何多余和冗长。我认为,如果将此应用程序翻译成 Visual Basic,在 Visual COBOL 中它不会更短,在 C# 中也不会短多少。所以我想我在这里做了一个论证。
历史
- 2010 年 9 月 19 日:初始版本