本文共 7135 字,大约阅读时间需要 23 分钟。
目录
注意:提供了SSMS 18教程的更新版本。
这将是如何开始创建SQL Server Management Studio 17(SSMS)扩展的绝对的初学者指南。如果您不知道从哪里开始创建自己的扩展,那么您来对地方了。它将只涵盖为从头开始开发SSMS扩展而设置开发环境的基础知识。
如果您想跳过我的悲伤故事以及我创建本教程的原因,您可以转到“要求”部分,直接跳转到项目。
注意:本教程是为了扩展最新版本的SQL Server Management Studio而创建的,该版本在撰写本文时为17.6。扩展旧版SSMS的过程应该类似。
我想要的只是创建一个简单的SQL Server Management Studio(SSMS)扩展来简化已经是一个简单的操作,而此操作我每周重复几次。我想,它有多难......这只是一个简单的操作。您单击菜单上的某个按钮,会发生一些简单的事情。我想,这将是简单而直接的。这将是一个有趣的项目。我知道存在SSMS扩展。它们不是很多,不像Visual Studio那样多,但确实存在。必须有一些好的初学者教程......必须有一个体面的文档解释所有的点点滴滴,提供一些示例代码。我只需要谷歌搜索一下,几个小时后可以继续前进。
孩子,我错了!那里没有任何东西。有关创建SSMS扩展的文档不存在。可用的教程很少,而且很遗憾,其中大多数都太旧了,解释了不再支持的旧的加载项系统,所以不幸的是它们几乎没用。所有存在的只是分散在互联网上的不完整的知识和记录的经验。
好吧,我想,回到原点。我知道Visual Studio有很多扩展,我知道SSMS 17基于Visual Studio 2015 Isolated shell。因此,也许Visual Studio扩展的教程可以帮助我开始。好吧,不是真的。一旦你启动并运行它们就会有所帮助,但是没有一个教程可以向我解释如何让SSMS扩展项目继续进行。
希望对其他人来说,这就是教程......
正如您将在下面看到的那样,该过程远非简单或直观,并且可能非常快速地变得非常棘手。让我们开始吧。
您只需要安装带有Visual Studio扩展工具的Visual Studio。这将使您能够在创建新的Visual Studio项目时使用VSIX项目模板。如果安装了Visual Studio但没有可扩展性工具,则可以通过“控制面板”中的“程序和功能”将它们添加到当前安装中。
我建议使用Visual Studio 2015,因为我在使用Visual Studio 2017时遇到了引用和依赖的问题。由于SSMS 17.X基于Visual Studio 2015 Isolated shell,我认为这可能是此类项目的更兼容的版本并决定坚持下去。如果您是一位经验丰富的用户,那么您可以使用Visual Studio 2017。
首先,我们将首先创建一个简单的Visual Studio扩展,然后将其移植到SSMS。要创建新的Visual Studio扩展,首先转到文件>新建>项目...然后选择已安装>模板> Visual C#>可扩展性> VSIX项目并命名HelloWorldSsmsExtension。
为了给我们的扩展提供一些功能,我们将在解决方案资源管理器中右键单击我们的项目,选择Add> New Item ...然后选择Visual C#Items> Extensibility> VSPackage> Custom Command并命名它HelloWorldCommand。
只要Visual Studio创建了该命令,就Visual Studio扩展而言,我们就会做的非常好。构建项目,在HelloWorldCommand类的MenuItemCallback方法(HelloWorldCommand.cs)中的某个地方放置一个断点并点击Start。
应该启动一个新的Visual Studio实例(实验实例),我们可以在工具菜单中找到名为“Invoke HelloWorldCommand”的命令(如果这是你第一次这样做,你可能需要通过Visual Studio的实验实例初始化设置向导)。如果我们现在尝试单击该命令,我们应该看到原始实例中的断点被命中,并且由于我们的命令代码而出现一条消息。
我们现在可以关闭消息框和实验实例,更改消息以显示“来自SSMS扩展的Hello World!”,然后再次尝试查看更改是否生效。启动调试会话,然后再次单击该命令。它现在应该显示新消息。
很简单吧?嗯,这是容易部分的结束和问题开始的地方。
好的,现在让我们尝试将我们的扩展移动到SSMS。我们要做的第一件事是在开始调试时启动SSMS而不是Visual Studio。为此,我们首先需要关闭Visual Studio并重新启动它,但这一次,以管理员身份运行它(我们需要这样做,因为Visual Studio需要移动一些文件并执行此操作,我们需要管理权限) 。进入Visual Studio后,再次打开解决方案,在解决方案资源管理器中右键单击该项目,然后选择“属性”。
在“调试”选项卡中,通过将“启动外部程序”属性更改为:将外部程序更改为SQL Server Management Studio而不是Visual Studio :
C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Ssms.exe
另外,一个好主意(但不是必需的)是在“命令行参数 ”字段中设置/log参数,以使SSMS将其活动记录到文件中,这可以帮助我们排除故障。可以在以下位置找到日志文件(ActivityLog.xml):
C:\Users\Username\AppData\Roaming\Microsoft\AppEnv\14.0
所以,既然我们已经完成了所有设置,我们可以尝试再次启动扩展。如果我们在Visual Studio中开始调试,我们现在应该看到SQL Server Management Studio在我们点击“开始”按钮时启动。等待它完全启动,当它关闭Connect to Server窗口时。好的,所以SQL Server Management Studio确实启动了,但我们的命令在工具菜单中找不到。
此外,如果我们回到Visual Studio,我们可以看到我们的断点没有激活。
这里不对劲。好吧,SSMS在启动时会查找扩展名:
C:\Program Files (x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Extensions\
如果我们去那个地方,我们可以看到我们的扩展不在那里。如果我们希望SSMS加载它,我们的扩展需要在这里。所以,让我们解决这个问题。再次打开项目的属性窗口,这次打开VSIX选项卡。在其中,选中“将VSIX内容复制到以下位置”,然后在文本框中输入SSMS Extensions文件夹。在该位置的末尾,我们将添加一个包含扩展名称的文件夹,因此完整位置应如下所示:
C:\Program Files(x86)\Microsoft SQL Server\140\Tools\Binn\ManagementStudio\Extensions\HelloWorldSsmsExtension
再次开始调试并等待SSMS打开。看起来我们的扩展程序仍无法正常工作,但如果我们转到extensions文件夹,我们可以看到新创建的文件夹。那么为什么我们的扩展没有加载?如果查看活动日志,可以看到SSMS正在导入.pkgdef文件而不是其他内容。一切都应该没问题,但事实并非如此。
您可以看到,Microsoft的SSMS团队列出了允许SSMS加载的所有扩展。它只是一个白名单中的的包GUID列表,由这些GUID标识的包(扩展)被加载到SSMS中没有问题。SSMS不会加载任何其他内容。我在某处读过,其原因是SSMS团队不希望SSMS充斥着无关的扩展。另一个地方说微软最终应该包括对SSMS扩展的官方支持,这在未来不应成为问题。但是在此之前,如果我们希望加载扩展程序,我们必须使用解决方法解决此问题(或者您可以联系Microsoft的SSMS团队并要求他们将您的扩展程序列入白名单)。那么,这个包GUID是什么?我们如何解决这个问题呢?
包GUID只不过是您的扩展的唯一标识符,它可以在我们的项目中的两个位置找到。第一个是在HelloWorldCommandPackage类中:
public const string PackageGuidString = "c626db04-880e-41bf-b780-ab5804d1ea2f";
另一个是在HelloWorldCommandPackage.vsct文件中:
要解决验证问题,我们需要在尝试启动时明确告诉SSMS跳过此程序包的验证。为此,遗憾的是我们需要稍微编辑注册表。要打开注册表编辑器,首先我们需要通过按键盘上的Windows + R打开“运行”窗口。在其中,键入regedit并单击“确定”。
注册表编辑器打开后,转到:
HKEY_CURRENT_USER\Software\Microsoft\SQL Server Management Studio\14.0
在其中,检查是否有“Packages”键,如果没有,请通过右键单击14.0然后选择New> Key来创建它。
在(新创建的)Packages键中,创建一个新键,扩展名的包GUID用花括号括起来作为其名称。键名应如下所示:
{c626db04-880e-41bf-b780-ab5804d1ea2f}
在新密钥(包含GUID作为其名称的密钥)中,通过右键单击该密钥并选择“新建”>“DWORD(32位)值”来添加新的DWORD(32位)值。
创建值后,右键单击它并将其重命名为SkipLoading。在此之后,我们的最后一步是通过右键单击new(SkipLoading)值并从上下文菜单中选择Modify ...将值设置为1。
只需在“值数据 ”字段中输入1,然后单击“确定”。
您现在可以关闭注册表编辑器。如果我们正确地执行此步骤,我们的扩展应该在我们开始调试时最终加载到SSMS中。回到Visual Studio并试一试。太好了,我们的命令就在这里,工作得很好。此外,当我们尝试运行它时,我们可以看到我们的Visual Studio断点命中,最后一切都很好。
好吧,不是真的!
问题是......如果SSMS正确加载扩展并且我们通过运行它来初始化它,那么SSMS将从注册表中删除SkipLoading值,并且我们的扩展将在下次启动SSMS时不起作用。这很容易检查。再次转到注册表编辑器,自己查看包密钥中缺少的SkipLoading值。
只有在SSMS尝试初始化扩展时才会发生这种情况,默认情况下,当你第一次运行扩展时会发生这种情况。如果你再次添加SkipLoading,一切都会再次运行,并且在开始调试时会加载扩展。如果在不运行命令的情况下关闭SSMS,则SSMS将不会初始化您的扩展,并且不会从注册表中删除该值。但是,当我们尝试开发命令并在每次运行之间在注册表编辑器中重新设置值时,不运行不是一个选项,这太耗时了。为此,我们需要另一种解决方案和另一种解决方法。我们将打开HelloWorldCommandPackage类并在其中添加以下方法:
// Call this method from the Initialize method// to add the SkipLoading value back to the registry// 2 seconds after it’s removed by SSMSprivate void AddSkipLoading(){ var timer = new Timer(2000); timer.Elapsed += (sender, args) => { timer.Stop(); var myPackage = UserRegistryRoot.CreateSubKey(@"Packages\{" + PackageGuidString + "}"); myPackage?.SetValue("SkipLoading", 1); }; timer.Start();}
注意:要使用它,我们还需要导入 System.Timers 命名空间:
using System.Timers;
我们在方法结束之前调用Initialize()方法。
////// Initialization of the package; this method is called right after the package is sited, /// so this is the place/// where you can put all the initialization code that rely on services provided by VisualStudio./// protected override void Initialize(){ HelloWorldCommand.Initialize(this); base.Initialize(); AddSkipLoading();}
最终结果应如下所示:
我们添加的方法在Initialize方法完成2秒后恢复包的SkipLoading键,SSMS从注册表中删除值。我们添加2秒延迟,以便我们确保在SSMS有时间删除之前我们不会恢复该值。这将使我们最终开始开发我们的扩展。如果我们启动SSMS但不运行命令,一切都很好,因为扩展没有初始化,SSMS没有删除该SkipLoading值。如果我们运行命令并且扩展程序初始化,那么代码将在SSMS删除它之后重新设置该值。所以下次我们启动SSMS时我们的扩展应该加载得很好。我们可以通过在Visual Studio中点击Start来尝试这一点,最后开始开发我们全新的扩展。
假设您完成了扩展程序的开发,并希望将其发送给朋友或同事。这很简单。只需压缩位于SSMS Extensions文件夹中的HelloWorldSsmsExtension文件夹,发送它,并告诉他将其放在同一位置。但是,如果你不想让自己难堪,告诉他如何做注册表编辑器的黑客只是让你的扩展第一次进行(请记住,扩展本身将在加载后设置SkipLoading值)。
事实证明,我们可以让SSMS为我们设定这个值。回顾一下......如果你的扩展没有通过SSMS验证,那么SSMS启动时就不会加载它。但是,要让SSMS知道您的扩展名是否为白名单,它至少必须读取构建扩展时生成的.pkgdef文件(包含包GUID以及其他配置信息)。在其中,我们可以为SSMS发出指令,以便在启动时自动加载扩展。有了这个指令,SSMS不会在加载扩展时静默失败,而是会抛出一个错误,我们可以使用它来设置SkipLoading值。在错误消息中,SSMS会抱怨扩展程序出现问题,并询问您是否应继续显示错误。如果选择“ 否”,则SSMS将自行添加SkipLoading值,但遗憾的是,在启动时不会加载扩展名。但是,下次启动SSMS时,该值将存在,从那时起,扩展本身将负责其在注册表中的存在。换句话说,您只需要在选择“否”后重新启动SSMS,从那时起一切都会好起来。
要将指令添加到.pkgdef文件,您需要做的就是将具有NoSolution上下文GUID 的ProvideAutoLoad 特性添加到您的HelloWorldCommandPackage类中。
[ProvideAutoLoad(UIContextGuids80.NoSolution)]
最终代码应如下所示:
这将迫使SSMS在启动时加载您的扩展,它将失败并且它将询问它是否应该继续显示错误。您选择否,重新启动SSMS,您应该看到您的扩展加载并正常工作。这只是SSMS的第一次启动才有问题。但是,嘿,这是我们现在得到的最好的东西。因此,当您将扩展程序发送给朋友时,只需告诉他们选择否并在第一次后重新启动SSMS,从那时起一切都会正常。
这是开始开发SQL Server Management Studio 17扩展时所需要知道的全部内容。对于旧版本的SSMS,该过程应该类似。如果有人有任何其他有用的提示,请随时与我联系,我会尝试在本教程中介绍它们。该HelloWorldSsmsExtension完整代码也可从github下载,地址如下:
注意:如果要尝试附加项目(或github上的项目),则需要首先在项目属性中设置“启动外部程序”属性。
就这些...
这些是我用来帮助我入门的资源,值得查看以获取更多信息:
还有一些github项目可以用来获得更多想法:
原文地址:
转载地址:http://hjzhj.baihongyu.com/