VS2019 基础知识(二)

原文:Essential Visual Studio 2019

协议:CC BY-NC-SA 4.0

五、在 Visual Studio 2019 中使用 Git

不使用某种形式的源代码控制的现代开发是不可想象的。虽然有很多选择,比如 Subversion、Mercurial 和 CVS(并发版本系统),但是粗略地看一下不同产品的流行程度,Git 似乎更有优势。取决于你如何计算不同的东西,GitHub(托管 Git 库的最受欢迎的站点)的受欢迎程度似乎是下一个托管站点的七倍。即使考虑到计数的差异,也可以相当安全地得出结论,Git 正被数百万开发人员使用,以托管从爱好网站到开源项目到商业产品的一切,所有这些都支持本章的前提,即专注于 Visual Studio 2019 为使用 Git 的开发人员提供的工具。

将 Git 与 Visual Studio 集成

对 Git 的详细描述远远超出了本书的范围。事实上,它将采取自己的书做公正。幸运的是,有这样一本书,在 Git 的文档部分( https://git-scm.com/book/en/v2 )找到。这本书名为 Pro Git ,也由 Apress 出版社出版,在 Amazon.com 上可以买到。

本章假设读者熟悉基本的 Git 概念,比如存储库、提交、分支、标签和拉请求。如果提到不寻常的东西,会有描述。但是对于基础的部分,将会假设一个基本的知识水平。

Visual Studio 2019 提供了几个组件,使您能够轻松地与 Git 进行交互。但是,这些组件不会随任何当前工作负载一起安装。为了使用 Git,您需要添加几个组件。

首先,启动 Visual Studio 安装程序。在第一个屏幕上(图 5-1 ,您应该会看到您已经安装在系统上的 Visual Studio 实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-1

Visual Studio 安装程序

在要添加 Git 支持的实例旁边,单击 Modify 按钮。这将打开表单(图 5-2 ),允许您修改 Visual Studio 2019 的工作负载、组件和语言包。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-2

为安装选择 Git 组件

在“单个组件”部分,向下滚动,直到到达“代码工具”部分。在那里,你会看到两个与 Git 相关的组件:Git for Windows 和 GitHub extension for Visual Studio。当然,您也可以在左栏顶部的搜索栏中输入Git来归档所需的组件。

确保选中这两个组件,然后单击右下角的修改按钮。这将启动安装过程。

安装完成后,安装完组件后,已安装的 Visual Studio 实例列表可能会重新出现。您可能会看到一条消息,指出有可用的更新。此消息通常意味着 Visual Studio 安装程序检测到有新版本的 Visual Studio 可用。更新不一定与添加的组件相关。单击查看详细信息链接并阅读发行说明以确保。

创建和克隆 Git 存储库

作为一个源代码控制系统,Git 的基本目的是跟踪一段时间内对一组文件所做的更改。这些文件可以在项目中,也可以是解决方案的一部分,或者只是在文件夹中。这些信息存储在称为存储库的文件集合中。存储库的详细信息存储在.git文件夹中。

另外,Git 是一个分布式源代码控制系统。实际上,这意味着项目没有中央存储。相反,无论项目在哪里,存储库都存在。在服务器上,有一个存储库。在客户端,有一个存储库。当您推送您的更改时,您正在将客户端上的存储库中的更改移动到服务器上的存储库中。当您克隆一个存储库时,您是在服务器上获取该存储库并将其复制到客户端。请记住,存储库包括所有文件。

Visual Studio 2019 支持 Git 库的创建和克隆。这两个操作中的一个是在开发中开始使用 Git 的关键。我们将通过创建一个新项目并将其添加到源代码控制中来创建一个 Git 存储库。这不是创建 Git 存储库的唯一方法。Git 命令行包含一个init命令,它也可以创建 Git 存储库所需的文件。但是我们将演示 Visual Studio 如何做到这一点。

创建 Git 存储库

正如本章前面提到的,Git 存储库是存储在文件和文件夹集合中的版本信息。关键是在适当的位置创建适当的文件。Visual Studio 2019 提供了一种直观的方式来实现这一点。

首先,创建一个全新的项目。这可以通过使用文件➤新➤项目菜单项来完成。在新建项目对话框中(图 5-3 ,选择 ASP.NET 核心 Web 应用的项目模板,点击下一步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-3

创建新项目

在下一个对话框中(图 5-4 ,提供项目名称和位置。您可能还会注意到,有一个“将解决方案和项目放在同一目录中”选项已经被选中。这不是默认设置,但在这里使用,以便项目的所有文件都在一个文件夹中。这使得将文件传输给其他人变得更容易,就像作为书籍下载的一部分。

提供值后,单击创建转到创建应用的下一步。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-4

配置新项目

最后一步是选择用于创建 web 应用的模板,如图 5-5 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-5

选择 ASP.NET 核心 Web 应用模板

该示例将使用 Web 应用,以避免在不同技术的支持者之间引发激烈的争论。但是请注意,Git 对您使用的模板类型是完全中立的,就像它对您用来构建项目的语言或部署中使用的底层技术是中立的一样。Git 是关于存储作为项目一部分的工件。你想用这些艺术品做什么是不可知的。

现在您已经有了一个要处理的项目,让我们看看为它创建一个 Git 存储库的相关步骤。

你实际上有很多选择。最简单的可以在 Visual Studio 的右下方找到(见图 5-6 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-6

添加到源代码管理

当您单击“添加到源代码管理”标签时,将出现已配置的源代码管理环境列表。图 5-6 显示 Git 是一个选项,如果你已经安装了本章前面描述的 Git 工具,就会出现这种情况。如果您在 Visual Studio 中配置了其他源代码管理工具,它们也会出现在此列表中。

一旦单击 Git,Visual Studio 就会在幕后创建所有必需的文件夹和内容。一旦完成,这应该只需要一分钟左右,Visual Studio 的右下角将如图 5-7 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-7

Git 存储库的状态栏

左边的标签是当前存储库的名称。单击标签将在团队资源管理器中打开存储库。名称右侧是当前分支。单击分支会提供许多选项来管理分支,这将在本章稍后讨论。

请注意,您刚刚创建的 Git 存储库只存在于您的机器上。它尚未保存到中心位置。因此,虽然您可以执行许多有用的操作,比如放弃对以前提交的项目的更改,但是如果您的机器发生问题,您仍然有可能丢失您的工作。为了防止这种情况,有必要将您的代码推到一个中央存储库中。一旦存储库被创建,随着状态栏的改变,团队资源管理器中的推送窗格(图 5-8 )被打开。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-8

团队资源管理器中的推送窗格

在推送窗格中,有三个可能的目的地来推送可见的代码。首先是 Azure DevOps。这是一个与微软 Azure 相关联的托管服务(也许从名字就可以看出来)。它使用您随 Visual Studio 提供的凭据来访问适当的帐户,并且您可以存储无限数量的私有存储库。如果您希望配置您的存储库以便其他人可以使用它,您最终可能需要付费使用该站点。

第二个选择是 GitHub。这可能是世界上最受欢迎的公共 Git 存储库站点,托管着数十万个项目。与 Azure DevOps 一样,免费托管的网站种类也有限制(公共或私人回购可以有最多三个合作者才能免费),但更广泛的情况下有付费选项。

最后一个选项更加通用。它允许您指定远程 Git 存储库的 URL。URL 应该代表远程服务器上现有的空存储库。例如,这个选项允许您使用 Git 存储库的企业实例作为远程存储点。

虽然对于还没有 Git 存储库的项目,状态栏底部提供的选项非常好,但是如果您不是从一个项目开始,还有其他一些方法可以使用。

起点是团队资源管理器,可以使用“查看➤团队资源管理器”菜单选项或使用键盘快捷键(Ctrl+\,默认为 Ctrl+M)来启动它。然后点击工具栏中的绿色插头以显示连接窗格,如图 5-9 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-9

团队资源管理器中的连接窗格

与 Push 窗格一样,有三个地方可以创建 Git 存储库。在底部,您可以看到任何本地 Git 存储库的列表。要创建新标签,请单击新标签。这将显示一个文本框,如图 5-10 所示,其中可以指定 Git 存储库的路径。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-10

指定存储库的路径

输入所需路径后,单击“创建”创建存储库。

图 5-9 中的另外两个部分与 Azure DevOps 和 GitHub 有关。对于 GitHub,您可以使用 GitHub 标签下的链接创建一个存储库。首先,您需要向 GitHub 提供您的凭证,如果您在之前的会话中还没有这样做。当您点击登录链接时,系统会提示您输入 GitHub 用户 ID 和密码。登录后,您可以通过单击“创建”来创建存储库。出现如图 5-11 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-11

创建 GitHub 存储库

该对话框中的前三个字段可能是您所期望的。它们是存储库的名称和描述,以及存储库在 GitHub 中创建后将被克隆到的本地路径。接下来的两个字段有点不同,需要一些解释。

Git ignore 选项是一个下拉列表,用于选择应该包含在存储库中的.gitignore文件。对于外行来说,.gitignore文件是一个模式集合,它定义了不应该包含在存储库中的文件和文件夹。在 Visual Studio 世界中,一个不应该提交的常见文件是.suo文件。这是一个包含特定于当前用户的 Visual Studio 解决方案设置的文件。因为它对于每个开发人员来说都是唯一的,所以它是一个不应该提交到存储库中的文件,因此应该包含在.gitignore文件中。下拉列表包含了.gitignore文件的不同模板列表。而且有很多。虽然默认设置是 Visual Studio,但是由于存储库的创建方式,请确保选择最适合您正在创建的项目的设置。但是也要注意,在.gitignore文件创建之后,您可以随时更改它。

下一个字段是您的项目将使用的许可证。默认情况下不选择许可证,但是如果您预计在某个时候您的项目将被商业使用或成为开源项目的一部分,您可能希望从下拉列表中选择最合适的许可证。再说一遍,你做的决定不是不可改变的。这只是你项目的一个起点。

一旦您提供了所有必要的信息,包括将成为存储库所有者的用户(图 5-11 中包含 LACanuck 的字段)和指定这是公共还是私有存储库的复选框,单击 Create 创建存储库。同时,存储库将被克隆到您的机器上,位于您指定的路径下。

第二组与 Azure DevOps 相关,在创建 Git 存储库时没有用。虽然你可以克隆已经在 Azure 中的存储库,但是你不能通过这个接口创建一个。这种情况下的解决方案是创建一个本地 Git 存储库,然后将其推送到 Azure DevOps。

克隆 Git 存储库

当谈到克隆 Git 存储库时,有许多途径可以实现。其中最直接的一个就发生在你启动 Visual Studio 2019 的时候。图 5-12 是启动屏幕的一个例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-12

Visual Studio 2019 启动屏幕

右边是四个按钮的集合,这四个按钮是开发人员的常见起点。这包括打开一个项目和创建一个新项目。最顶端是能够克隆或检出代码的选项。点击该按钮将显示图 5-13 ,用于指定要克隆的存储库的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-13

克隆或检出项目

对于任何一个任意的存储库,都会有一个标识位置的 URL。该 URL 需要在第一个文本框中输入,而第二个文本框包含本地机器上的路径。单击“克隆”按钮时,在特定位置找到的存储库将被克隆到指定的路径中。除了所有的项目工件之外,还将建立本地和远程存储库之间的上游链接。这个链接使得将提交从本地推送到远程存储库变得更加容易。

除了这两个文本框之外,在 Browse a repository 标签下还有另外两个链接,如果您不知道合适的 URL,它们可以让您找到存储库。

如果你点击 Azure DevOps 链接,你会被带到一个类似图 5-14 的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-14

浏览 Azure DevOps 帐户

顶部是一个下拉列表,包含您已添加到计算机的不同 Microsoft 帐户。当选择一个帐户时,可访问的不同 Azure 帐户出现在占据对话框大部分的树中。在这里,您可以导航到您正在寻找的存储库。当您选择存储库并单击对话框底部的连接时,将出现 Visual Studio IDE 并显示团队资源管理器窗格(图 5-15 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-15

团队资源管理器的主页窗格

如前所述,有多种方法可以克隆 Git 存储库。刚刚描述的工作流在您第一次打开 Visual Studio 时可用。但是,也可以从 Visual Studio 2019 IDE 本身中访问该流。如果使用文件➤克隆或检出代码菜单选项,出现如图 5-13 所示的对话框,所述流程从那里继续。

团队资源管理器提供了一个完全不同的流程。首先,点击工具栏中的插头图标,导航至连接窗格(图 5-16 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-16

团队资源管理器中的连接窗格

在此窗格中,您有两种不同的方法来克隆存储库。在顶部的 GitHub 部分下面,有一个克隆选项。点击该选项的结果是一个屏幕(图 5-17 ),让您在 GitHub 上找到一个存储库,然后将其克隆到您的本地机器上。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-17

从 GitHub 克隆

在此对话框中,会出现一个存储库列表,您可以从中进行选择。在那里,存储库或者是您的,属于您被添加到的组织,或者是您被添加到的项目。当然,这假定您有一个 GitHub 帐户。首次访问该对话框时,系统会提示您登录 GitHub。

如果您想要克隆的存储库不在列表中,您可以在对话框顶部提供它的 URL。同样,您可以在顶部文本框中输入一个搜索词。但是,搜索仅在列表中显示的存储库中执行。如果你想在 GitHub 中搜索库,你需要访问 GitHub 并直接在那里搜索。

对话框底部的文本框是存储库将被克隆到的本地路径。一旦提供了所有必要的信息,克隆按钮就会变为启用状态。单击它将启动克隆过程。

在 Connect 窗格的下半部分,有第二种克隆存储库的方法。在本地 Git 存储库标题下,有一个克隆选项。点击后,会显示一个类似图 5-18 的区域。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-18

克隆非 GitHub Git 存储库

所需的信息与您尚未关联的 GitHub 存储库所需的信息类似。在顶部的文本框(浅黄色背景)中,指定 Git 存储库的 URL。在第二个文本框中,指定将存储库克隆到的本地路径。右边的按钮(带有省略号)用于打开“打开文件”对话框。当提供这些信息时,克隆按钮被启用。单击它将启动克隆过程。递归克隆子模块复选框用于允许克隆子模块,如果它们是基本存储库的一部分。

Git Submodules

Git 中子模块背后的思想是将一个现有的存储库附加到另一个存储库的文件夹结构中。虽然这种机制有许多好处,但主要的好处是能够从多个存储库中引用一个存储库,并且当其他存储库愿意接受对这个存储库的更改时,可以将这些更改提供给其他存储库。

当您使用这些步骤中的任何一个步骤克隆了一个存储库之后,您将得到一个您可以修改的代码的本地版本。这被称为本地存储库或本地回购。该存储库还与作为克隆源的存储库相关联。该存储库被称为远程存储库或上游存储库。当您完成开发时,这种关系会变得很有用,如下一节所述。

提交和同步更改

一旦您在本地机器上有了 Git 存储库,通常的下一步包括进行修改、测试、进行更多的修改等等,直到您对自己的工作满意为止。虽然 Visual Studio 有一些工具可以帮助您(正如在前面和后面的章节中所介绍的),但是您使用 Git 的事实对您的开发工作流并没有太大的影响。嗯,至少没那么频繁。但是一旦你完成了你的代码,并准备将它转移到生产中,Git 肯定会参与进来。

第一步是将您的代码放入您的本地存储库中。这是通过执行“提交”来完成的

提交过程由两个独立的步骤组成。第一个是识别提交中要包括的文件。这就是所谓的暂存文件。第二个是在本地存储库中记录已识别的变更(即暂存文件)。

在 Visual Studio 2019 中,提交过程的起点是团队资源管理器中的提交窗格(图 5-19 )。可以通过单击团队资源管理器主窗格中的“更改”选项来访问它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-19

团队资源管理器中的更改窗格

中间的大部分标记为 Changes,是自上次执行提交以来添加、删除或修改的文件的集合。这些文件(或它们的子集)将是您提交的一部分。

在 Visual Studio 中,默认情况下,所有已更改的文件最初都被视为暂存文件。这是为了让开发人员更容易执行提交。开发人员执行的大部分提交包括所有更改的文件,因此这种优化通常会节省一个步骤。但是,您总是可以明智地选择要转移的文件。右键单击单个文件和文件夹,然后从上下文菜单中选择“转移”,即可转移这些文件和文件夹。当您暂存任何文件时,Visual Studio 开始时的假设(所有文件都应被视为暂存的)将被放弃,只有显式暂存的文件才有资格提交。图 5-20 显示了一些文件已经暂存的变更窗格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-20

包含一些暂存文件的“更改”窗格

除了添加文件和文件夹,您还可以通过单击“更改”标签右侧的加号来暂存整套更改。也可以通过单击单个文件并从上下文菜单中选择“取消登台”来取消登台已登台的文件。或者,可以使用暂存更改标签右侧的减号取消暂存所有暂存文件。

除了转移和取消转移文件之外,还有一种方法可以防止文件包含在提交中。那就是撤销所有已经做出的改变。如果您临时修改了一个文件(比如说,通过修改一个连接字符串),或者您正在进行一些实验性的开发,这将非常有用。也许你并不完全确定如何解决一个问题,在走了一条特定的路之后,你决定结果并不符合你的喜好。不管是什么原因,自上次提交以来对文件所做的更改都可以通过上下文菜单来撤消。在“更改”或“分段更改”部分中选择要还原的一个或多个文件。然后右键单击并从上下文菜单中选择撤消更改。几分钟后,最后提交的文件版本将替换当前文件。

此时,文件集合已经暂存。下一步是提交它们。从功能上来说,这包括用暂存文件中的更改更新本地存储库。就您采取的步骤而言,它们仍然在团队资源管理器的“更改”窗格中。

提交文件有一个必填字段。在图 5-21 中,顶部有一个文本框。如果留空,背景颜色为浅黄色。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-21

“更改”窗格中的“提交注释”字段

此字段用于为您的提交提供注释。注释与一组变更相关联,用于识别(至少在较高层次上)变更的原因,这意味着虽然在注释中加入一些简短且可能没有意义的内容很有诱惑力,但从长远来看,如果您努力保持注释有意义,它会更有用。

输入注释后,注释文本框正下方的提交暂存按钮将被启用。单击此按钮将暂存的更改提交到本地存储库。

该按钮的右边有一个下拉按钮。这是因为团队资源管理器在提交时为您提供了几个其他选择。

提交暂存的获取暂存的文件,并用更改更新本地存储库。

提交阶段和推送执行与提交阶段相同的功能。但是一旦提交完成,更改就会被推送到上游存储库。这相当于先执行一个git commit,然后再执行一个git push

提交阶段和同步通过执行与提交阶段相同的功能开始。接下来,将上游存储库中任何未完成的提交集成到您的本地存储库中。最后,任何更改都被推回到上游存储库。等效的命令是git commit后跟一个git pull,然后是一个git push

深入了解哪个命令适合您的环境超出了本书的范围。事实上,有一些资料可以帮助您理解如何在您的工作流中使用 Git。

但是,当我们讨论拉和推的主题时,您总是可以独立于提交代码来执行这些操作。在 Visual Studio 的右下方,如图 5-22 所示,有一个区域表示您当前的分支。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-22

状态栏上可用的 Git 命令

单击分支名称时,会出现一个包含多个选项的菜单。本章稍后将介绍分支和拉取请求选项。但是 Pull、Push 和 Fetch 命令与刚才描述的提交功能相关。

Pull 从上游存储库中检索任何提交,并将它们合并到您的本地存储库中。

Push 获取本地存储库中的任何提交,并将它们推送到上游存储库。

Fetch 从上游存储库中检索任何提交,并让您决定是否要将它们合并到本地存储库中。这类似于拉取,但是没有自动合并到您的本地存储库中。

隐藏

当你使用 Git 工作时,不可避免的是,你最终会面临以下情况:你一直愉快地工作在你自己的分支上,做出改变,让测试通过,等等;您被要求审查存在于另一个分支上的代码(或者某人需要帮助解决某个问题,或者您想出的任何其他需要改变分支的理由);不提交代码就不能切换分支,但是您的工作还没有准备好提交。如何在不丢掉工作的情况下换到想要的分支?

答案来自于隐藏功能的形式。通过隐藏您的更改,您可以在保存它们的同时从当前分支中删除它们,以便将来可以恢复它们。一旦更改不在您当前的分支中,您就可以不受惩罚地切换分支。在您完成了这个新分支上的工作之后,您可以回到您原来的分支(或者实际上是任何其他分支),并且用您保存的变更来更新那个分支。

隐藏功能的起点是团队资源管理器中的“更改”窗格。正如你在图 5-23 中看到的,在提交暂存按钮的右边有一个存储选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-23

在“更改”面板中隐藏菜单选项

第一个选项 Stash All 将所有的变更(不仅仅是阶段性变更…所有的变更)记录到一个 Stash 中。然后,它移除所有更改,将代码恢复到更改前的状态。如果您熟悉不同的 Git 客户端,您可能会看到这被称为放弃更改、撤销更改或恢复。第二个选项是 Stash All and Keep Staged,它记录所有的更改并保留任何已被登台的更改。未分级的更改将被反转。

一旦存储被创建,它就会出现在团队资源管理器中的 Changes 窗格的底部(图 5-24 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-24

团队资源管理器中的隐藏

每个存储都用最初创建它的分支以及提交消息来标识。

您可以对单个存储执行四个操作。右键单击贮藏处可获得这些选项。从出现的上下文菜单中,您可以执行以下操作:

View Changes 显示作为存储一部分的变更。它们以类似于“变更”窗格中的“暂存变更/变更”部分的格式显示。图 5-25 提供了图示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-25

存储详细信息

在这里,您可以看到已经转移的文件仍然与刚刚修改的文件分开。此外,还提供了存储库的描述、创建日期、存储库的版本,以及存储库基于哪个特定提交的指示符。表示存储基数的字符集合(在图 5-25 中,是 015f2ad9)是分支中最近完成的提交的散列的一部分。

Note

任何 Git 提交的散列都是提交的元数据的阿沙-1 散列,以及提交的内容。在 Git 中,散列被用作提交的惟一标识符。虽然完整的散列有 40 个字符长,但通常只是使用字符的子集来标识场景中的提交,如图 5-25 所示。

这些命令获取存储的内容并更新当前分支。这两个选项的区别在于分支更新后会发生什么。应用选项在更改完成后保留存储。Pop 选项会在更改完成后删除隐藏内容。

这两个选项都有两个额外的选择。图 5-26 显示了可用于应用的选项,但是 Pop 有同样的两个选择。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-26

应用隐藏选项

第一个选项是分阶段应用和恢复,用存储中的所有更改更新当前分支。然而,在存储中进行的变更也将在分支中进行。第二个选项,Apply All as Unstaged,用所有的变更更新当前的分支,但是即使变更在 stash 中被登台,它们也将在分支中被登台。

Drop 你可以使用的第四个命令实际上是从你的仓库中删除了毒品。当前分支中不会更新任何内容,该选择是永久性的。没有一种机制可以撤销一个存储的删除。

全部丢弃如果您的存储库中有多个存储,您还会看到一个全部丢弃选项。此选项不仅会删除当前选定的贮藏,还会删除所有其他贮藏。

使用分支和标签

前一节提到了分支,特别是作为关于隐藏的讨论的一部分,但并没有真正深入到它们是什么的任何细节,当然也没有触及如何在 Visual Studio 2019 中操纵它们。本节纠正了这种情况。

如果您熟悉 Git(或任何最常用的源代码控制系统),那么您对分支的概念并不陌生。如果您是 Git 的新手,那么考虑分支的最佳方式是一个独立的开发流。图 5-27 展示了一个简单的分支示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-27

简单分支

图 5-27 中有两个分支:特征Master 是 Git 中默认分支的名称。考虑顶行上的每个圆圈,以指示对分支的不同提交。在第二次提交之后,基于主服务器的当前状态,创建一个新的分支。那个分支叫做特征。现在,开发可以在特征上彼此独立地进行。如果事情在特征中严重出错,那么该分支可以被丢弃,而不会影响。或者更有可能的情况是《??》中的工作是成功的。在这种情况下,功能的变化可以合并回中,这样每个人都可以分享你的成功。

Git 的优势之一是能够快速创建新的分支,以及从一个分支移动到另一个分支。这给了开发人员很大的自由去试验不同的解决方案,安全地丢弃那些不工作的。或者你可以从处理一个特性转移到修复一个不同分支中的 bug,完成后很容易再回来。当然,Visual Studio 中的 Git 支持允许您利用所有这些能力。

创建分支

使用分支的第一步是创建它。Visual Studio 为您提供了许多不同的机制来实现这一点,具体取决于您的工作环境。功能最全的选项来自团队资源管理器。图 5-28 显示了团队资源管理器中的分支窗格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-28

团队资源管理器中的分支窗格

“分支”页面显示了本地存储库和远程存储库中定义的所有分支。该列表由活动储存库进一步分离。在图 5-28 中,有一个单独的活动存储库,称为 EssentialV2019。在该存储库的本地版本中,有两个分支,主和 159-Break _ version _ number _ into _ parts。当前检出的分支(即当前正在处理的分支)的名称是粗体的。远程存储库由 remotes/origin 节点表示,在该存储库中有许多分支。

要创建新分支,请单击分支标题下方的新分支链接。窗格的顶部展开以提供必要的选项,如图 5-29 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-29

“分支”窗格中的新分支信息

为了创建一个分支,需要提供两条信息。首先,在顶部的文本框中输入新分支的名称。然后,确定分支的基础。分支名称的正下方是一个下拉列表,其中包含您可以使用的所有分支,包括本地分支和远程存储库中的分支。选择所需的现有分支,然后单击“创建分支”以创建分支。您可能会注意到一个标有 Checkout branch 的复选框。如果您想在新分支创建后立即开始工作,那么请确保复选框被选中。否则,你将留在你目前的分支机构。

Note

如果使用远程分支作为基础创建分支,则远程分支将被设置为新分支的跟踪分支。这不会影响任何功能,但是当您将来需要这样做时,它会使您更容易将您的更改推回到基础分支。

创建新分支的第二种机制实际上是获得图 5-29 的不同方式。在 Visual Studio 状态栏的右侧,有当前分支的名称。当你点击它时,会出现一些额外的选项,如图 5-30 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-30

Visual Studio 状态栏中的分支选项

要创建新分支,请单击新建分支…菜单选项。这将启动团队资源管理器(如果尚未打开),并显示“分支”窗格,其中显示了创建新分支所需的控件。换句话说,看起来和图 5-29 一模一样。

还有一种创建新分支的方法。在“分支”窗格中,您可以右键单击任何分支,无论是远程分支还是本地分支。上下文菜单包括一个新的本地分支 from…菜单选项。当您点击该选项时,创建新分支所需的字段就会显示出来(同样,如图 5-29 ),不同之处在于您右击的分支被用作分支下拉列表的选定值。

您可能已经注意到,我们创建的唯一分支都是本地分支。虽然可以使用 Git Hub web 门户创建远程分支,但是在 Visual Studio 中没有这样做的机制。至少,不是直接的。

默认情况下,从远程分支创建本地分支会设置跟踪分支。现在,当您发出 pull、push 或 fetch 命令时,Visual Studio 会自动对跟踪分支执行该命令。并且这些操作中的每一个都是在不给你改变跟踪分支的机会的情况下执行的。诀窍是从取消设置跟踪分支开始。为此,在“分支”窗格中,右键单击本地分支并选择“取消设置上游分支”菜单选项。此时,本地分支和任何远程分支之间不再有关系。

下一步是将分支重新连接到远程分支。没有办法通过 Visual Studio 目录做到这一点。如果您没有将当前存储库与远程存储库相关联,您可以通过同步窗格来完成此操作。而是打开 Visual Studio 2019 Developer 命令提示符,导航到您的本地存储库所在的目录。然后执行命令git branch <branchName> -u origin/<remoteBranchName>,,其中<branchName>是本地分支的名称,<remoteBranchName>是上游分支的名称。

切换分支

为了利用分支,您需要能够在不同的分支之间快速切换。这允许您利用 Git 分支的轻量级特性,根据工作需要切换开发上下文。

在 Visual Studio 中,有两个区域可以更改当前分支。首先,在团队资源管理器中,转到分支窗格(图 5-31 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-31

团队资源管理器中的分支窗格

存储库下面是本地和远程分支的列表。如果右键单击一个分支,在上下文菜单中会有一个签出选项。选择该选项会导致当前分支切换到所选分支。如果您签出了一个远程分支,则会创建一个同名的本地分支,然后新分支会被设置为当前分支。并且远程分支(该分支的原始源)被设置为上游分支。您可以通过双击分支而不是使用上下文菜单来完成相同的功能。

第二个改变分支的地方是在 Visual Studio 底部的状态栏。如果点击状态栏右侧的当前分支,会出现一个菜单(图 5-32 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-32

从状态栏切换分支

菜单顶部是本地分支机构的列表。当前签出的分支是灰色的,并且在左侧有一个复选标记。要签出另一个分支,请单击它。

合并分支

Git 中典型的开发流程包括创建一个本地分支,一直开发到完成,将您的更改提交到本地分支,然后将更新后的分支推回到远程分支。

如果您在一个有多个开发人员的系统上工作,那么在您进行开发时,其他人可能已经更新了远程分支。如果发生这种情况,流程中的实际步骤包括从远程分支提取任何更改,将远程更改与您的更改合并,然后将结果推回到远程分支。这个过程的一个关键部分是合并。

虽然如何成功执行合并的细节超出了本书的范围,但前提是简单明了的。如果同一个文件在两个分支中都被更改了,那么就比较代码的各个行。如果这种比较在两个分支中的文件内的相同位置发现变化,则识别出冲突。否则,这两项更改都将包含在合并的文件中。

虽然这种合并和冲突检测是作为 Git pull 的一部分自动发生的,但是您也可以在您选择的时间手动执行这种合并。为此,请进入团队资源管理器中的“分支”窗格。如果右键单击某个分支,其中一个选项是“从…合并”。选择此选项将在分支窗格顶部打开一个区域,如图 5-33 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-33

在团队资源管理器中合并分支

第一个字段是下拉列表,包含本地和远程分支的列表。在这里,您可以选择要合并的分支。第二个字段是您当前分支的名称。这只是为了提供信息。您不能对其进行更改,只能合并到您当前的分支中。此外,还有一个复选框,指示您是否希望在成功合并后立即执行提交。当这些值按照您的要求设置后,单击“合并”按钮开始该过程。

如果没有冲突,这两个分支将被合并,您可以继续您的开发。但是,如果合并检测到冲突,您必须在继续之前解决冲突或还原合并。

分支窗格中会出现一条消息,通知您存在冲突(图 5-34 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-34

“合并分支”窗格中的冲突

在冲突消息的正下方有两个选项。如果不想继续合并,请单击中止链接。为了解决任何冲突(您可以从数字中看到此时只有一个冲突),请单击 conflicts 链接。这将显示图 5-35 中的解决冲突窗格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-35

团队资源管理器中的解决冲突窗格

这里列出了包含冲突的每个文件。在继续之前,需要适当地合并每个冲突的文件。当你点击一个文件时,显示可用于处理该文件的选项(图 5-36 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-36

冲突解决方案选项

一旦选择了一个文件,就有许多选项可以帮助您决定如何完成合并。页面上有三个不同的链接:冲突消息下面的比较文件和编辑消息旁边的两个比较链接。这些链接中的每一个都会启动 Visual Studio 比较工具。链接之间的区别(双关语)是被比较的文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-37

Visual Studio 中的比较工具

图 5-37 显示了 Diff 工具结果的样本视图。这个想法基本上是为了突出两个不同文件之间存在的差异。Diff 过程有一个目标和一个源。当一行发生变化时,它将在源中显示为浅红色,在目标中显示为浅绿色。如果在源和目标之间删除了一条线,则该线在源中显示为浅红色。如果在目标中添加了一行,它会以浅绿色突出显示。

前面提到的三个链接都导致相同的视图。但是他们使用不同的来源和目标。“比较文件”链接比较已经提交给正在合并的两个分支的文件。Diff 链接将当前本地文件(不一定是已提交的)与特定分支中的文件实例进行比较。

为了通过解决冲突来帮助完成合并,Visual Studio 包括一个内置的三向 Diff/Merge 工具。除非您已经修改了 Git 的设置(本章稍后讨论)以使用不同的工具,图 5-38 包含了您将看到的示例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-38

Visual Studio 中的差异/合并工具

使用 Diff/Merge 工具的目的是让您轻松定义正确的合并结果。窗格顶部有许多图标和消息来帮助您浏览文件。

首先,冲突的线条以浅橙色/棕色显示。每一行旁边都有一个复选框。要指出某一行应该包含在合并文件中,只需确保复选框被选中。您可以同时包括其中一行或两行。结果显示在底部的窗格中。底部窗格也可以直接编辑,这样您就可以添加创建正确结果所需的任何附加代码。

这两个文件之间可能还有其他不会导致冲突的差异。它们由之前在 Diff 工具中描述的相同配色方案来表示。

页面顶部会显示一条消息,指出已识别的冲突数量以及尚未解决的冲突数量。您可以手动浏览文件,查找冲突(它们在滚动条中显示为橙棕色的点)。或者您可以使用工具栏上的前四个图标导航到第一个、上一个、下一个和最后一个冲突(按顺序)。

接下来的两个图标(它们是填充了最左边或最右边形状的三个矩形)用于从左边或右边的文件中获取所有的更改。

下一个图标(看起来像图 5-38 中窗格的基本布局)用于改变窗格的组织。除了示例中的二对一布局之外,您还可以垂直或水平排列窗格。

接下来是一个图标,用于直接从 merge 启动 Diff 工具。这三个选项与“解决冲突”窗格中描述的选项相同。您可以在源和目标、源和基础(本地版本)或目标和基础之间执行差异。

最后,最后一个图标用于将焦点设置在三个窗格中的一个上。虽然您不太可能直接使用这些菜单项(只需单击窗格会更容易),但这些选项有相关的快捷键,允许您在窗格之间切换焦点,而不必将手指从按键上移开。

根据需要使用尽可能多的工具,将文件转换到一个正确的状态,以便合并两个冲突的文件。准备好文件后,单击接受合并以完成冲突解决过程。这将获取合并的文件并使其成为本地文件。如果有更多冲突的文件,请依次修复每个文件。完成后,合并会自动标识为完成。如果您在启动合并时已经指出您希望在合并完成时提交合并的文件,那么提交将会完成。更重要的是,你能够继续正常发展。

你甚至不需要使用合并工具来解决合并冲突。Git 表示在文件本身中查看源文件和目标文件所需的信息。例如,下面是产生图 5-38 中冲突的代码行:

<<<<<<< HEAD
<p>Conflicting change. This is the updated privacy policy. As you can tell by the number of characters in this page, privacy is something that we take very seriously.</p>
=======
<p>Addition change. This is the updated privacy policy. As you can tell by the number of characters in this page, privacy is something that we take very seriously.</p>
>>>>>>> 153-Update_privacy_message_on_main_screen

向左和向右指向的人字形集合是冲突的警告标志。以<<<<<<< HEAD开始并以=======结束的部分是当前在本地文件中的代码。以=======开始并以>>>>>>> <branchName>结束的部分是来自合并文件的代码。<branchName>是您要合并的分支的名称。您可以进入您喜欢的文本编辑器,直接进行更改,然后删除用于分隔冲突部分的行。一旦进行了这些更改并保存了文件,它就不再被认为是冲突的。

重建树枝基

在 Git 中合并文件的想法是将两个文件的内容结合起来,创建一个包含两个更改的文件版本(或者基于人工干预的更改的修改)。对于大多数情况,这是获取一个分支的内容并将其添加到另一个分支的最简单的方法。

然而,Git 有第二种技术来组合两个分支:rebasing。使用 rebasing,而不是合并文件,您从一个分支获取提交,并将它们重新应用到当前分支。实际步骤如下:

  • 定位两个分支(当前和传入)之间最近的共同祖先。

  • 收集传入分支中每个提交中的更改所生成的文件差异。

  • 将当前分支重置为最近一次提交。

  • 按照发生的顺序,应用传入分支提交的每个文件差异。

  • 执行快进合并。

当你完成了重新定基,你应该有一组与合并相同的文件。换句话说,从结果的角度来看,重定基础和合并是同一个来源。不同之处在于存储库中的历史记录。在合并过程中,两个分支的历史被合并。大多数 Git 历史可视化工具将合并显示为两个单独的历史路径,它们在创建源分支时分开,然后通过合并再次结合。重定基础文件的历史是线性的。您会看到直到最近一次提交之前的所有更改。然后您会看到来自文件差异的提交。结果是历史是线性的,而不是分支的。

在 Visual Studio 中,重置基础的过程与合并非常相似。它从团队资源管理器开始。在“分支”窗格中,顶部有一个标记为 Rebase 的链接。点击图标会在窗格顶部打开一个区域,如图 5-39 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-39

团队资源管理器中的重置基础

通过获取当前分支并将变更推送到另一个分支来执行基础变更。当您单击 Rebase 链接时,顶部的文本框包含当前的分支名称(并且您不能更改它)。该字段下方是包含本地和远程分支的下拉列表。如果您选择了一个本地分支,单击 Rebase 按钮会导致当前分支重新基于所选分支。如果您选择了一个远程分支,那么该分支将被拉入到一个本地分支中,其名称与执行 rebase 之前的名称相同。

也可以通过右键单击 full Branches 窗格中的一个分支来访问 rebase 选项。在这种情况下,您右键单击的分支将成为 rebase 的目标(除非您右键单击当前分支,在这种情况下,下拉列表为空)。

删除分支

在 Visual Studio 中,删除分支是一个简单的过程。在团队资源管理器的“分支”窗格中启动。右键单击分支并从上下文菜单中选择删除。如果该分支有尚未被推送到其上游存储库的提交,您将得到一条这样的消息。您可以选择继续(相当于- delete 选项)或取消删除。

如果右键单击远程分支,删除选项将标记为“从远程删除分支”。您将收到一条消息,要求确认删除,如果您接受,那么分支将从原点删除。

拉取请求

至此,当我们谈论将代码推送到另一个分支时,您负责整个过程确保传入的代码是好的,执行合并,并确保合并的代码得到测试。如果你负责这个项目,那很好。但是随着越来越多的人参与进来,通常会有一个或更多的人来担当传入代码的看门人的角色。在这种情况下,当代码被添加到项目中时,把关者负责确保质量和功能得到维护。您通常会在拥有一个或多个开发团队的开源或大型项目中看到这种结构。

在这种情况下,允许每个人推送代码可能会很危险。虽然大多数开发人员不会引起问题,但一个错误的承诺会严重影响项目的质量和声誉。为了解决这个问题,Git 支持拉请求的思想。使用 pull 请求,而不是将您的更改直接合并到一个分支中,这些更改被打包,以便可以对它们进行审查。这个包是 pull 请求,包含其他信息,比如标题、描述和相关的工作项。然后,拉取请求由有权批准拉取请求的人进行审阅。当拉请求被批准时,代码被合并到目标分支中。

Visual Studio 2019 提供对创建拉请求的支持,只是因为它在 Team Foundation Service 或 GitHub 中启动新的拉请求网页,并填入适当的信息。若要启动该页面,请在团队资源管理器的“分支”窗格中,右键单击某个分支,然后从上下文菜单中选择“创建请求”选项。当您单击状态栏右侧的分支时,可以从出现的菜单中找到相同的选项。当点击该选项时(并且您连接到位于 TFS 的存储库),以下页面(图 5-40 )将在您的默认浏览器中打开。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-40

创建新的拉取请求

能够创建拉请求的标准之一是两个分支(源和目标)都需要在服务器上可用。换句话说,您不能将请求从本地分支拉至远程分支。因此,为了创建一个拉请求,您必须提交到本地分支,然后将提交推送到上游分支。当您进入新的拉取请求屏幕时,所选择的分支(或其上游伙伴)出现在左上方的下拉列表中。下拉列表的右侧是拉取请求的目标。这两个都可以在这个屏幕上修改。

在目标和源分支下面是拉请求的元数据。标题必选,强烈建议描述。描述的右下方有一个链接,用于将提交消息添加到描述中。然而,这可能还不够。在编写描述时,要考虑到将来有人会仔细阅读描述,以了解拉请求中的内容。换句话说,帮你未来的自己一个忙(因为,不可避免地,你将是阅读描述的人),尽可能清楚和完整地了解拉取请求中的内容。

在描述下面是作为拉请求的审阅者的人员列表。存储库的策略可以自动添加审阅者(个人或组),但是您也可以指定特定的人。将向这些人发送电子邮件,通知他们拉取请求已经创建。

还有一个将工作项与拉请求相关联的地方。如果您这样做,拉请求将成为工作项关联的一部分。它允许其他人查看哪些拉请求可能已经被接受,以完成开发或修复工作项中描述的问题。

元数据下面(在图 5-40 中不可见,除了标题)是每个文件中所做的更改,以及作为拉请求一部分的提交。最好检查一下这些,以确保只有您期望的更改是拉请求的一部分。

信息准备就绪后,单击 Create 创建拉请求。还有一个选项可以将拉取请求创建为草稿。这允许您稍后再回来填写缺失的信息或添加文件。需要记住的一点是,当拉请求打开时,对同一远程分支的后续提交会自动包含在拉请求中。

创建完成后,包含拉取请求信息的页面如图 5-41 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-41

Visual Studio Online 中现有的拉请求

审阅者和创建拉请求的人都可以看到该视图。在某些时候,评审者将批准(或拒绝)拉取请求。这可能是在提出需要解决的意见之后。但是在查看拉请求时,可以通过单击 Complete 按钮来完成。此时,作为拉请求一部分的变更将被合并到目标分支中。

查看代码的历史记录

跟踪一段时间内对文件所做的更改的能力是识别新出现的 bug 的来源的一个很好的方法。毕竟,如果代码过去可以工作,现在不行了,那么在此期间所做的任何更改都是开始寻找 bug 的好地方。

查看任何文件的历史记录的起点是解决方案资源管理器。右键单击所需文件,然后从上下文菜单中选择“查看历史记录”。这将显示历史表格,如图 5-42 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-42

Visual Studio 2019 中的简单历史视图

对文件所做的每个更改都会出现在此列表中,包括提交哈希、提交消息、提交日期和时间、提交者以及开发人员的图片(如果有)。这是简单的历史观。点击工具栏左侧第二个图标,查看详细历史视图(图 5-43 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-43

Visual Studio 2019 中的详细历史视图

详细视图中可用的信息与简单视图非常相似,只是开发人员的图片不可见。让读者来决定这是多大的损失。

可以显示更完整的历史。首先,右边的最后一个图标用于显示应用于提交的所有标记。右边倒数第二个图标包括提交所来自的远程分支。另外,右边第四个按钮(带时钟的那个)显示完整的历史记录。默认情况下,合并提交不在显示范围内。完整的历史记录会将这些提交添加到列表中。图 5-44 说明了不同的远程分支标签和合并提交。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-44

包含所有提交和远程分支标签的历史视图

有些操作可以在单个提交上执行,这样您就可以更近距离地看到所做的更改。要启动其中的每一个,请通过单击第一个并按住 Ctrl 键单击第二个来选择两个不同的提交。那么上下文菜单将包括以下选项:

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-45

团队资源管理器中的“比较提交”窗格

  • 这将启动“合并分支”一节中描述的 Visual Studio Diff 工具。

  • 比较提交该选项在团队资源管理器中打开“比较提交”窗格(图 5-45 )。

此窗格的目的是让您在文件视图中查看正在比较的两个提交。这两个提交的详细信息占据了窗格的大部分。下面是两次提交之间修改的文件。如果双击任何一个文件,就会打开 Diff 工具,比较两个不同提交中的选定文件。

Git 设置

Git 有各种各样的设置可供操作。通常,这些设置是使用 Git 命令行配置的。但是,Visual Studio 允许设置一些基本信息和默认值,包括所有 Git 函数和每个存储库。可以通过单击团队资源管理器主页上的“设置”按钮来访问这些设置。这将显示设置窗格,如图 5-46 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-46

团队资源管理器中的设置窗格

在这个设置列表的底部有两个链接,带您到专门与 Git 相关的独立窗格。全局设置窗格(图 5-47 )控制每个 Git 存储库的设置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-47

团队资源管理器中的全局 Git 设置窗格

在窗格顶部,您可以为任何新的存储库设置用户名、电子邮件地址和默认位置。接下来的几个设置不太简单。

在提取期间修剪远程分支–如果设置为 True,则在执行提取时,如果本地分支的上游分支不再存在,则删除本地分支。

提取时重设基础本地分支–此设置控制提取时是否自动重设基础。如果设置为 True,则每次拉取都会产生一个基数。将此项设置为 False 意味着 pull 执行合并,而不是 rebase。Preserve 选项使 rebase 在 pull 上执行,但是本地分支上的任何合并提交都被保留。这个设置其实是有交互选项可用的,但是 Visual Studio 2019 内不支持。如果需要,可以通过 Git 命令行使用git config pull.rebase设置来设置该选项。

加密网络提供者–指定应该使用哪个 SSL 后端与 Git 服务器通信。选项有 OpenSSL 和安全通道。它们都支持 TLS 和 SSL 协议。不同之处在于,安全通道将访问 Windows 凭据存储,这使得它成为管理用于与 g it 服务器通信的证书的企业的合适选择。

启用下载作者图像–选中时,将从 Gravatar 图像源(GitHub 的图像源)下载作者图像。

默认情况下,合并后提交更改——这个选项非常简单明了。如果选中,则在成功合并后,将立即执行提交。

启用 push-force–选中时,执行的任何推送都将使用force选项执行。当在没有强制的情况下执行推送时,将执行检查,以查看自上次推送以来是否进行了任何提交。如果有过,你会被告知先拉再推。这将导致任何变更都被合并到您的分支中,并在您可以推送之前完成任何必要的冲突解决。使用force选项可能是危险的,因为有可能覆盖上游分支中的更改。

“全局设置”窗格的底部是正在使用的“比较”和“合并”工具。通常,这些工具是使用git config命令行命令设置的。但是,如果要将 Visual Studio 工具设置为默认工具,可以单击“使用 Visual Studio”链接。

存储库设置类似于全局设置。图 5-48 展示了一个典型的储存库。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-48

团队资源管理器中的存储库设置

窗格的上半部分包含“全局”窗格中的一些设置。您可以覆盖用户名和电子邮件地址。您还可以在提取时设置修剪远程分支,在提取时设置重置本地分支以覆盖全局值。

在这些可重写设置的下面是。gitignore.gitattributes文件。这些是包含模式集合的标准 Git 文件。对于.gitignore,如果一个文件路径匹配模式,它将被 Git 忽略。对于.gitattributes,如果一个文件路径与模式匹配,那么一组属性将被应用于该路径。每个文件都包含一个编辑链接,打开文件允许您直接编辑。

在窗格的底部,有一个部分定义了当前本地存储库(即上游存储库)的远程存储库。有可能有不同的存储库,每个都有一个单独的名称。默认名称为 origin,如图 5-48 所示。但是您可以添加新的远程定义,以及编辑现有的远程服务器。点击添加或编辑打开一个对话框(如图 5-49 所示),让您指定存储库的路径。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 5-49

编辑远程存储库 URL

远程存储库的名称在第一个字段中。另外两个文本框用于获取和推送 URL。虽然它们通常是相同的 URL,但也不一定是相同的。选中推送匹配获取复选框后,将自动同步获取和推送 URL。如果它们需要不同,则取消选中该选项,并将每个 URL 设置为适当的值。

摘要

Git 已经紧密集成到 Visual Studio 2019 中。部分原因是因为 Git 在许多不同的开发环境和平台中的广泛使用。这至少部分是因为微软最近收购了 GitHub,这是一个领先的 Git 项目库,包括开源项目和个人项目。随着时间的推移,可能会有更多的 Git 函数可用。

虽然 Git 是一个协作工具,因为许多开发人员可以同时在同一个代码库上工作,但它不是 Visual Studio 中可用的全部协作。在下一章中,我们将了解 Visual Studio 2019 支持的一些交互式协作体验。

六、协作

上一章描述的 Git 功能的核心是协作的概念。你修改代码。其他开发人员对代码进行更改。这些变化被合并成一个单一的功能单元。拉请求更进一步,在被分支接受之前,潜在的提交需要被检查和评论。

但这并不是 Visual Studio 2019 中可用的协作的限制。有几个新特性将代码审查、结对开发和辅助调试提升到了新的水平。在这一章中,详细讨论了协作开发、实时共享和集成代码评审的焦点。

Visual Studio 实时共享

Visual Studio Live Share 背后的前提非常令人印象深刻。使用 Visual Studio 或 Visual Studio 代码,您可以与其他开发人员协作实时编辑和调试您的应用,参与者可以查看应用代码和调试信息、执行终端命令、转发本地主机请求以及通过语音呼叫进行通信。想象一下 Skype、Visual Studio 和远程调试的组合,你就有了想法,至少有了功能组合的想法。实现更加令人印象深刻。

系统需求

对于 Visual Studio 2019,主要要求是安装支持 Live Share 的工作负载。这包括 ASP.NET。NET Core、C++(具有 C++工作负载的桌面开发)、Python 和 Node.js,对于 Visual Studio 2017,需要运行 15.6 以上版本。同样,您需要安装一个名为 Visual Studio Live Share 的扩展。它可以在 Visual Studio 市场上获得。对于 Visual Studio 代码,需要相同的扩展(来自市场的 Visual Studio Live Share)。

出于完整性考虑,并不是每种语言都受到同等程度的支持。您可以将实时共享功能分为三个高级别组:

  • 共享语言服务参与者看到一个人所做的编辑会立即出现在他们的编辑器中。您还可以看到他们的光标位置和选择。此外,您可以跟随其他参与者(自动导航到他们正在导航的位置)或发送和接收焦点通知(要求参与者将注意力集中在您的编辑上)。

  • 共享调试参与者能够在同一个调试会话中工作。这包括查看状态和同步执行的能力。

  • 应用共享参与者共享应用的执行。例如,对于一个 web 应用,他们可以向网站发出请求,即使它运行在另一个参与者的本地主机上。对于非 web 应用,它们可以像在本地运行一样与应用进行交互。

对于给定的语言和平台(Visual Studio 与 Visual Studio 代码),提供了不同级别的支持。主要是因为 Visual Studio 代码中可用的语言范围非常广泛。对于 Visual Studio,共享语言服务支持最常用的语言(包括 C#、Python、C++、VB.NET 和 F#)。在撰写本文时,最显著的例外是 R,尽管它在 Visual Studio 代码中受支持。并且这些语言中的大部分也可用于共享调试(有趣的是,R 可用于协同调试)。例外是那些没有真正执行的语言(CSS,HTML,XAML,Markdown,SQL)。

如果参与者使用的是 Visual Studio 代码,那么共享语言服务和共享调试所支持的语言列表会更长,也更奇特。

说到 App 分享,支持的开发平台也很广泛。支持大多数预期的环境(web 前端和后端、控制台应用)。同样,有许多环境可能会令人惊讶,包括 Kubernetes、Azure functions、Ethereum 和使用 Cordova 或 React Native 的移动开发。总而言之,这个列表足够完整,可以涵盖大多数协作情况。

连通性

实时共享支持三种连接模式:

  • 主机和客户机可以通过本地网络直接通信。

  • 主机和客户机之间的通信是通过 Azure 服务总线完成的。

  • Auto 允许直接连接,通过本地网络,或者通过 Azure 服务总线。

建立实时共享连接时,需要完成许多步骤。首先,主机建立会话。这样做时,它可以指定所有连接都必须通过两种连接模式之一进行。换句话说,主机可以通过指定直接连接类型来确保只有本地网络上的参与者才能加入。

一旦建立了主机会话,就允许来宾连接。与主机一样,它们可以选择直接、中继或自动连接模式。对于 guest 虚拟机,自动模式将通过检查是否可以直接连接到主机来启动。如果可用,则使用该连接。如果没有,则会话退回到中继模式。

所有连接都是 SSH 或 SSL 加密的,因此除了参与者之外,任何人都看不到任何通信。但是,有些端口需要开放,以便能够托管或参与。对于直接连接,使用 5990 和 5999 之间的端口。对于继电器连接,您必须能够访问*.servicebus.windows.net:443

安全性

为了主持或连接到实时共享会话,您必须通过 Azure Active Directory 帐户、Microsoft Live 帐户或 GitHub 帐户进行身份验证。使用内部 Active Directory 帐户或 GitHub Enterprise 帐户无法连接到 Live Share,尽管微软正在考虑将它们作为未来的增强功能。

主持实时分享会议

要开始实时共享会话,您需要执行两个步骤。首先,您需要登录到 Visual Studio。这是您第一次安装 Visual Studio 时会被问到的问题。如果您已经登录,右上角将类似于图 6-1 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-1

Visual Studio 中的登录帐户信息

您保持登录状态,因此如果您在安装后没有进行过身份验证,请不要感到惊讶。如果您还没有登录,那么在图 6-1 中的圆圈处有一个登录标签。单击该标签将启动身份验证过程。一旦完成,你就完成了分享生活的一半。

第二步,也是比较简单的一步,实际上有两个部分。从打开或创建一个解决方案开始。这样做的目的是在 Visual Studio 中打开您想要共享的解决方案。一旦解决方案准备就绪,点击实时共享标签,如图 6-2 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-2

实时共享链接

如果您没有看到这个实时共享链接,可能是因为您没有安装包含它的任何工作负载。您可以这样做(该列表位于本章开头),或者直接从 Visual Studio Marketplace 安装。

单击实时共享开始共享您的环境。第一次这样做时,您可能会看到许多对话框,要求您配置 Windows 环境。如果您在自动模式下使用实时共享,并且 Windows 防火墙中未启用适当的端口范围,则会出现图 6-3 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-3

实时共享防火墙访问对话框

如果您点击 Ok,那么您将几乎立即看到如图 6-4 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-4

用于实时共享的 Windows 防火墙警报

此对话框由 Windows 防火墙显示,它表示由名称、发行者和路径详细信息描述的应用正在请求访问。在这种情况下,代理用于托管实时共享。单击“允许访问”会打开必要的端口。

如果您使用不同的防火墙或安全包,您在图 6-3 后看到的对话框可能会有所不同。或者您可能要求管理员通过全局设置打开端口。请记住,出现这些对话框是因为实时共享模式是自动的。可以通过 Live Share Settings(实时共享设置)屏幕更改默认设置,本节稍后将对此进行介绍。

配置端口访问后,实时共享会话将开始。设置可能需要几分钟时间,这取决于您的计算机和网络连接的速度。但是一旦它开始运行,你的 Visual Studio 将看起来类似于图 6-5 。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-5

运行实时共享的 Visual Studio

第二次及以后共享时,您将看不到“入门”窗口。相反,只显示“实时共享”窗格(在右侧)和邀请链接消息(黄色,紧靠工具栏下方)。但是,您可以通过单击邀请链接消息中的“更多信息”标签来取回它。

除了显示入门页面,邀请链接消息也是在列表共享会话开始时获取您可能感兴趣的信息的快捷方式。默认情况下,可用于加入会话的 URL 会粘贴到剪贴板。这样,您可以不费吹灰之力就将链接发送给任何可能感兴趣的人。在链接消息中,您可以使用“再次复制”链接将链接重新添加到剪贴板。您也可以使用“设为只读”链接将会话转换为只读。

但是邀请链接消息只是一种方便。功能的真正来源在实时共享窗格中。图 6-6 显示了与一个参与者(即除主持人之外的一个参与者)的活动会话的实时共享窗格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-6

活动托管会话的实时共享窗格

窗格的主体是会话中的活动参与者、服务器和终端的列表。每个标题下列出了每种类型组件的实例。然而,当谈到您可以采取的行动时,大多数功能都在工具栏中。除了两个例外,它们将在接下来的章节中讨论。

两个例外是最右边的图标(红色方块)和分隔线右边的图标(看起来像复制图标和链接图标的组合)。方形图标用于终止实时共享会话。复制链接图标用于将用于连接到实时共享会话的 URL 的副本放置到剪贴板上。然后,可以通过任何方式(电子邮件、Skype、团队、Slack 等)将该 URL 发送给任何有兴趣加入该会话的人。)你更喜欢。

尽管并非所有功能都可用,但实时共享窗格对参与会话的每个人都可见。

作为实时共享会话的主持人,每当被邀请人加入您的会话时,您都会收到通知。您会在 Visual Studio 的右下方看到通知(图 6-7 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-7

你收到通知了

通知本身(图 6-8 )显示了加入者的姓名和电子邮件地址。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-8

当某人加入实时共享会话时出现的通知

“实时共享”部分的其余部分介绍了会话活动时可用的不同协作工具。

实时编辑

人们可以很容易地将实时编辑(或协同编辑)描述为实时共享的基本功能。前提很简单。您可以近乎实时地看到会话中每个人的更改、选择和光标定位。当有人打开文件时,该文件将在您的 Visual Studio 实例中打开。当有人做出更改时,该更改会出现在您的编辑器中。同样,您也可以获得参与者的姓名。图 6-9 提供了一个 Visual Studio 的两个实例的例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-9

在多个 Visual Studio 实例中进行实时编辑

尽管图 6-9 中的两个 Visual Studio 实例都是由同一个人(可能是作者)运行的,但其目的是演示每个人在实时编辑时看到的内容。

对于 top 实例,光标位于以"Logging"开始的行的开头。这在底部实例中由一个看起来像胖 t 形的蓝色指示器表示。当您将鼠标悬停在指示器上时,光标所在的参与者的姓名会显示为工具提示。

在底部实例中,光标位于最后一行的末尾。您可以看到在顶部实例中用 T 指示器表示。

通过这个简单的界面,每个参与者都可以看到其他人在做什么。除了光标定位之外,一个参与者所做的选择也会显示给其他参与者,如图 6-10 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-10

协作选择

与选择一样,一个参与者所做的任何编辑对所有其他参与者几乎实时可见。如果你在一个高速网络上工作,“接近实时”是足够接近的,就好像你的同事在你的屏幕上编辑的同时在他的机器上打字。

专注并跟随

Live Share 有一个关注一个参与者的概念。如果您跟随一个参与者,这意味着无论那个人在 Visual Studio 中做什么,您的 Visual Studio 实例都会跟随。这包括编辑、光标放置、选择和导航到其他文件。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-11

关注实时共享中的参与者

图 6-11 展示了两种不同的方式来查看您当前关注的人。在 Visual Studio 右上角的工具栏中,有一个圆圈集合,每个参与者一个。它们包含参与者的姓名首字母,但是如果您将鼠标悬停在它们上面,则可以看到全名。

BJ 参与者周围的双圆圈表示您当前正在关注此人。您可以随时通过点按圆圈或点按另一个参与者的圆圈来停止关注。

与工具栏一样,实时共享窗格也显示您当前关注的人。其他每个用户都可以在参与者节点下的列表中看到。每个名字旁边都有一个圆圈。如果圆圈是空的,那么你没有跟随那个人。如果圆圈有一个中心点(如图 6-11 所示),那么你正在跟随那个人。您可以通过单击其他参与者来更改您关注的人。或者,您可以通过点按某人的姓名来停止关注他。还有上下文菜单选项来关注和取消关注个人。

如果您正在进行实时共享会话,有时您可能希望其他参与者关注您正在做的事情。这是通过一个叫做聚焦的特性来实现的。您向每个参与者发送通知,请求他们跟随您。

您可以通过两种不同的技术发送焦点通知。首先,在 Visual Studio 右上角的工具栏中,有一个标记为“共享”(如果您是主持人)或“加入”(如果您是参与者)的下拉列表。此下拉列表包含许多实时共享命令的执行点。在这种情况下,从下拉列表中选择焦点参与者。这将生成一个发送给每个参与者的通知(见图 6-12 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-12

焦点通知

除了通知之外,参与者还会被自动设置为关注您。自然地,他们总是可以选择不跟随,使用前面段落中提到的技巧。

联合调试

Live Share 提供的更有用的特性之一是协作参与调试会话的能力。启动联合调试会话就像在 Visual Studio 中启动调试会话一样简单。一旦宿主的调试器附加到进程,每个参与者的 Visual Studio 实例都将连接到调试会话。从参与者的角度来看,他们看起来和感觉起来都像是在本地调试。

当遇到断点时,每个参与者的实例也会停止。同样,这看起来像一个典型的调试会话。事实上,参与者可以像在本地运行调试会话一样探索与调试会话相关联的值。考虑图 6-13 中显示的两个 Visual Studio 实例。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-13

联合调试时的断点和显示值

托管会话是出现在图 6-13 顶部的实例。但是,在底部的实例中,将鼠标悬停在 ViewData 变量上会显示包含当前属性值的工具提示。

Note

对于参与者来说,调试会话中显示的属性值是不可修改的(与在本地运行时能够修改它们相反)。

在调试会话中,参与者可以设置断点、查看正在使用的变量值、查看调用堆栈以及导航到进程中的任何其他文件。换句话说,您可以自由探索不同的选项来帮助确定被检查问题的原因。

自动连接到主机的调试会话。也就是说,一旦为调试设置了主机,参与者就可以轻松地连接起来。有时候这种行为可能会适得其反。可以配置主机调试会话开始后发生的事情。单击工具➤选项菜单项,然后导航至实时共享(图 6-14 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-14

实时股票期权

调试会话加入行为选项有自动(默认)、手动(因此您必须使用下一段中描述的技术加入会话)和提示。

您可能没有连接到宿主的调试会话,因为您选择了“手动”选项,在出现提示时回答“否”,或者只是停止了调试会话(这将阻止您跟踪该会话,但该会话将对其他所有人继续进行)。如果您希望加入正在运行的调试会话,可以采用与启动本地调试会话相同的方式。在工具栏中,运行选项包括一个下拉菜单,为您提供了许多启动选项。图 6-15 举例说明了您在实时共享会话中的情况。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-15

实时共享时运行选项

选择指示您正在附加到 GUID 的项目将使您加入实时共享调试会话。该 GUID 与链接中显示的 GUID 相同,该链接用于连接到实时共享会话。

共享服务器

现代应用可能是由不同服务器组成的复杂网络。认证服务器、微服务端点和基于 REST 的端点都可以是正在运行的应用的一部分。当让其他人参与调试过程时,允许实时共享参与者访问不同的端点会很有帮助。这样,他们就可以以类似于本地调试时的方式与应用进行交互。

当您为联合调试会话启动 web 应用时,web 服务器会自动与其他参与者共享。您可以在实时共享窗格中看到共享的服务器(图 6-16 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-16

共享服务器的实时共享窗格

在本例中,名为 SampleWebApplication 的 web 应用在端口 44399 上可用。这意味着,如果参与者使用浏览器导航到http://localhost:44399,他们将访问运行在实时共享主机上的服务器。请注意,这也意味着它们会遇到在该服务器的执行路径中定义的任何断点。如果他们正在联合调试,他们会看到断点命中,但如果没有,参与者可能会等待很长时间的响应。

但是共享 web 应用端口并不总是足够的。主持人可以专门共享额外的服务器供参与者交互。这是通过使用管理共享服务器命令来完成的。您可以单击实时共享窗格工具栏中的图标(图 6-16 中右数第二个)或使用 Visual Studio 工具栏中的共享下拉菜单。共享的本地服务器如图 6-17 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-17

共享本地服务器对话框

此对话框用于管理主机上运行的服务器,这些服务器可供实时共享参与者访问。在捕获图 6-17 的图像时,SampleWebApplication 服务器正在运行。通过单击“添加”按钮,可以添加不同的服务器。您需要提供服务器的端口号和名称。添加服务器后,参与者将可以在实时共享窗格中看到该服务器。他们将能够通过浏览器或代码或任何他们喜欢的方法来访问它。

在此对话框中,您还可以删除共享服务器(通过选择然后单击删除),在浏览器窗口中打开特定服务器,或将服务器的 URL 复制到剪贴板。

共享终端

有时,命令行功能可能需要由实时共享参与者使用或向他们演示。为了支持这一点,实时共享包括与参与者共享终端会话的能力。这意味着他们可以看到主机在终端窗口中输入的命令及其结果。这也意味着他们可以自己执行命令。

在这两种情况下,共享终端会话都是从主机环境中的两个位置之一开始的。在实时共享窗格中,单击共享终端图标(从右数第三个,见图 6-18 )并从两个选项中选择一个。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-18

在“实时共享”面板中共享终端

或者,Visual Studio 工具栏中的共享图标包括图 6-18 中可见的两个选项。

你有两个选择。在第一个只读终端中,您与每个参与者共享终端窗口以及所有内容。但是您没有共享参与者执行命令的能力。使用第二个选项,读写终端,您允许参与者执行他们自己的命令,完成该功能的所有潜在安全隐患。

无论选择哪种方式,共享终端都会打开一个单独的终端窗口。至少,这是 Visual Studio 的默认行为。由于 Visual Studio 不包括现成的集成终端窗口,因此需要一个单独的窗口。但是,您会在工具栏下方看到一个通知(如图 6-19 所示)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 6-19

终端共享通知

通知消息中的一个链接 Install integrated terminal 会将您引导到 Visual Studio Marketplace,在那里您可以安装 Whack Whack 扩展,这是一个用于 Visual Studio 的集成终端窗口。

实时共享的安全性

作为联合调试功能的一部分,实时共享参与者可以访问命令和即时窗口。从联合调试的角度来看,这提供了更接近本地调试的丰富调试体验。绝对是加分项。从安全角度来看,有点不一样。当您在联合调试会话中使用这些窗口时,命令正在主机的计算机上执行。这种访问的安全后果应该显而易见。参与者可能有权使用会话主机的授权来执行他们想要的任何命令。这包括潜在的破坏性命令,如清除整个文件系统。因此,信任您邀请参加实时共享会话的人非常重要。

在实时共享会话中使用共享终端时,也会出现同样的安全问题。如果你想确保参与者不能在你的机器上执行命令,那就只共享一个只读终端。否则,您必须相信参与者在连接时不会恶意行为。

同样,在实时共享会话中进行编辑时,参与者可以看到共享项目的整个文件树。参与者不需要跟着你,允许他们随意在树中导航。如果文件中嵌入了秘密(如服务器或数据库密码),参与者就可能发现它们。

就文件访问而言,降低一些风险是可能的。.vsls.json文件包含用于控制参与者对文件的访问权限的设置。下面是一个.vsls.json文件的例子:

{
    "$schema": "http://json.schemastore.org/vsls",
    "gitignore":"none",
    "excludeFiles":[
        "*.cer",
        "*.config",
        ".gitignore"
    ],
    "hideFiles": [
        "bin",
        "obj"
    ]
}

文件中有三个属性用于控制访问:

  • exclude filles定义了不允许参与者打开的文件和文件夹列表。这种限制包括您可能希望能够访问这些文件的情况,例如当您在调试会话期间单步执行某个文件时。这样做的目的是包含参与者永远看不到的文件。

  • hideFiles 定义了在树中不可见的文件和文件夹列表。但是,如果文件是通过导航出现的(比如找到一个定义),或者是在调试过程中出现的,参与者将能够导航到这些文件。

  • 默认情况下,.gitignore文件中的文件被视为隐藏。但是,您可以使用该属性来更改该行为。可能的值如下:

    • none–``.gitignore内容对项目树中的可见内容没有影响。

    • 隐藏–``.gitignore内容被视为hideFiles属性的一部分。

    • 排除–``.gitignore内容被视为excludeFiles属性的一部分。

gitignore属性使用 exclude 选项有一个潜在的问题。通常,node_modules目录包含在.gitignore文件中。但是在试图隔离行为时,调试到node_modules中的文件中可能是有用的。为了缓解这个问题,Live Share 支持否定.gitignore中定义的可见性的能力。例如,下面的.vsls.json文件仍然允许您调试到node_module文件中,即使它们已经被排除在.gitignore文件之外:

{
    "$schema": "http://json.schemastore.org/vsls",
    "gitignore":"exclude",
    "excludeFiles":[
        "!node_modules"
    ],
    "hideFiles": [
        "node_modules"
    ]
}

还要注意在hideFiles属性中使用了node_modules。排除和隐藏逻辑是彼此独立处理的。因此,这个设置将允许node_modules文件从解决方案树中隐藏(以减少混乱),但仍然允许文件被查看或进入。

摘要

协作无疑是 Visual Studio 2019 新增功能的一个重点。特别是在解决特别有害的 bug 时,现场分享有很大的帮助潜力。在这个问题上有多只眼睛是好的。当你调试得更好的时候,让别人监督你。允许参与者在调试的同时戳戳你的代码,这提供了高度的灵活性,这正是解决挑战性问题所需要的。

然而,联合调试选项并不是 Visual Studio 2019 中添加的唯一调试功能。在下一章中,我们将会看到一些已经添加的其他调试功能,所有这些功能都是为了使问题的跟踪变得更加容易。

七、调试和分析

作为一名开发人员,您将花费大量时间调试代码。当然,不是你的代码。你的代码完全被单元测试覆盖,没有任何错误。而是别人的代码。那些没有你多年经验的人,或者没有你打造防弹解决方案的技能的人。或者第三方或开源代码。有时候里面也有 bug。

希望开头那段的挖苦性质是显而易见的。但这一点仍然有效。您将花费大量时间调试您的应用。Visual Studio 提供了大量工具来帮助完成这一过程。因为这是一个过程,至少在某些时候,需要你能得到的所有帮助。

本章不打算讨论在 Visual Studio 中调试应用的基础知识。假设已经很好地理解了设置断点、查看变量的当前值以及使用局部变量、监视和快速监视功能的技术。这些对 Visual Studio 2019 来说都不是新的,已经在开发人员的军火库中存在多年了。相反,重点将放在 Visual Studio 2019 中已经引入或增强的功能上,或者只是有用但未得到充分重视的功能上。

断点

在介绍完之后,开始谈论断点可能有点奇怪。毕竟,断点是调试技术的元老。它们在应用中指定一个应该暂停执行的位置,并给你机会检查运行时的当前状态。这是最先教给任何开发人员的事情之一。但是使用断点的某些部分没有被充分利用。Visual Studio 2019 更令人兴奋的新增功能之一恰好针对这一古老的功能。

正如刚才提到的,断点用于在特定的代码行暂停应用。但是,默认行为是每当命中该行代码时暂停。在某些情况下,这很好。对于其他人来说,则不然。您可能希望对给定断点暂停执行的时间有更多的控制。

条件断点

您可以通过断点设置窗格向断点添加条件。通过右键单击断点指示器(位于编辑器的左侧)时出现的上下文菜单上的设置选项,可以访问此窗格。在图 7-1 中看到的上下文菜单,包括许多对更高级断点功能有用的选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-1

断点的上下文菜单

点击条件选项显示窗格,如图 7-2 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-2

用于定义条件的断点设置窗格

有许多选项可用于确定应用于断点的条件类型。首先,有一个包含所用条件类型的下拉列表。有三种选择。

条件表达式

前提是定义条件的那一行右边的大文本框将包含一个表达式。中间的字段包含一个下拉菜单,用于控制表达式的使用方式。下拉列表中有两个选项。对于Is true选项,如果表达式的计算结果为真,那么执行将在断点处停止。对于When changed选项,执行会在第一次遇到设置了断点的行时暂停。计算表达式,并记住值。随后每次命中断点时,都使用当前变量再次计算表达式。如果结果与前一个值不同,执行将在断点处停止。

Note

如果您正在调试本机代码,则“更改时间”选项的行为会略有不同。在这种情况下,调试器不认为第一次求值是值的变化。结果是第一次命中断点时,执行不会停止。

表达式使用的语言取决于设置断点的文件的语言。C#文件将使用 C#表达式。JavaScript 文件将使用 JavaScript 表达式。对于其他情况,确定文件类型和表达式语言之间的关系是留给读者的练习。

虽然表达式具有 IntelliSense,但它不立即进行语法检查。而且它肯定不能判断你的表达式是否会产生运行时异常。在这两种情况下,执行在断点处第一次停止。也就是说,在语法错误的情况下,第一次遇到断点,对于运行时异常,第一次引发异常。

当您有对象集合时,使用条件表达式可能会令人沮丧。除了创建与对象的唯一属性相关联的附加条件之外,没有明显的方法来区分集合中的不同对象。Visual Studio 2019 提供了一种机制,允许您生成一个对象 ID,然后可以在断点表达式中使用。在“局部变量”窗口中,右键单击所需的对象,并从上下文菜单中选择“生成对象 ID”(图 7-3 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-3

局部变量的上下文菜单

一个新的变量现在被添加到“局部变量”窗口中(图 7-4 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-4

对象 ID 跟踪变量

变量名的格式是$n,其中n是一个序列号。要在条件断点中使用这个对象标识符,可以添加表达式item == $n,其中$n是对象标识符。

尽管这种选择可能有用,但也有一些缺点。首先,对象标识符不会超过当前调试会话。您需要为每个调试会话创建一个对象标识符。标识符的数字部分有可能是相同的(序列号在每个调试会话中都被重置为 1),但这是您应该确保的。

此外,原始对象和跟踪对象之间的关系是弱引用。这意味着跟踪对象的存在不会阻止原始对象被垃圾回收。根据您正在调试的具体情况,这可能是一个重大问题。

点击计数

有些时候,条件就是不合适。相反,您希望在一行执行了一定次数后中断执行。如果您的代码在循环中执行,或者被应用的其他部分多次访问,这种情况很常见。

定义命中次数条件是通过同一个断点设置窗格完成的。不同的是,第一个下拉菜单设置为点击次数(图 7-5 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-5

断点的命中次数设置

点击次数的表达式是数字的。事实上,不允许非数字输入。如何处理该数字取决于中间下拉列表中的值。可用的选项如下:

  • Equals (=) 当断点达到表达式中找到的次数时,执行停止。

  • 的倍数当断点被命中的次数是表达式中数值的偶数倍时,执行停止。

  • 大于或等于(> =) 当断点达到表达式中找到的次数时,执行停止。之后每次执行都会暂停。

过滤器

应用早就达到了需要运行多个应用才能正常工作的地步。Visual Studio 的优势之一是能够作为调试会话的一部分启动多个应用。然而,这可能会给调试这样的解决方案带来一些问题。当执行在断点处暂停时,所有的进程都会暂停,而不仅仅是断点所在的进程。

有一个设置可以改变这种行为。在“工具➤选项”对话框中,导航到“调试➤常规”节点。在列表顶部附近,您会发现一个名为“当一个进程中断时,中断所有进程”的选项。如果您取消选中该选项,那么执行将只在包含断点的进程中暂停。

虽然这很好,但并不总是足够的。创建多线程应用变得越来越普遍。并且这些线程在单个进程中运行。如果能够定位一个断点,使执行只在单个线程中暂停,而不是每次在所有线程中遇到断点时都暂停,这将非常有用。筛选条件是为多线程和多进程目标设计的。

图 7-6 显示了过滤条件的断点设置窗格。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-6

断点的筛选器设置

前两个字段没有选项。第三个字段是表达式。它也是有限的。虽然表达式可以有 ANDs)、or(| |)、NOTs(!),和括号,可以测试的值仅限于线程、进程和机器值。具体来说,可以使用 ThreadId、ThreadName、ProcessId、ProcessName 和 MachineName。

附加设置

您可能已经注意到,在“条件类型”下拉列表下面有一个“添加条件”链接。一旦您填充了任何条件,您就能够添加额外的条件,注意每种类型只能添加一个条件。换句话说,当命中次数为 5 并且进程名为“demo.exe”时,可以有一个断点,在该断点处执行停止。但是不能有条件为“命中次数为 5,命中次数为 7”的断点。

除了多个条件之外,您还可以精确确定断点的位置。如果在一行代码中有多个语句,这很有用。在窗格的顶部,有一个设置断点的位置。点击数值可以直接编辑数值,如图 7-7 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-7

设置断点的位置

在这里,您可以指定源代码文件中的行号以及该行中的字符位置。如果当前源代码不同于用于编译正在运行的可执行文件的源代码,那么会有一个复选框指示您是否愿意允许断点处于活动状态。

动作断点

当在调试会话期间遇到断点时,默认操作是停止当前线程。事实上,默认情况下是停止所有线程,尽管正如上一节提到的,这是一个配置选项。但是,如果您试图调试一个正在处理争用情况的多线程应用,这可能会是一个问题。或者如果您只是不需要暂停应用,而只需要在断点命中时从调试器中获取一些信息。

这些情况可以通过操作断点(也称为跟踪点)来解决。创建操作断点与创建常规断点是一样的。事实上,正是您对断点的设置所做的事情使它成为一个操作断点。与条件断点一样,右键单击断点指示器(在编辑器的左侧),然后从上下文菜单中选择“操作”。断点设置窗格出现,这次操作是可见的,如图 7-8 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-8

断点窗格中的操作设置

有两个字段与操作设置相关联。第一个是断点命中时设置到输出窗口的消息说明。有几个适用的格式元素(它们将在下面的段落中描述),但这是操作断点的基本目的。这样,它类似于代码中的调试或跟踪语句。区别在于动作断点是动态设置的,因此不需要重新编译应用。

第二个字段是一个复选框,指示当断点被命中时程序的执行是否应该继续。默认情况下,应用不会暂停执行。在这种情况下,它与常规断点完全相反,并且这种行为在本节开头描述的多线程场景中运行良好。但是,如果您仍然希望暂停执行,请清除此复选框。

要显示的消息不是表达式。也就是说,期望不是定义一个字符串值,用连接符号完成。相反,这种格式更接近于您在String.Format字符串中使用的模板,使用特殊的变量作为固有值,使用花括号符号作为变量值。例如,考虑以下情况:

$FUNCTION: The value of x.y is {x.y}

当遇到这个动作断点时,我们将从当前函数的名称(即$FUNCTION值)开始,接着是字符串The value of x.y is,然后是x对象上y属性的值。因此,消息由内置变量、文本和局部变量值的花括号符号的组合组成。

内置变量列表可通过 IntelliSense 获得(在图 7-8 中可见)。每个的含义如下:

  • $ADDRESS 当前指令

  • $CALLER 调用当前方法的函数的名称

  • $CALLSTACK 当前调用堆栈

  • $FILEPOS 代码文件中的当前位置

  • $FUNCTION 当前函数的名称

  • $PID 当前进程 ID

  • $PNAME 当前进程的名称

  • $TICK 当前的滴答计数

  • $TID 当前线程 ID

  • $TNAME 当前线程的名称

动作断点(与常规断点相反)的存在由不同的断点指示符来指示。编辑器的左边出现了一个红色的菱形,而不是红色的圆圈,尽管只有勾选了Continue code execution复选框时才会出现这种情况。如果未选中,则红圈照常出现。

函数断点

无论是否添加条件,手动设置断点的一个基本前提是,您可以访问要应用断点的源代码。您可以打开文件,找到有问题的行,并应用断点。但这并不总是行得通的。Visual Studio 2019 提供了几个不同的函数,旨在帮助解决这些情况。

当您知道要暂停执行的函数的名称,但不知道文件在源代码中的位置时,可以使用函数断点。或者,如果您有一个函数的多个重载,使用函数断点比在每个重载方法中放置断点更容易。

使用调试菜单创建函数断点,特别是选择调试➤新断点➤函数断点。出现如图 7-9 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-9

函数断点对话框

在对话框的下半部分,有两个复选框,分别标记为条件和操作。这些用于设置您希望应用于断点的任何条件,或者在到达断点时应该发生的任何操作。这些操作与常规断点对话框中的条件和操作相同。本章前面的“条件断点”和“操作断点”部分描述了用这些复选框启动的选项。

将函数断点与其他断点区别开来的是如何定义何时暂停执行。这是在函数名文本框中完成的。最简单的方法是,输入函数的名称。该名称必须是完全限定的,因此,例如,它看起来像下面这样:

SampleApplication.Models.Order.Add()

在这个例子中,方法的名称空间是SampleApplication.Models。包含方法的类的名字是Order,方法的名字是Add。还要注意没有参数的括号。这个符号将匹配对Add的每个调用,而不管使用的参数是什么。换句话说,它将在Add方法的每个重载实例上中断。

函数名的目标是提供尽可能多的特殊性或可变性,以便在适当的时候打破。例如,尽管前面的例子将在所有的Add方法上中断,不管签名是什么,但是您可以通过提供参数和数据类型来更准确地使用断点。

SampleApplication.Models.Order.Add(Customer c)

现在,只有当类型为Customer的单个参数被传递给Add方法时,执行才会暂停。

您可以指定该方法所在的模块,而不是为该方法使用命名空间。例如,当从 Order.dll 模块调用 Add 方法时,下面的代码将暂停执行。

Order.dll!Add

最后,如果在本机 C++中调试,可以在用于标识断点位置的信息中包含偏移量。

{Add, , Order.dll}+2

此符号在 Order.dll 模块中从 Add 方法开始的第二行设置一个断点。

与函数名相关的另一个字段是语言下拉列表。这用于影响您用来声明函数名的语法。前面显示的向方法传递参数的示例使用了 C#语法,这意味着需要将 Language 属性设置为 C#。下拉列表包含许多不同的选项,包括 JavaScript、TypeScript、F#和 Basic。用于定义函数名的语法需要与所选择的语言相匹配。

数据断点

Visual Studio 2019 的一个新功能是数据断点的概念。其思想是,当变量值改变时,执行暂停,而不是在一行代码处中断。这是一个非常强大的想法,因为解决 bug 的关键通常是识别应用中变量值被修改的地方。虽然 C++开发人员已经可以使用这一功能,但长期以来,它一直是托管代码开发人员的常规要求。

首先,坏消息。目前,创建数据断点仅在中可用。网芯 3.0 或更高版本。从好的方面来看。NET Core 3.0 支持使用 WPF 或 Windows 窗体的 Windows 桌面应用,因此您对可以使用的应用类型的限制已经大大减少。但如果你不坚持。NET Core 3.0,那么这个功能对你是不可用的。

若要在托管代码中设置数据断点,需要运行应用。然后在“局部变量”、“自动”或“监视”窗口中,右键单击要监视的属性,并从上下文菜单中选择“值更改时中断”。图 7-10 显示了该序列的作用。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-10

设置数据断点

一旦设置了断点,窗口中的变量旁边就会出现一个红色的圆圈。

在执行过程中,如果变量的值发生变化,则执行会暂停,并出现一条消息,指出断点的原因。图 7-11 说明了该信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-11

为数据断点显示的消息

此时,您的执行已经暂停,您可以访问所有典型的调试信息和功能。

Note

提醒一下,当变量值改变时,数据断点被触发。如果您将断点与一个对象相关联,那就很好了。但是在一个对象上设置断点不会在该对象的属性被修改时暂停执行。为此,您需要在 Locals/Auto/Watch 窗口中展开对象,并在该对象中选择要监视的属性。为了强调这一点,数据断点是实例敏感的。如果您有同一个类别的两个执行个体,当第二个执行个体的相同属性被修改时,在其中一个执行个体的属性上设定的资料中断点不会导致执行暂停。

使用调用堆栈定义断点

对于大型应用,调试的挑战之一是在正确的位置设置断点。在执行过程中过早地设置它,您将花费很长时间来使用单步执行和单步执行函数。如果设置得太晚,那么,一切都太晚了。这实际上是司法使用条件断点如此有价值的原因之一。

但是 Visual Studio 确实提供了另一种定义断点的方法,这种方法非常有用,尤其是在试图确定意外异常的来源时。当执行因任何原因暂停时,调用堆栈是可用的。虽然调用堆栈中的所有级别都不容易调试,但您的代码在堆栈中肯定是可见的。在堆栈中的任何级别,您都可以右击并在上下文菜单中选择插入断点。这将在代码中由调用堆栈指示的位置放置一个断点。

现在可能需要添加额外的条件来避免多次命中断点,但是您可以在调用点检查局部变量,看看最合适的选择是什么。但最重要的是,您不需要浏览代码来找出它是如何到达异常位置的。调用堆栈已经给出了路径。

远程调试

在麻烦的生产应用中,远程调试的诱惑始终存在。有多少次,您在本地开发和测试了一个应用,甚至是在一个试运行环境中,结果却是在它被部署到生产环境中后遇到了全新的问题。

通过使用一个小的可执行文件,您可以像调试本地应用一样调试远程应用,也就是说,断点和单步执行功能是可用的,查看变量值的能力也是可用的。关键是那个小的可执行文件和使用哪个文件背后的细节。

第一步是下载适当的可执行文件。起点是下载 Visual Studio 2019 的远程工具。你可以在 https://visualstudio.microsoft.com/downloads/#remote-tools-for-visual-studio-2019 找到下载链接。在图 7-12 中可以看到页面本身的一部分。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-12

Visual Studio 2019 远程工具的下载页面

诀窍是下载正确的工具集。ARM64、x64 和 X86 的描述右侧有一组单选按钮。此选项应设置为目标计算机的体系结构,而不是运行 Visual Studio 的计算机的体系结构。

远程工具由远程调试监视器和远程调试器配置向导组成。在最简单的部署中,您可以将远程调试监视器(msvsmon.exe)复制到目标机器上并执行它。要知道,每次想要初始化调试会话时,都需要执行监视器。配置向导的目的是帮助您将远程调试监视器设置为 Windows 服务,从而允许更经常地进行远程调试,而无需开发人员或 IT 人员付出额外的努力。

当您执行远程调试监视器时,拥有对计算机的管理员访问权限是很重要的。这可以通过以管理员身份登录或使用应用上下文菜单中的“以管理员身份运行”选项来关闭。当应用启动时,界面如图 7-13 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-13

远程调试配置

远程调试监视器要求安装 Window Web 服务 API 并配置 Windows 防火墙,以允许远程访问 Visual Studio 用来与监视器通信的端口。配置远程机器的必要选项可通过该对话框获得,该对话框仅在当前配置不允许远程调试时出现。您唯一的选择是应该允许哪些网络进行远程调试。作为标准的安全实践,建议只选择那些您真正需要的选项。虽然检查所有这些工作,但它确实有可能为运行它的机器打开一个攻击媒介。

当监视器启动时,它会显示一个包含状态信息的屏幕。图 7-14 显示了启动时的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-14

Visual Studio 2019 远程调试器状态信息

一旦远程调试器开始运行,Visual Studio 2019 就该开始行动了。现在,您连接到远程调试器所采取的步骤基于您正在调试的应用的类型。

ASP.NET 应用

对于 Web 应用,无论是 ASP.NET 还是 ASP.NET 核心,都可以通过使用“调试➤附加到进程”菜单来附加到远程调试监视器。在出现的对话框中(图 7-15 ,指定远程机器的名称,以及监视器监听的端口。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-15

附加到远程进程进行调试

默认情况下,对于 Visual Studio 2019,该端口为 4024。列表中可能已经包含了您正在寻找的进程,但是如果没有,请检查显示所有用户的进程,将每个正在运行的进程都包含在列表中。连接到所需的进程(通常是一个w3wp.exe进程),调试会话开始。

桌面应用

对于桌面应用,远程调试的配置在项目的属性中进行。打开 Properties 窗格(通过右击项目并选择 Properties)并导航到 Debug 部分,如图 7-16 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-16

桌面应用的调试窗格

选中“使用远程计算机”复选框,然后在右侧的文本框中填入远程计算机的名称和端口号。在开始调试之前,还需要满足几个其他条件。首先,Working directory字段需要为空,并且必须取消选中Enable native code debugging复选框。工作目录需要是空的,因为您将在远程机器上运行应用,所以在本地指定工作目录是无效的。并且远程调试当前不支持本机代码调试。

最后一个主要要求是,您要调试的应用的调试版本需要位于远程计算机上,与本地应用的调试实例位于同一路径。也就是说,路径中的所有文件夹都需要匹配,包括…/bin/Debug 文件夹(默认情况下)。通常,工作流是构建应用,然后使用您喜欢的方法将其复制到远程机器,然后启动调试会话。

Azure 应用

如果您已经将应用部署到 Azure 中,您仍然能够远程调试它。同样,路径取决于部署的类型。如果将应用加载到虚拟机(VM)中,远程调试的步骤与 ASP.NET 或桌面应用相同,具体取决于 VM 上运行的应用。然而,如果您部署到 Azure 应用服务中,步骤会有所不同。首先打开服务器浏览器并展开 Azure 节点(图 7-17 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-17

服务器资源管理器中的 Azure 节点

当您单击应用服务节点下的打开云浏览器选项时,它会启动云浏览器。在该窗格中找到的树包括所有 Azure 订阅,您可以使用 Visual Studio 中使用的当前凭据访问这些订阅。如果您尚未登录,系统会提示您提供 Azure 凭据,然后再继续。图 7-18 展示了应用服务节点展开后的云浏览器。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-18

云浏览器中的应用服务节点

右键单击要调试的应用服务。在出现的上下文菜单中(这可能需要几秒钟),选择“附加调试器”。这将您连接到远程调试器,方式与前面描述的 ASP.NET 应用部分相同。

快照调试

调试应用的另一个圣杯是致力于解决生产中出现的问题。很少有开发者没有遇到过那种“但是它在我的机器上工作”的感觉。虽然越来越多地使用模拟生产的测试和试运行环境降低了频率,但仍有在早期环境中工作的应用在生产中出现问题的情况。当人们真的在使用一个网站时,设置断点和单步调试代码的想法,伴随着所有其他线程的暂停,是行不通的。

快照调试器的目的是帮助解决这种情况。在应用执行期间的适当时刻,拍摄应用状态的快照。这个过程大约需要 10 20 毫秒,所以对性能有一定的影响。但是对整体用户体验的影响应该可以忽略不计。

在 Visual Studio 2019 中,您需要安装快照调试器组件。这是 ASP.NET 和 web 开发工作量的一部分。此外,你的应用需要运行在许多不同的环境中的一个:Azure 应用服务、Azure 虚拟机或运行在 Kubernetes 服务中的 ASP.NET 应用,在所有情况下,至少运行在 ASP.NET 应用上。NET Framework 4.6.1 或。网芯 2.0。

通常,执行快照调试的流程是打开要调试的解决方案。然后通过为应用指定端点来附加到快照调试器。此时,您正在调试应用,但不是以通常的方式。您可以指定对齐点,而不是指定断点。这个过程类似于设置断点。然而,不是暂停执行并允许您查看本地状态,而是制作本地状态的副本并继续执行。您仍然可以查看本地状态,但是应用不会暂停…这在您处理生产时非常重要。

现在,让我们更详细地介绍一下这些步骤。首先,打开已部署应用的解决方案。重要的是源代码与部署的版本相匹配。否则,您将会遇到与使用过时的源代码调试本地项目时相同的问题,也就是说,您的快照点将会受到影响。事实上,不匹配的源代码是尝试快照调试时出现问题的主要原因,所以如果您发现自己无法跟上,那么这应该是您首先要考虑的地方。

阅读解决方案后,选择“调试➤连接快照调试器”菜单项。出现如图 7-19 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-19。

附加到快照调试器

该对话框会记住您最后输入的内容,因此第一次附加时,两个下拉列表都是空的。在这两种情况下,下拉菜单都会弹出如图 7-20 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-20

选择 Azure 资源

下拉值的目的是让您确定要调试的 azure 资源以及将用于包含快照信息的存储帐户。对于这两个下拉列表,您选择 Azure 订阅,然后选择应用服务、虚拟机或 Kubernetes 服务(对于 Azure 资源值)或存储帐户(对于商店帐户值)。

当两个值都指定后,点击图 7-19 中的连接按钮,等待调试会话开始。如果这是你第一次在选择的资源上使用快照调试,你会看到一个如图 7-21 所示的对话框,询问你是否允许安装几个扩展。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-21

授予安装扩展的权限

虽然运行快照调试器需要这些扩展,但请注意安装这些扩展将会重新启动您的站点。重新启动可能会影响应用的状态。一旦安装了扩展,您将需要完成再次连接到快照调试器的步骤。毕竟,目标资源已经重新启动。

一旦连接到快照调试器,下一步就是设置快照点。在您想要放置对齐点的代码行左侧的装订线中单击。会显示一个六边形指示器来显示对齐点的位置。一旦快照点就位,您可以右键单击它以提供更多详细信息,例如拍摄快照点的条件。图 7-22 不仅显示了卡点指示器,还显示了可用的选项。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-22

已经设置了快照点

除了断点中可用的条件和操作,还有一个快照选项。您可以确定捕获的快照的最大数量。限制这些信息的原因是,每个快照都会占用您的 Azure 存储帐户中的资源。创建的快照越多,使用的存储就越大,因此产生的成本也就越高。通过限制快照的数量,您可以确保拥有数百个用户或将您的快照点置于循环中不会过度使用存储帐户。

识别快照点后,您可以通过单击工具栏中的“Start Collection”选项开始收集快照。或者使用“调试➤开始收集”菜单项。Visual Studio 会将快照点部署到资源。为了生成快照,您需要在 web 应用中安排放置快照的代码行,或者等待用户这样做。一旦快照命中,您将看到快照的详细信息出现在诊断工具窗口的快照调试器窗格中(图 7-23 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-23

连接到快照调试器时拍摄的快照

有关快照的详细信息可以通过单击快照来查看。但是,如果您想要查看快照的详细信息,包括状态,请单击相应快照底部的查看快照链接。或者您也可以双击快照。

此时,快照的内容被下载到您的本地机器上。这需要多长时间取决于您的网络速度,但有可能会有几分钟的延迟。

一旦快照可用,您将被置于代码中拍摄快照的位置。此时的视图看起来非常像典型的调试会话(参见图 7-24 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-24

快照调试视图

你现在看到的是 Visual Studio 中的历史调试。您可以访问拍摄快照时范围内的值。例如,“局部变量”窗口包含所有局部变量的值。您可以展开任何对象来查看属性值,以及任何其他相关的对象。“调用堆栈”窗口可用于显示代码到达这一点所采用的路径。你可以通过悬停在变量上来查看变量的值。

当然,你不能做的是单步调试代码,看看接下来会发生什么,或者改变变量的值来影响程序流程。这是您看到的历史信息,生成快照的请求早已完成。但是请记住,快照调试的目的是让您在生产过程中看到应用的状态。快照调试器绝对符合这个标准。

默认情况下,对于您设置的任何快照点,只拍摄一个快照。如前所述,您可以通过快照点设置窗格更改快照的数量(图 7-22 )。但是快照将只包含第一次点击快照点时的信息。如果要为快照收集另一个数据快照,请单击工具栏中出现的“更新集合”按钮,或者使用“调试➤更新集合”菜单项。

智能跟踪

与从生产环境中获取调试信息相关的挑战已经在快照调试器一节中提到。在那一节中,描述了一种适用于部署到各种 Azure 环境中的 ASP.NET 应用的技术。但是没有人会感到惊讶,Azure 并不是唯一一个。NET 应用已部署。IntelliTrace 的目的至少部分在于允许在服务器上捕获应用的状态(生产或非生产),然后由查看原始源代码的开发人员检查。

IntelliTrace 并不局限于在生产环境中使用。当测试人员发现的 bug 不能在开发环境中重现时,这是非常方便的。通过 IntelliTrace 捕获的信息可以附加到 bug 上,然后由开发人员在以后打开。

首先,IntelliTrace 收集器需要安装在运行应用的环境中。IntelliTrace 适用于在 7.0 到 16.0 版本的 Internet 信息服务(IIS)下运行的 ASP.NET 应用。但它也可用于从 SharePoint 2010 和 2013 应用、Windows Presentation Foundation(WPF)应用和 Windows Forms (WinForms)应用中捕获信息。收集器可以在微软下载中心找到( https://visualstudio.microsoft.com/downloads/#intellitrace-standalone-collector-for-visual-studio-2019 )。该下载是一个可执行文件。这个文件需要在收集信息的机器上执行。这可能是 ASP.NET 应用或 SharePoint 应用的 web 服务器,也可能是 WPF 或 WinForms 应用的用户机器。当它被执行时,它会创建一个IntelliTraceCollection.cab文件。一旦。cab 文件是可用的,命令expand /f:∗ <pathToCabFile>/IntelliTraceCollection.cab将用必要的文件填充目录。<pathToCabFile>是生成.cab文件的路径,或者是相对于当前目录,或者是完全限定路径。

您还需要创建一个目录,在其中可以创建 IntelliTrace 文件。它与IntelliTraceCollection.cab文件被展开的目录是同一个目录没有问题,但这不是必需的。然后,您需要确保运行该应用的用户对 IntelliTrace 文件目录拥有完全权限。

如果您计划在 web 或 SharePoint 应用上使用 IntelliTrace,有一些 PowerShell 脚本非常有用。使用 Install-Module cmdlet 安装展开的Microsoft.VisualStudio.IntelliTrace.PowerShell.dll文件。执行此操作的命令如下:

Install-Module -Name Microsoft.VisualStudio.IntelliTrace.PowerShell

现在您已经准备好捕获 IntelliTrace 文件了。无论您使用的是 web 应用还是客户端可执行文件,概念都是相同的。您将指定放置跟踪文件的位置,并确定 IntelliTrace 要使用的收集计划。收集计划是一个 XML 文件,它指定 IntelliTrace 运行时要捕获的事件。在可以使用的扩展文件中有许多标准收集计划。

对于 WPF 或 WinForms 应用,IntelliTrace 收集器不仅可用于开始捕获跟踪文件,还可用于启动应用本身。命令行的基本结构如下:

IntelliTraceSC.exe launch
   /cp:<collectionPath>
   /f:<pathToTraceFileDirectory>
   <pathToExecutableBeingTested>

需要注意的是,跟踪文件的位置路径必须是完全限定的路径。相对路径不行。

对于 web 或 SharePoint 应用,有一个 PowerShell cmdlet,尽管提供的信息基本相同。

Start-IntelliTraceCollection "<applicationPool>"
   <collectionPath> <pathToTraceFileDirectory>

应用池是运行 web 应用的应用池的名称。

现在复制你遇到的问题。当您运行应用时,会生成跟踪信息,但是您不一定能够看到跟踪文件(具有.itrace扩展名)大小的增加。您正在跟踪的应用需要在生成.itrace文件之前完成。对于 WPF 或 WinForms 应用,这只是一个终止应用的问题。对于 web 或 SharePoint 应用,运行以下命令停止收集信息:

Stop-IntelliTraceCollection "<applicationPool>"

所有这些活动的结果是一个.itrace文件。开发人员要使用它,需要将其移动到安装了 Visual Studio 2019 Enterprise 的机器上。一旦有了它,就可以打开它,为开发人员提供类似于快照调试器所提供的历史调试体验,其中有一个主要的变化。

IntelliTrace 和快照调试器都提供称为历史调试的功能。这意味着,即使调试会话是在不同的环境中执行的,它的信息对 Visual Studio 也是可用的。不同之处在于,快照调试是在单个快照点捕获的信息,而通过 IntelliTrace 捕获的信息允许您继续进行更传统的调试会话。

当你打开一个.itrace文件时,你会看到一个类似于图 7-25 的概述。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-25

iTrace 文件摘要窗格

可以看到许多可扩展的部分。你可能还能看到一些其他的。例如,如果应用中出现了异常,或者应用的某些部分的执行时间过长,那么将会有针对这些异常的可见部分。对于每一个部分,您都可以选择一项并单击一个按钮来开始调试。这将打开 IntelliTrace 事件或项目的详细信息。

调试事件时会发生什么取决于事件。如果您调试异常或性能冲突,并且触发事件在您的代码中引发,您将被带到代码中发生该事件的位置。此时,您可以使用调用堆栈、局部变量或自动窗口来查看变量的当前值。这就是历史调试带给你的。

但是,IntelliTrace 允许您继续执行。IntelliTrace 更像是一系列离散事件,而不是一个时间点。因此,一旦您完成了对一个事件的检查,您就可以进入下一个事件。现在,应用的状态变为捕获流中的下一个 IntelliTrace 事件。这样,你就可以跟踪应用的流程,从一个事件到另一个事件,向前和向后,寻找你试图解决的任何问题的原因。

诊断工具窗口

可通过调试➤窗口➤显示诊断工具菜单项访问的诊断工具窗口是用于帮助进行性能分析的工具的中心位置。虽然它们可能不会在日常生活中使用,但是当你需要它们的时候,它们在你的工具箱中是非常有用的。

通过诊断工具获得的性能信息用于监控 CPU 和内存的使用情况。虽然它们在可视信息方面是不同的,但它们是联系在一起的,因为它们是同时收集的,并且可以一起可视化。

在“诊断工具”窗口可用之前,需要将其打开。这是通过工具➤选项对话框完成的。导航到“调试➤常规”节点,并确保选中“调试时启用诊断工具”选项。

启用诊断工具后,当您调试应用时,“诊断工具”窗口将打开,并开始收集和显示信息。图 7-26 是一个应用运行一段时间后,这个窗口的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-26

诊断工具窗口

在图 7-26 中,窗口顶部有三个可展开的部分。它们针对事件(特别是 IntelliTrace 事件)、正在运行的进程所使用的内存量以及解决方案中所有进程的 CPU 使用情况。在最顶端,有一个调试会话的时间表。在深入了解一些细节时,您可以使用此时间表来选择会话的子集。

事件

“事件”选项卡出现在窗口的顶部。与时间线类似,它旨在帮助您确定要关注的诊断部分。事件的主要特征是沿时间轴以不同间隔出现的菱形。每个形状对应于一个被跟踪的特定事件。要查看事件的详细信息,单击窗口顶部的事件选项卡(图 7-27 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-27

诊断工具窗口中的事件选项卡

从列表中选择一个特定事件会显示该事件的更多详细信息。在列表的顶部,您可以按类别或来源(即事件发生的线程)过滤事件。或者您可以在右边的框中键入文本,它将只显示名称或描述包含匹配项的事件。

内存使用

图 7-26 中间的图表记录了一段时间内应用的内存使用情况。有两个指标标志着某些与记忆有关的事件何时发生。第一个是较小的橙色箭头。这表示在时间线内垃圾收集发生的时间。第二个是蓝色三角形,表示拍摄快照的时间。

虽然内存使用图表很好,但在确定应用中可能存在的任何内存问题的来源时,它并不是非常有用。在诊断工具窗口的底部,有一个内存使用选项卡。图 7-28 是该选项卡的一个例子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-28

内存使用选项卡

最初,这个选项卡是空的。使用它的关键是“拍摄快照”按钮。此按钮的目的是在特定时间点拍摄应用正在使用的内存的快照。它收集在堆中找到的所有信息,并显示对象的计数和堆的大小。您可以在应用运行过程中拍摄多个快照。这允许您比较一段时间内内存的大小和内容,这通常是识别内存使用来源的核心。

正如你所想象的,收集信息确实需要一点时间。您甚至可能会对应用中存在的对象数量感到惊讶。在 web 应用(用于生成图形的应用类型)的情况下,它不仅包括您已经创建的所有对象,还包括提供 web 页面所需的对象。因此,对于 MVC 应用,它包括会话信息、路由信息和用于构建呈现页面的对象。换句话说,有很多对象,虽然它们是为应用服务而创建的,但并不是显式创建的。

在图 7-28 中,您可以看到在流程的不同点拍摄了三个快照。对于每一张照片,您都可以看到拍摄快照的时间点。并且有一个对象计数和堆大小如何从一个快照变化到另一个快照的可视化表示。要深入查看特定快照的内容,请单击对象计数或堆大小值。或者选择一个快照,然后单击工具栏中的查看堆图标。详情见图 7-29 窗口。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-29

内存快照的内容

快照的详细信息分为两部分。顶部是组成快照的对象类型列表。每种类型的对象都包含在列表中。对于每种类型,您可以看到存在多少个对象以及对象的累积大小。实际上有两个大小的列。这两个值的区别在于 Size 列是特定对象的字节大小。包含大小列不仅是对象中的字节数,也是对象引用的子对象中的所有字节数。

图 7-29 的下半部分将所选对象类型的计数分为不同的派生类型。图 7-29 显示应用中的大部分数组列表对象实际上是 ConfigurationValue 对象。

如果要查看特定类型的各个对象的更多详细信息,请在鼠标悬停在特定行上时,单击显示在对象类型名称右侧的图标。该图标在图 7-29 中可见,在数组列表类型旁边。具体如图 7-30 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-30

检查特定对象类型的实例

在图 7-30 中,您可以看到所选对象类型的不同实例列表。对于每个实例,都有大小和包含大小,以字节为单位。在屏幕底部,您可以看到与图 7-29 中相同的衍生类型扩展。

拍摄快照的目的之一是比较内存随时间的增长情况。好吧,有可能记忆力会随着时间而下降。但这种情况发生的可能性有多大?

在用于查看不同对象类型的原始窗口的顶部,有一个包含当前流程的其他快照的下拉列表。通过选择其中一个快照,您可以比较两者之间对象的变化。该信息的可视化与图 7-29 相似,但也包括变更。如图 7-31 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-31

两个快照的比较

现在,这些列显示了快照之间在计数、大小和包含大小方面的差异。屏幕的下半部分包括对象类型及其派生类型的相同细分,其中有一列显示快照之间的引用计数差异以及绝对计数。

CPU 使用情况

图 7-26 中的下图以百分比的形式跟踪了应用运行期间的 CPU 使用率。如果您有多个 CPU,将在所有可用的 CPU 中计算百分比。有关 CPU 使用的更多详细信息,点击 CPU 使用选项卡以显示类似于图 7-32 所示的区域,但没有功能信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-32

诊断工具中的 CPU 使用选项卡

为了查看图 7-32 中可见的信息,应用必须暂停。窗格的初始状态包括一个 Break All 链接,单击该链接可以暂停所有线程。或者应用可以被您放置的任何断点暂停。当应用中断时,将收集到该点的 CPU 使用信息,片刻之后,显示如图 7-32 所示。

“诊断工具”窗口中还有另外两个元素会影响 CPU 使用率信息的显示。第一个是在 CPU 使用选项卡上。工具栏左侧是一个黑色或红色的圆圈。此图标用于开始或停止收集 CPU 信息。除非开启了收集过程,否则您将看不到任何详细信息。

第二个元素实际上是贯穿所有网格的东西,实际上在本节前面已经提到过。可以通过按住鼠标并沿着窗口顶部的 CPU 使用图表拖动鼠标来选择时间范围。然后,选择的时间范围成为生成 CPU 使用信息的界限。如果在指定的时间范围内未收集到 CPU 信息,则“CPU 使用情况”选项卡上会显示一条消息。否则,计算并显示使用信息。

如图 7-32 所示,使用信息显示了应用中不同组件使用的 CPU 数量。从图中可以看出,大部分时间都花在了外部代码上,这对于 web 应用来说并不罕见。但是您也可以看到几个控制器和一个利用 CPU 的模型。

但这些信息还不够详细,不足以采取行动。要获得特定组件中 CPU 使用情况的更多详细信息,请双击它。这将以如图 7-33 所示的形式显示详细信息。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 7-33

CPU 使用详细信息

在图 7-33 的顶部,你可以看到三个区域。左边是调用所选类的函数。右边是从所选类中调用的函数。中间区域包含所选类中使用了 CPU 的函数。对于每个函数,您可以看到 CPU 使用百分比。图 7-33 的底部将当前类的 CPU 使用率分解到行级别。

请记住,这个区域的目标是允许您在应用中导航,搜索 CPU 使用的来源。通过双击区域的所需部分来完成导航。例如,如果您想查看 AosWebManager 的用法。Lines 类中,您可以双击被调用函数区域的下半部分。这将修改 CPU 使用情况详细信息窗口中显示的数据,以便当前函数是 AosWebManager.Models.Lines .并且其他两个区域(调用函数和被调用函数)被调整为匹配。这项技术使您能够快速上下移动呼叫树,寻找潜在的问题。

摘要

调试是许多开发人员花费大量时间的地方。所以他们的开发环境提供的任何帮助都是受欢迎的。多年来,Visual Studio 一直处于调试辅助技术的前沿,最新版本也不例外。可用的工具不仅有助于解决一些更普通的情况,它们还可以让开发人员处理更具挑战性的场景,如识别生产环境中的问题,所有这些都有助于使 Visual Studio 像现在这样受欢迎。

但是诊断和调试并不是开发人员的唯一兴趣。事实上,Visual Studio 努力确保开发人员,不管他们使用什么语言,都能得到改进。在下一章中,我们将探讨使用 ASP.NET、Node.js、C++以及其他语言和平台的程序员可以使用的附加功能。

八、特定于语言的改进

虽然 Visual Studio 2019 中的许多改进在不同的语言和平台上都很有用,但总有一些更改是特定于个别语言的。它们满足了特定开发人员的特定需求。或者,这种语言的底层结构使得在不同平台上复制这种特性很难顺利实现。随着时间的推移,这些改进可能会出现在其他环境中,但是最初,它们只在某些工作负载中可用。

一个很好的例子是在第七章“调试和分析”中讨论的数据断点 C++开发人员可以使用数据断点为许多版本创建本机代码应用。支持数据断点的功能从未在。NET 框架。只有在 Visual Studio 2019 中,它们才可以被 C#应用访问,甚至只有在。NET 核心平台。

本着这种心态,本章将介绍 Visual Studio 2019 中的一些增强功能,这些功能更紧密地专注于一种语言或平台。即使您不使用这些环境进行开发,有时知道它们的存在也是有用的。至少,它可能会迫使你向微软提出建议,让他们花费必要的资源将该功能带给更多的用户。

总体改进

在我们开始介绍为支持个别语言而添加的功能之前,让我们花一些时间来介绍一些跨语言的功能,这些功能并不完全适合任何其他章节。

新闻部意识

众所周知,使用多台显示器的开发人员比只使用一台显示器的开发人员更有效率。无需切换应用即可查看代码、运行应用和浏览的能力惊人地强大。然而,在现实世界中,它并不是没有令人头痛的问题。拥有相同的显示器固然很好,但并不总是可能的。

分辨率、缩放设置或高于 100%的差异通常足以降低文本的清晰度。在这些情况下,经常会遇到模糊不清的文本。典型的情况是文本在一台显示器上看起来很棒,但在第二台显示器上就不那么清晰了。或者也许它只是在所有的监视器上看起来很糟糕。

Visual Studio 已经成为许多版本的 DPI(每英寸点数)感知应用。它被设置为系统感知模式。这意味着 Visual Studio 在确定如何呈现各种可视元素(包括文本)时将使用系统级分辨率信息。如前所述,当处理多个监视器时,这是一个问题。当远程处理到具有不同显示配置的机器时,这也是一个问题。

Visual Studio 2019 引入了每显示器 DPI 感知功能(PMA)。它要求。安装. NET Framework 4.8,并在 Windows 10(2018 年 4 月更新或更新版本)上运行。如果可用,它会自动激活。不同之处在于,它不是将单个设置(系统设置)应用于所有监视器,而是使用每个监视器的设置来确定元素的渲染方式。

虽然您不太可能想要禁用此功能,但是您可以选择。如图 8-1 所示,在选项对话框的环境➤常规部分有一个设置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-1

用于 PMA 支持的环境设置

如果您注意到在不同的监视器上看时,Visual Studio 中的文本或图标很模糊,那么查看此设置的主要好处可能就来了。如果相关的选项(标有优化不同像素密度屏幕的渲染的明显名称)是灰色的,这意味着您的系统不符合。NET Framework 4.8 或 Windows 10 要求。升级到这两个版本应该可以解决这个问题。

。NET Core 3.0 支持

2019 年,微软宣布发布。网芯 3.0。虽然这个名字看起来并不重要,但就所提供的功能而言,这是一个分水岭。NET 开发人员。第一次。NET Core 支持许多旧技术,包括 Windows 窗体(WinForms)和 Windows Presentation Foundation(WPF)。这对开发人员来说意味着您可以将旧的应用移植到。NET 核心,并让它使用最新的 API 集工作。

现在,并非所有平台都支持所有技术。WPF 和 WinForms 只能在 Windows 上使用。移植旧的应用需要注意一些问题。向后兼容性支持不是 100%。而微软内部也在努力打造类似的 surface。NET Core 2.0(及更高版本)和。NET 框架,有些差异不容易弥合。为了帮助确定可能存在的问题,微软提供了一个. NET 可移植性分析器,可以在 https://docs.microsoft.com/en-us/dotnet/standard/analyzers/portability-analyzer 找到。

除了支持 WinForms 和 WPF,还有一个新的窗体设计器可供这两者使用。然而,他们不是同时被释放的。WPF 设计器包含在 Visual Studio 2019 版本 16.3 中,因此您可能需要升级到 Visual Studio 的更高版本才能看到它。新的 Windows 窗体设计器的预览版在 16.4 版中提供。但是,默认情况下不启用。要使用新的设计器,您需要转到选项对话框的环境➤预览功能部分(图 8-2 )并手动启用它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-2

为启用预览 Windows 窗体设计器。净核心

C++改进

在 Visual Studio 2019 中,C++领域有许多增量改进,旨在帮助开发人员更新和调试他们的应用。有趣的是,这些改进说明了两种语言之间的交叉授粉。例如,数据断点对于 C#开发人员来说是新的,但在 C++中已经存在一段时间了。另一方面,C#有一个快速的动作,为几个版本添加对缺失包的引用。这相当于在 C++中将缺失的包添加到 CMake 中。

CMake 支持

CMake 是一个管理构建过程的开源工具。自 Visual Studio 2017 以来,它一直受 Visual Studio 支持,最新版本在许多方面对此进行了补充。

然而,你注意到的第一个变化可能会有点令人不安。CMake 菜单在 Visual Studio 2019 中不再是顶级菜单。但是不要害怕。并不是菜单项消失了。只是通过与 Visual Studio 的集成,这些项目已经移到了更合适的项目、构建、调试和测试菜单中。这种重组使普通 Visual Studio 用户更容易找到他们正在寻找的功能。直观地说,在 Build 菜单下找到 CMake Build 选项比在 CMake 菜单下更有意义。

CMake 设置编辑器

CMake 进程由 CMakeSettings.json 文件控制。这只是一个 JSON 格式的文本文件,包含用于控制 CMake 构建如何运行的属性。因为它只是一个 JSON 文件,所以可以使用任何文本编辑器进行编辑,包括在 Visual Studio 中。不过,根据开发者的反馈,Visual Studio 2019 包含了一个新的 CMake 设置编辑器,如图 8-3 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-3

CMake 设置编辑器

该编辑器可通过出现在现有配置列表底部的管理配置选项获得(见图 8-4 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-4

访问 CMake 设置编辑器

编辑器的左侧是为您的项目定义的配置列表。列表顶部的按钮用于添加、删除和克隆配置。当您添加配置时,您会看到安装在您机器上的 CMake 配置模板列表(图 8-5 ,尽管您的列表可能会有所不同)。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-5

添加 CMake 配置

屏幕右侧是管理实际设置的地方。有四个主要部分:常规、命令参数、CMake 变量和缓存以及高级。所提供的实际值取决于上下文(这超出了本书的范围)。例如,Linux 设置不同于 Windows 设置。但是任何开发人员都应该熟悉编辑这些值的机制。此外,默认情况下,高级部分是隐藏的。要查看和修改高级值,请单击编辑器底部的显示高级设置链接。最后,如果您想直接修改 JSON 文件,在编辑器的右上角,有一个编辑 JSON 链接,它将在文本编辑器中打开设置文件。

CMake 警告集成

当涉及到与 CMake 一起生成的警告时,Visual Studio 2019 包括几个不同的集成点。有些旨在帮助开发人员识别以前可能难以发现的问题。例如,不一致或不兼容的 CMake 设置(如使用 32 位生成器和 64 位配置)会生成警告,这些警告可在“错误列表”窗口中找到。

除了这种集成,您还可以配置生成的错误消息的级别。默认情况下,只显示错误。警告最终被禁止。但是,在 Visual Studio 2019 中,您可以对该行为进行更多的控制。图 8-6 显示了通过工具➤选项菜单可用的 CMake 设置页面。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-6

通过选项对话框进行设置

在图 8-6 的右侧中间,有一个启用详细 CMake 输出的选项。如果启用此选项,将不会禁止显示警告。如果您需要更深入地研究 CMake 问题,可以选择启用内部诊断日志来进行调试。这使得 CMake 本身生成的消息可以选择记录到文件中,或者显示在输出窗口的单独窗格中。

仅我的代码支持

“仅我的代码”是一项调试功能,在 C#和 Visual Basic 的许多版本中都是 Visual Studio 的一部分。前提是,在单步调试代码时,调试器将跳过您没有编写的代码。这将包括系统调用或某些类型的生成代码。这个想法是,在调试应用时执行的自动单步执行只会在您编写的代码处停止。

关于默认添加一个类似“仅我的代码”的特性,有趣的事情之一是总会有一群人需要能够关闭它。正如你所料(或者只是认为这是一个幸运的巧合),有一个设置可以做到这一点。在图 8-7 中,可以看到调试选项卡。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-7

启用“仅我的代码”设置

突出显示的设置用于启用或禁用“仅我的代码”。作为一个警告,这个设置不是特定于语言的。如果您禁用了“仅我的代码”并开始调试 C#应用,您可能会发现自己步入了意想不到的函数。

控件

如果你与 XAML 合作,无论是作为 WPF 开发人员还是因为你正在编写 UWP(通用 Windows 平台)应用,那么 Visual Studio 2019 中的添加和改进都非常令人兴奋。主要重点是改进您如何创建和调试 XAML,但还有其他一些您会发现非常有用的花絮。

热重装

您可能知道此功能是“XAML 编辑并继续”,但在此版本的 Visual Studio 中,它已被重命名为“XAML 热重新加载”。更改名称的理由是这个名称更接近于 web 应用中常见的热重装功能。使用 XAML,当重载发生时,应用不会暂停,正如“编辑并继续”这个名字所暗示的那样。相反,它只是对呈现的表单的即时自动更新。

热重载的目标是解决 XAML 设计者的一个长期问题——使用应用的运行时上下文调试应用的外观。在热重新加载之前,您需要查看应用,决定要更改什么,停止应用,进行更改,然后重新运行应用。如果需要多个步骤才能回到应用中的目标点,那就太糟糕了。

使用热重装,您可以在调试模式下运行应用时更改应用的 XAML。更改会立即被检测到,甚至不需要保存文件。然后为新的 XAML 触发组件的呈现,并且应用的外观会立即修改。

热重装有一些限制。从平台的角度来看,WPF 应用需要运行。NET Framework 4.6 或更高版本以及。网芯 3。而且需要 Windows 7 以上。对于 UWP 应用,您需要安装 Windows 10 或更高版本,SKD 版本为 14393 或更高版本。

但是局限性并不仅限于平台。存在一些功能性挑战,但数量惊人地少。大多数问题都可以通过暂停应用来解决。

例如,您不能在热重装中修改事件处理程序属性。也不能在应用运行时向其添加控件、类或其他文件。这包括对 NuGet 包的任何管理。而且,虽然它只适用于 UWP 应用,但您不能修改 x:Uid 指令。

从概念上讲,所有这些都是有意义的。在每种情况下,您实际上并没有改变应用的外观,而是改变了应用可执行文件的一些组件。因此,如果您需要进行类似的更改,暂停或重启应用是必要的。

从 Visual Studio 2019 开始,支持一个强大的功能。这就是调整 x:Bind 标记扩展的值的能力。这意味着作为热重新加载的一部分,您可以更改 XAML 中属性值的来源。

由于存在一些潜在的障碍,微软在应用内工具栏中添加了一个通知,该通知在调试 XAML 应用时可用。图 8-8 显示了当热重装可用时工具栏的样子。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-8

应用内 XAML 工具栏

您可以通过单击工具栏右侧的 v 形图标来显示或隐藏消息。

最后一个考虑事项只有当您在调试模式下从 Visual Studio(或者 Visual Studio 代码)中启动应用时,热重载才可用。如果使用附加到进程功能将调试器附加到已经运行的应用,则热重新加载功能将不可用。

应用内工具栏

因为我们已经看到了应用内工具栏,所以有一些小的调整来提高它的可用性。

现在,您可以在应用的顶部重新定位工具栏。工具栏的左侧有一个抓手,可以让你在窗口顶部拖动工具栏,如图 8-9 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-9

应用内工具栏重新定位

此外,您可能会注意到应用内工具栏的样式略有不同。在 Visual Studio 的早期版本中,工具栏总是深色的。它已经过修改,因此可以选择您在 Visual Studio 中使用的主题。

从功能的角度来看,有一个变化可能需要一些时间来适应。左侧第二个图标用于选择应用中的元素,并在实时可视化树窗格中选择相应的元素。以前,您可以继续选择元素,并让该行为继续下去(即,每个选择的元素修改活动视觉树)。然而,这令人困惑,因为它不同于各种浏览器中的开发工具的工作方式。应用内工具栏已经更改,因此一旦您选择了一个元素,后续的点击将不会选择其他元素。

只是我的 XAML

Visual Studio 2019 在调试会话期间有一个名为实时视觉树的窗口可用。它包含应用的整个视觉树,允许您深入甚至单个控件,以查看功能和视觉效果是如何实现的。尽管毫无疑问,实时视觉树具有很大的价值,但它一直受到一个重大问题的困扰。它会很快变得非常混乱。考虑图 8-10 中的实时视觉树。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-10

具有单个按钮的表单的实时可视化树

该树是从一个包含一个按钮的表单中生成的(如图 8-9 所示)。树的问题是它不能代表开发人员如何可视化表单。他们认为这是一个带有按钮的表单,而不是一个带有网格等内容呈现器的装饰器。从大多数开发人员的角度来看,动态视觉树应该只包含他们添加的组件。额外的元素虽然完全准确,却妨碍了对树的处理。

为了改善这种情况,Visual Studio 2019 引入了“仅我的 XAML”功能。类似于调试中的“仅我的代码”,当“仅我的 XAML”打开时(这是默认设置),实时视觉树仅显示开发人员添加的组件。图 8-11 显示了启用“仅我的 XAML”时同一表单的实时视觉树。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-11

打开“仅我的 XAML”的实时视觉树

虽然不那么杂乱的视图肯定有好处,但有时您可能需要所有的细节。您可以使用“实时可视化树”窗格工具栏中最右侧的图标在启用和禁用“仅我的 XAML”之间切换。或者,如果你喜欢一直关闭它,在工具➤选项对话框的调试窗格中有一个设置(见图 8-12 )可以用来禁用它。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-12

选项对话框仅显示我的 XAML 设置

。净核心

。NET Core 3.0 对于 Windows 应用的开发人员来说是一件大事,不仅仅是因为版本号比 2.0 大。3.0 版本完成了过去 5 年的旅程。当然,现在您可以构建在 Windows 上运行的服务器应用。而且这些应用将在 MacOS、众多版本的 Linux、iPhone 和物联网设备上运行。

客户端对的支持。网芯 3.0 同样令人印象深刻。你可以用。NET Core 3.0(只能运行在 Windows 平台上,不能运行在 Linux 或 MacOS 上)来构建 Windows 窗体和 WPF 应用。这意味着您可以将旧的桌面应用迁移到现在,并且知道它们在将来也会得到支持。除了对德高望重者的支持,还有对尖端技术的支持。。NET Code 3.0 提供了使用 Blazor 编写客户端 web 应用的能力。

WPF 表单设计器

而最初的情绪时,听到有一个设计师可申请 WPF 在。NET Core 可能是怀疑论,现实几乎是令人失望的。图 8-12 显示了的 WPF 表单设计器。NET Core 3.0,以及工具箱。3

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-13

WPF 表单设计器。网络核心 3.0

失望的原因?窗体设计器的外观和行为与 WPF 窗体设计器在 Visual Studio 的最后几个版本中的外观和行为非常相似,也就是说,它将会让 WPF 开发人员感到舒适和熟悉。

为了了解设计者,有一个针对 WPF 应用的项目模板。NET 核心。以这种方式创建新项目时,WPF 窗体设计器可作为默认设计器使用。因此,您可以双击 XAML 文件并打开设计器,就像您一直在做的那样。

WPF 支持的更有趣的作品。NET 核心正在从现有的 WPF 应用迁移到。NET 核心。有一些基本的差异需要解决,但是这样做的步骤有很好的文档记录,GitHub 上有一个示例项目(Bean Trader,在 https://github.com/dotnet/windows-desktop/tree/master/Samples/BeanTrader 找到)。

一般来说,迁移问题分为两大类。首先,添加引用包的方法需要更改为使用 NuGet。更重要的是,NuGet 引用需要作为<PackageReference>元素包含在.csproj文件中,而不是有一个单独的packages.config文件。虽然这不是一个要求,但是使用针对。NET 标准,而不是。NET 框架。这不是必要条件的原因是。NET Framework 开发工作已经指向目标。净标准。结果是,。NET Framework 4.7.2 具有坚实的。NET 标准 2.0 支持。并且该支撑在两者之间包括足够的重叠。网芯和。NET Framework 表面上看,许多包无需修改就可以工作。然而,如果有问题,你不会发现它,直到遇到运行时异常。

第二类也涉及到。网芯和。NET 框架。您的应用可能正在使用在任何或所有平台上都不可用的功能。NET 核心支持。如前所述,微软提供了一个. NET 可移植性分析器( https://docs.microsoft.com/en-us/dotnet/standard/analyzers/portability-analyzer )。该工具帮助您识别可能出现兼容性问题的区域,并能够识别。您的应用使用的. NET 核心。这在您确定能够支持您的应用的平台时非常有用。

Windows 窗体设计器

使用 Windows 窗体的流程。NET 核心设计器几乎等同于 WPF 应用。不同之处在于,虽然安装了设计器,但它仍处于预览模式。因此,默认情况下它是不启用的。相反,第一次通过双击 Windows 窗体组件启动设计器时,您会在顶部看到一个黄色通知栏,要求您启用设计器。通过工具➤选项对话框中的预览特征选项卡启用设计器(见图 8-14 )。请注意,在设计器可用之前,您需要重新启动 Visual Studio。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-14

启用 Windows 窗体。网络核心设计者

Note

Visual Studio 2019 的早期版本(16.5 之前)具有 Windows 窗体。NET Core Designer 作为一个单独的 VSIX (Visual Studio 扩展)包,需要在使用前下载并安装。在 Visual Studio 2019 的未来版本中,在设计器不再处于预览状态后,Windows 窗体设计器很可能会默认启用。

但是一旦启用了设计器,你会发现体验和你习惯的几乎一样。图 8-15 显示了 Windows 窗体。NET 核心设计师。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-15

Windows 窗体。网络核心设计者

转换为的过程。NET 核心版的 Windows 窗体类似于 WPF。一样的。在 WPF 部分描述的. NET 可移植性分析器工具对于识别潜在的问题是有用的。如果你使用的是 NuGet 包,那么把它们升级到目标包是个好主意。NET 标准,而不是。NET 框架。

Windows 窗体应用最有可能出现问题的一个方面是。NET API。这只是 Windows 窗体时代的一个结果。为了帮助缓解这些情况,微软提供了一个 Windows 兼容包。这是一个添加了许多 API 的库,这些 API 可用于 Windows 窗体应用,但在。NET 核心。当您考虑到软件包中大约有 20,000 个 API 时,您会很快意识到从 Windows 窗体移植时它是多么有用。您可以在 https://docs.microsoft.com/en-us/dotnet/core/porting/windows-compat-pack 找到关于该软件包的更多信息,包括如何将其添加到您的应用中。

计算机编程语言

Visual Studio 中对 Python 开发的支持是通过一组名为 Python Tools for Visual Studio(PTVS)的工具提供的。这些工具都是开源的,源代码可以在 GitHub ( https://microsoft.github.io/PTVS/ )上找到。但是,它们受 Microsoft 支持,并且可以通过将 Python 开发工作负载包含在 Visual Studio 安装程序中而包含在 Visual Studio 中。它也包含在数据科学和应用工作负载中。

Visual Studio 2019 中可用的 PTVS 版本的改进主要围绕单元测试功能。包含了对 pytest 单元测试框架的支持,以及使用从文件夹打开功能创建单元测试的能力。

设置使用 pytest 只是在早期版本的 PTVS 中如何设置 unittest 框架的一个扩展。右键单击项目名称,并从上下文菜单中选择属性。这将显示项目的属性。导航到左侧的测试选项卡。出现的下拉菜单(如图 8-16 所示)包括 unittest 和 pytest。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 8-16

为 Python 项目设置单元测试框架

现在。在执行测试发现过程时,将使用 pytest 的 ini 配置。如果您打开 Test Explorer 窗口,您将看到通过使用作为配置文件一部分的模式确定的测试列表。请记住,发现过程可能需要一分钟才能完成。

Visual Studio 2019 支持 Python 开发的打开文件夹场景。在这种情况下,您不是打开一个项目文件,而是将一个目录的内容作为整个 Python 项目使用。这是一种非常流行的使用 Visual Studio 来处理不是最初在 Visual Studio 中创建的现有 Python 项目的方式。

当使用打开文件夹方法时,您仍然可以确定要使用的测试框架。在 PythonSettings.json 文件中,可以添加许多 Visual Studio 将用来配置测试发现和执行的属性。以下是使用 pytest 的 PythonSettings.json 文件的示例:

{
   "TestFramework": "pytest",
   "UnitTestRootDirectory": "tests",
   "UnitTestPattern": "test_*.py",
   "SearchPaths": [ ".\\src" ]
}

属性标识了单元测试框架。UnitTestRootDirectory指定了包含测试的目录的名称。该目录将被扫描以查找匹配UnitTestPattern模式的文件。最后,如果您的源代码文件不在包含tests目录的同一个文件夹中,您需要指定包含源代码的路径。

摘要

Visual Studio 的体系结构是这样的,来自微软内部和外部的许多不同的团队都能够对环境的改进做出贡献。向更模块化结构的转变还允许不同的团队按照他们自己的节奏发布功能,而不是依赖于 Visual Studio 新版本的发布时间。因此,您会发现 Visual Studio 中新增的功能列表很难跟上。本章主要关注范围内的主要变化,但这不是一个广泛的列表,因为即使在本书出版时,不同的工具团队仍在继续发布新的功能。

本章有意遗漏的领域是与云计算机和容器相关的 Visual Studio 2019 的更改。这是因为它们中的每一个都足够重要,值得拥有自己的一章。这些变化将在接下来的两章中介绍。

九、Azure 工具

以这样或那样的方式,云已经成为大多数软件开发的中心。无论您是编写桌面应用、创建网站,还是使用移动设备,都可能有一个组件利用云,或者在适当的情况下能够利用云。

Visual Studio 已经发展到接受这种趋势。你可以在本书前面描述的实时分享功能中看到一些。但它也全心全意地支持使用 Microsoft Azure 作为云开发工作的基础。本章的重点是描述如何提供这种支持。

本章不会花时间详细描述微软 Azure 是什么。它包含了太多不同的片段,几个段落无法做到公正。很有可能在你写下这些段落和阅读它们之间,事情会有所改变。这就是云世界的发展速度。因此,Azure 的任何细节将只在所涉及的 Visual Studio 组件的上下文中提及。

云浏览器

Visual Studio 中 Azure 体验的核心是 Azure 云浏览器。通过云浏览器,您可以跨不同的资源组和订阅查看您的 Azure 资源。除了查看它们的属性,还可以对它们执行一些操作(列表取决于资源),包括开发人员识别和解决问题所需的诊断类型。

当您通过 Visual Studio 安装程序安装 Azure 工作负载时,云浏览器默认可用。安装后,它将作为云浏览器选项出现在“视图”菜单上。选中该选项后,出现云浏览器窗口,如图 9-1 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-1

云浏览器

图 9-1 显示了云浏览器的基本外观。窗口顶部是当前用户可用的 Azure 订阅列表。窗口底部的端口当前是空的,用于查看和修改单个资源的属性,以及针对资源启动不同的操作。

默认情况下,用于登录 Visual Studio 的凭据用于检索 Azure 资源。但是你不限于使用那个账户,甚至不限于使用一个账户。若要添加帐户,请点按面板顶部工具栏中的帐户图标(形状像人的头部和肩部的图标)。这将打开一个区域,在这里您可以看到与您的 Visual Studio 实例的 Azure 相关联的不同 Microsoft 帐户(参见图 9-2 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-2

在云浏览器中选择订阅

对于每个帐户,您可以看到与它们相关联的不同订阅。通过选中和取消选中相应的复选框,您可以指定这些订阅的资源在 Cloud Explorer 中是否可用。在列表的底部,有一个用于管理通过此窗格可见的帐户的链接。如果要添加或删除账户,点击链接显示如图 9-3 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-3

将 Microsoft 帐户与 Visual Studio 关联

这是用于定义 Visual Studio 帐户设置的同一个屏幕。在对话框的右下角,有一个关联帐户的列表。您可以添加帐户、移除帐户或对帐户应用过滤器。在这三个函数中,只有应用过滤器需要进一步解释。

可以将多个 Microsoft 帐户链接在一起,这样即使使用不同的电子邮件地址,它们也会被视为单一登录。这样,您只需登录一次,就可以访问每个关联帐户。通过应用过滤器,你可以看到链接帐户的列表,并选择在访问 Azure 时要使用的帐户。图 9-4 显示了点击应用过滤器时出现的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-4

对 Microsoft 帐户应用筛选器

如果有 Azure 订阅与任何选中的 Microsoft 帐户相关联,它们将出现在如图 9-2 所示的列表中。取消选中电子邮件地址将从列表中删除任何关联的订阅。

资源

一旦确定了帐户并选择了所需的订阅,您就可以返回到图 9-1 中的基本云浏览器。每个订阅都在树视图中可用。通过展开订阅,您可以看到按资源类型或资源组收集到组中的资源。图 9-5 和 9-6 显示了同一订阅的两个视图。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-6

云浏览器的资源组视图

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-5

云浏览器中的资源类型视图

资源类型视图根据资源类型将订阅中的资源划分为预定义的分组。如果您想要查看订阅中的所有数据库或虚拟机,它们将在您展开相应的节点时出现。

“资源组”视图将资源分成您定义的组。Azure 中资源组的概念是由管理员放入桶中的资源集合。也许资源是按部门、项目或地点分组的。选择权由管理员决定。

属性和操作

对于任何单个资源,都有许多关于资源的属性,以及可以在资源上执行的操作,这些都可以通过云资源管理器获得。这些显示在窗格底部的选项卡区域中。

要使用这个区域,首先要在树中导航,找到想要查看的资源。当您选择它时,适当的属性会显示在窗格的底部,如图 9-7 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-7

云浏览器中的属性窗格

显示的属性是只读的。如果你想对它们进行修改,那么你必须进入 Azure 门户网站。属性列表取决于资源的类型。有些人除了名字和类型之外什么也没有。其他人提供了更多的细节。

在操作窗格上也是如此,如图 9-8 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-8

云浏览器中的操作窗格

在操作窗格中,有一个可以对选定资源执行的操作列表。与属性相比,可能的操作列表会因所选资源而异。至少,每个资源都支持在门户中打开操作。这将启动 Azure 门户网站,自动将您置于所选资源中。此外,如果所选资源有任何子资源,将从这里进行搜索并执行刷新操作。所有这些都可以在图 9-8 中看到,都是与一个 App 服务相关的动作。然而,从图 9-8 中,您还可以看到其他操作,例如启动和下载发布配置文件。这些是特定于应用服务的,如果你转移到不同类型的资源,它们就会消失。

Note

如果在云浏览器中右键单击某个资源,也可以使用操作窗格中可见的选项。

物联网中心

云浏览器的一个新功能是支持物联网。Azure 支持创建物联网中心。对于物联网开发来说,物联网中枢是一种中央服务,通过它可以执行通信、身份验证和监控。如果您将您的物联网环境想象为一个工厂车间(见图 9-9 ),其中有数百个设备发送遥测数据并执行操作,那么物联网中枢就是该网络的中心,将这些设备相互连接(如果需要)并与其他服务连接。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-9

工厂中的物联网

就云浏览器而言,在许多方面,物联网中心就像任何其他 Azure 资源一样。它在资源树中可见,并且具有可用的属性和操作。图 9-10 显示了它在树和动作列表中的位置。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-10

云浏览器中的物联网中心操作

列表中的操作开始让人了解云浏览器具有的与物联网设备相关的功能。您可以在集线器中创建设备,可以是常规设备,也可以是边缘设备。这两种设备的区别在于它们的功能。常规物联网设备是连接到无线网络的非传统计算机(即,不是笔记本电脑、台式机、平板电脑或手机),能够发送数据,有时还能接收命令和执行操作。

边缘设备是具有允许其作为常规设备的监控能力的设备。它与常规设备通信,收集数据,然后将数据传回集线器。通常,它能够运行程序(通常使用 Docker 之类的容器基础设施部署),这使它成为半自治的。

除了通过云浏览器创建设备,您还能够为物联网中心生成共享访问签名(SAS)令牌。物联网集线器和设备使用此令牌来提供基于声明的身份验证机制。

云浏览器和物联网设备提供的更有趣的功能之一始于监控作为物联网中心一部分的事件端点的能力。事件端点是相关设备(常规设备和边缘设备)发送任何数据的地方。通过开始监视事件端点,您可以看到输出窗口中显示的所有传入消息。

这种监控功能很有用,但并不止于此。如果您在云浏览器中选择一个设备,操作列表会发生变化,如图 9-11 所示。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-11

常规物联网设备的操作

与物联网中心一样,您可以监控特定设备的传入事件。此选项可用是因为常规物联网设备可能拥有相关的子设备。因此该选项监视来自这些子设备的任何传入请求。

当谈到物联网集线器和设备之间的消息传递时,有四种操作可用。您可以开始或停止监控 C2D 消息。在此操作中,“C”代表云,“D”代表“设备”因此,你所监控的是从云(物联网中心)传递到设备的信息。如果您想要查看 D2C 消息(即设备到云),您可以监控物联网中心的事件端点消息。

但是监控并不是 Cloud Explorer 所提供功能的极限。您还可以在物联网集线器和设备之间手动发送消息,反之亦然。“将 D2C 消息发送到物联网集线器”操作会打开一个对话框,允许您输入将发送到集线器的消息,就像该消息是由设备生成的一样。“将 C2D 消息发送到设备”操作允许您输入一条消息,该消息将被传输到设备,就像来自物联网集线器一样。通过所有这些不同的选项,您可以非常灵活地诊断或纠正物联网基础设施中出现的任何问题。

对于您可能需要对物联网设备进行的任何诊断工作,还有一些其他措施可以提供帮助。有一个操作(调用设备直接方法)允许您将消息直接发送到特定的设备。当动作被触发时,系统会提示您输入方法名和 JSON 格式的有效负载。直接方法的想法是使用 HTTPS 将请求发送到设备的 URL。该请求包括指定的方法名和有效负载。预计设备将响应请求,但不要求有任何有效载荷。请求的结果出现在输出窗口中。

编辑设备 Twin 操作允许您在 IoT Hub 中编辑描述设备的 JSON 文件。这个 JSON 文件被称为 device twin,因为它描述了设备的属性和功能。它还包含设备的状态信息,因此可以使用设备提供的数据定期更新。

“创建模块”操作允许您为选定的 IoT 设备创建模块。物联网世界中的模块是一个独立的命名空间,通过它可以访问设备。然后,命名空间可以被赋予不同的访问规则,以便它们可以彼此独立地受到保护。远程维护的自动售货机就是一个例子。虽然自动售货机被认为是单个设备,但机器中可能有多个传感器。例如,一个传感器可能指示机器中仍有多少物品,而另一个传感器可能指示剩余的零钱数量。每组数据可能由不同的部门负责。在这种情况下,设备将包含两个模块,一个公开与清单相关的消息,另一个公开与变更相关的消息。

触发创建模块操作会向物联网设备添加子项。您输入模块的名称。如果您右键单击该模块(或查看其操作窗格),您可以编辑该模块的模块孪生。类似于 Device Twin,这是一个基于云的 JSON 文件,描述了模块的元数据、状态和功能。

最后,为设备操作生成 SAS 令牌。这是为物联网集线器创建 SAS 令牌的相应操作。该操作会生成 SAS 令牌,设备可以使用该令牌与物联网集线器进行通信。完成生成所需的输入是令牌的生命周期(以小时为单位)。该值决定了在需要生成另一个令牌之前,该令牌将持续有效多长时间。

Azure 函数

Azure 函数的官方定义(改写自 Azure 文档)是一种无服务器的计算服务,它运行事件触发的代码,而不需要提供支持基础设施。这个定义中有很多概念,所以让我们用几个段落来分解细节。

Azure 函数的根本目标是运行一段代码。它与您可能运行的其他代码的不同之处在于,它被设计成无需预先部署服务器就能执行这段代码,因此有了“无服务器”这个形容词。当您部署 Azure 功能时,您指定的是正在执行的代码,而不是它将在其中执行的环境。当它需要运行时,会在函数执行前动态构建环境。

代码本身可以用多种不同的语言编写:C#、Java、JavaScript、Python 或 PowerShell。支持的不仅仅是语言。您可以绑定不同类型的资源(队列、数据库、SendGrid 等。)以声明方式添加到您的函数中。对于 C#,属性用于将函数连接到资源。对于其他语言,绑定在一个function.json文件中声明。

该功能的执行是通过几种不同的机制启动的。其中一个更简单的是计时器。在这种情况下,该功能按照常规的预定时间表执行。但该函数也可以基于外部事件开始运行,比如队列中消息的到达、HTTP 请求或 Azure 事件网格中引发的事件。通过这一系列的触发器,Azure 功能的使用数量非常多。所以我们来看看 Visual Studio 在这个过程中是如何使用的。

创建 Azure 函数

Visual Studio 2019 提供了一个项目模板,可以作为你的 Azure 函数的起点。只要您在 Visual Studio 实例中包含了 Azure 开发工作负载,就可以使用该模板。还要注意,为了部署 Azure 功能,你需要一个 Azure 订阅。除了用 HTTP 请求触发的 Azure 函数之外,您还需要有与函数相关联的 blob 存储。但是不要让需求压倒一切,尤其是在成本方面。有一些免费资源足以让你的第一个 Azure 功能运行起来。

Azure 函数的起点是使用内置模板创建一个新项目。使用文件➤新➤项目菜单项启动对话框(见图 9-12 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-12

Azure 函数的新项目对话框

在对话框右侧显示的已安装模板列表中,找到 Azure Functions 模板。在图 9-12 中,顶部的搜索框已经被使用。选择模板,然后单击下一步。这将打开用于命名新项目和指定位置的对话框(图 9-13 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-13

新建项目配置对话框

提供必要的配置信息后,单击“创建”按钮。这将打开用于选择您正在创建的 Azure 函数类型的对话框。图 9-14 显示了该对话框。正是在这个对话框中,你开始有特定于 Azure 功能的选择。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-14

创建新的 Azure 函数应用对话框

在创建 Azure Function 项目之前,您需要指定四个不同的属性。它们是平台、模板、存储帐户和授权。接下来的几节将更详细地介绍。

平台

Azure 函数支持三种不同的运行时环境,这些环境或多或少与不同版本的发布时间相对应。做出选择。对于 Azure 函数 v1。NET Framework 4.6 是受支持的运行时。对于 v2,增加了对的支持。网芯 2.2。最新的版本是 v3。支持网芯 3.0。

不同的版本也有不同的语言支持。Azure Functions v1.0 版仅支持 C#、F#和 JavaScript。在 v2 中,增加了 Java、PowerShell、Python 和 TypeScript。

还有一个变化会影响不同版本 Azure Functions runtime 的开发。随着从。NET 框架到。NET Core,一些不同的触发器和绑定(除了 HTTP 和 Timer)需要在绑定可用之前安装一个扩展。如果您使用下一节中描述的模板之一,就会安装该扩展。但是,如果您选择空模板,您将需要手动添加扩展。这可以通过一个 NuGet 包来完成,所以机制是熟悉的。

模板

在 Visual Studio 中创建 Azure Function 应用的优势之一是可以帮助您入门的模板。不一定需要模板。有一个可用的空模板,您可以手动添加必要的配置和扩展。但是如果你在开始之前知道你的函数将要使用的触发器,那么这个模板会让事情变得更简单。

触发器和绑定都是 Azure 函数的一部分,尽管只有触发器是模板的一部分。触发器是启动功能的事件。请记住,Azure 函数背后的思想是,它们是为了响应某些外部事件而执行的。触发器类型决定了生成外部事件的底层技术。绑定还指定了一种技术。不同之处在于,绑定可以是函数的输入或输出(或两者都是),而不是启动事件。

例如,考虑一个想要检索图像缩略图的传入 HTTP 请求。Azure 函数将由 HTTP 请求触发,使用 blob 存储绑定来获取请求的图像,然后输出包含图像缩略图版本的 HTTP 响应。触发技术是 HTTP。绑定是 blob 存储(输入)和 HTTP(输出)。

提供了许多内置模板。您可以在图 9-14 中看到运行时选择下方的部分列表。在下文中可以找到更完整的列表和说明。请注意,每个模板中的触发器只是一个起点。您可以在开发过程中添加或删除触发器和绑定。

Blob 触发器

当添加新的 blob 或更改现有 blob 时,Blog 触发器启动该函数。该函数被绑定到一个 Blob 存储帐户,该帐户是监视更改的存储库。当触发触发器时,新的或更新的 blob 作为参数提供给函数。

Cosmos DB 触发器

Cosmos DB 是一种 NoSQL 风格的数据存储技术。它允许将项目存储在容器中,其中“项目”是一段与模式无关的数据,类似于 MongoDB 中的文档。Cosmos DB 中的容器类似于数据库表,尽管更准确地说它是文档所在的名称空间。

每当修改或添加特定容器中的一个项目时,Cosmos DB 触发器都会调用该函数。触发器中包括修改或添加的项目。

事件网格触发器

Azure Event Grid 是一项允许开发人员轻松构建基于事件的消息应用的服务。它使用发布和订阅模型工作,方式与 Azure Service Bus 相同。但是,它不是传递消息,而是发送事件通知。是的,通知可以包括数据。但是这些数据只是事件的一部分,不会在事件引发后持续存在。在这方面,它不同于 Azure 服务总线。有了事件网格,发送者就不需要知道谁将处理事件或者事件是否会被处理。

每当相应的发布者引发事件时,事件网格触发器就会执行该函数。在这方面,事件网格触发器在事件网格支持的发布/下标模型中充当订阅者。

事件中心触发器

事件网格名称的相似性掩盖了它的不同之处。Event Hub 是一个 Azure 服务,支持数据流的捕获和处理。这是一个大数据管道,传递信息,如遥测或状态,可能来自多个并发源。通过这种方式,它将自己与事件网格和服务总线的离散负载区分开来。当你设计一个带有事件中心触发器的 Azure 函数时,你需要意识到每秒钟可能会发生成千上万个触发器。

当通过事件流接收到事件时,触发事件中心触发器。通常有与事件相关的数据,但它只是作为字符串值键入。

Http 触发器

当通过 HTTP 管道收到请求时,将触发 Http 触发器。这允许使用任何能够提交 HTTP 请求的技术来启动 Azure 函数,公平地说,这几乎是所有技术。

对于触发器的发送者,响应要么是 HTTP 200 状态代码(对于 Azure 函数 v1),要么是 HTTP 204 状态代码(对于 Azure 函数 v2 和 v3)。无论如何,没有迹象表明由事件触发的功能是成功还是失败。如果这是您的应用的要求,那么您需要向该函数添加一个 HTTP 输出绑定。

物联网集线器触发器

物联网中心触发器与事件中心触发器非常相似。物联网集线器负责发送与一个或多个物联网设备相关的事件数据流。随着每个事件的到来,Azure 功能被启动。与物联网中心事件相关的任何数据都以字符串数据类型传递给该函数。

队列触发器

队列存储是 Azure 中的一种存储类型,它模仿队列的功能。发送方发送的消息被接收到队列存储中。这些消息一直保留在队列存储中,直到被队列消息的接收者删除。

有了队列触发器,Azure 函数的执行就变成了排队消息的接收者。当消息到达队列存储时,函数被调用。排队的消息作为参数提供给函数。

服务总线触发器

Azure 服务总线是最古老的 Azure 技术之一。它支持企业服务总线的传统概念。消息以先进先出的方式接收和处理,并具有有保证的传递、事务支持和过滤功能。

服务总线触发器在消息到达服务总线时启动 Azure 功能。触发器既可以针对整个服务总线队列进行操作,也可以针对该队列中的一个主题进行操作。对于后一种情况,您将选择服务总线主题触发器,而不是服务总线触发器作为模板。

定时器触发器

虽然这个模板在列表中按字母顺序排在最后,但它在许多应用中是一个非常常见的请求。前提很简单。你希望有一个功能,你希望定期运行可能是每小时,每天,甚至更复杂的情况。但是在适当的时候,你希望函数被执行。定时器触发启用这种能力。

关于定时器触发器有趣的部分是如何指定时间表。Azure 函数使用 NCRONTAB 格式来计时。这种格式类似于 CRON 格式,具有允许识别精确到秒的执行时间的扩展(CRON 将执行限制到分钟)。

存储帐户

除了 Http 触发器之外,所有触发器模板都需要存储帐户。在创建对话框中,窗口右上角有一个下拉菜单,您可以在其中指定将要使用的存储帐户。

下拉列表中有三个选项:无、存储模拟器和浏览。对于大多数触发器(即除 Http 之外的所有触发器),您可以选择 Storage Emulator 作为起点。这允许你开发你的 Azure 函数,而不必首先识别存储帐户。相反,在开发应用时,它使用 Visual Studio 中的存储模拟器功能。但是,在部署完整的应用之前,您需要选择一个存储帐户。如果您没有选择,部署时会自动创建一个存储帐户。

如果您已经知道将在部署时使用哪个存储帐户,请选择浏览选项。这将打开一个对话框(如图 9-15 所示),可用于选择要使用的存储帐户。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-15

选择现有存储帐户

批准

创建 Azure 函数项目时最后一个可用的选项是为 Azure 函数设置授权。用于设置值的下拉列表位于存储帐户的正下方。可用选项包括功能、匿名和管理。

这些选项中最简单的是匿名。使用该选项,根本不执行任何授权。任何请求都被接受,不做进一步的检查。

Function 选项利用作为请求的一部分发送的密钥来限制谁有权访问 Azure 函数。有两种类型的键可用:主机和功能键。你的 Azure Function app 公开的所有函数都使用主机密钥。一个功能键专门绑定到一个功能,这意味着您需要不同的功能键,每个公开的功能一个。

Note

认识到使用功能键并不是访问 Azure 功能的完全安全的方式是非常重要的。用于访问功能的密钥不一定是加密的。例如,如果您使用 Http 触发器,则可以在 URL 的末尾或标头中作为不记名 cookie 传递密钥。该密钥没有加密,因此,如果请求被捕获,恶意用户可能会查看并保存该密钥,并在将来使用它来发送请求。

最后一个选项是 Admin。这类似于 Function 选项,因为请求时需要传递一个键。不同之处在于,唯一允许的密钥类型是主机密钥。如果传递了功能键,则返回 HTTP 状态 403(未授权)。

Function 和 Admin 选项都要求任何传入的请求中都要有一个键。密钥的生成是通过 Azure 门户完成的。不提供使用云浏览器生成密钥的功能。

项目文件

一旦指定了 Azure 函数需要的所有信息,单击 Create 创建项目。只有几个文件包含在生成的项目中。有一个 Function1.cs 文件包含一个示例 Azure 函数。这是一个静态类,有一个 Run 方法,用各种属性修饰。通常,该类将被删除或重命名,以便为函数提供更具描述性的名称。

项目中还有另外两个重要的文件。它们都是 JSON 文件,包含函数使用的配置信息。

  • hosts.json 包含应用于函数应用中定义的所有函数的元数据。这包括实例模型(无论是否是单例模型)、日志记录细节、用于调用函数的触发器以及输入和输出绑定等细节。

  • local.settings.json 包含函数在本地运行时使用的设置。这包括连接字符串、应用设置(典型的键/值对)和宿主详细信息。该文件仅用于本地执行。当您部署函数应用时,您需要配置此文件中包含的设置,以便在 Azure 中使用。这将在下一节“部署 Azure 功能”中讨论

部署 Azure 功能

一旦你完成了功能的开发和测试,就该把它部署到 Azure 了。对于 Visual Studio,部署是通过使用发布选项启动的。如果右键单击该项目,可以单击“发布”菜单项。或者您可以使用“生成”菜单中的“发布”项。无论您使用哪种方式,第一次发布项目时,都会出现如图 9-16 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-16

选择 Azure 发布目标

在实际部署函数应用之前,需要创建发布概要文件。接下来的几个对话框是用来创建概要文件的。如果您已经有一个可用的配置文件,您可以通过单击左下角的 Import Profile 按钮来使用它。

在继续之前,您需要注意,当您选择目标时,图 9-16 中可见的目标列表可能不会全部出现。可能的目标列表取决于您导入的概要文件,以及您用来创建应用的模板。例如,如果您使用常规的。NET 框架应用,那么在几个段落中描述的 Azure 功能计划可能不会出现。

在左边,您从五个不同的发布目标中选择一个。最简单的是列表底部的文件夹选项。如果部署到文件夹,则会创建一个 ZIP 部署包。这个包是一个 ZIP 文件,它的结构是 Azure 可以识别的。它允许您创建一个部署包并将其交给某人,然后此人可以将其部署到他们自己的 Azure 订阅中。

其他四个选项分为两个独立的组。前两个是 Azure Functions 消费计划和 Azure Functions Premium 计划。对于这两个计划,您的函数主机是根据传入请求的数量动态添加和删除的。因此,从这个角度来看,您的功能可以根据需求扩大和缩小。这是你应该从 Azure 函数的无服务器环境中期待的。

这种差异与环境的环境准备度有关。对于消费计划,您为正在使用的资源付费。一旦你的函数用完了它们,你就不再为它们付费了。这包括内存和计算时间。但是当发出请求时,可能会有短暂的延迟。如果前一个函数已经完成,则内存和计算资源已经被释放。它们需要被重新分配以处理请求。这需要一小段非零的时间。

另一方面,premium 计划总是有一个 warm 实例备用。因此,无论何时收到请求,都会有内存和计算资源准备好处理它。自然,这是有代价的。除了运行该功能所产生的成本之外,您还需要为待机模式下维护的资源付费。

一般来说,你的选择取决于对你的职能的要求。如果对你的功能有持续的需求,那么溢价计划是有意义的。它确保了您的函数对每个请求的响应时间始终是良好的。如果对你的功能的需求是不稳定的或集中的,那么消费计划更有意义。响应时间可能不一致,但是您不会为只是偶尔需要的资源付费。

其他两个发布目标(Azure App Service Plan 和 Azure App Service Plan Linux)都涉及到将您的功能部署到应用服务虚拟机(VM)上。这可能是一个已经在你的订阅中托管一个或多个网站的应用服务。因此,通过这个计划,您可以选择您需要的大小(内核和内存的数量)和隔离(共享或专用)。而且两个方案之间,区别在于底层服务器操作系统是 Windows 还是 Linux。

对于除文件夹之外的所有发布目标,您可以选择创建新的应用服务或使用现有的应用服务。如果您选择使用现有服务,单击创建配置文件会显示一个类似于图 9-14 的对话框,您可以在其中浏览您的订阅以选择所需的应用服务。如果你想为你的 Azure 功能创建一个新的应用服务,点击创建配置文件会显示如图 9-17 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-17

为部署创建新的应用服务

此对话框中的可用信息用于配置将要创建的应用服务。需要明确的是,即使您当前正在创建用于部署的配置文件(而不是实际部署应用),如果您单击 Create 按钮,将会创建一个新的应用服务。换句话说,部署过程不会创建应用服务。你实际上正在创造它。

一旦您完成了概要文件的创建,或者如果这不是第一次发布函数应用,下一步就是实际触发部署。图 9-18 显示了用于开始部署到 Azure 的屏幕。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-18

发布 Azure 函数

对话框的顶部是一个下拉列表,包含项目的发布概要文件列表。您在本节前面经历的步骤创建了一个概要文件(在一个.pubxml文件中找到)。但是没有什么可以阻止您为一个项目拥有多个概要文件。发布过程非常简单,只需选择所需的配置文件并单击发布即可。下拉列表下方的区域是所选配置文件的设置摘要,这样您就可以在触发部署之前知道自己在做什么。

在对话框的右侧,有几个链接指向您可以采取的快速操作。顶部的链接“在云浏览器中管理”会打开云浏览器窗格(图 9-19 )。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-19

云浏览器中的 Azure 功能应用服务

在 Cloud Explorer 中,您可以查看应用服务的部署槽,以及上传和下载与服务相关的文件(至少是文本文件,如hosts.json和任何日志文件)。

第二个选项,编辑 Azure 应用服务设置,在本章前面提到过。local.settings.json文件包含功能应用在本地运行时使用的设置。此点击允许您配置当您的函数应用在 Azure 上运行时将使用的设置。点击链接显示如图 9-20 所示的对话框。

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

图 9-20

定义 Azure 功能应用设置

为了了解对话框正在做什么,local.settings.json文件的相关部分如下所示:

"Values": {
   "AzureWebJobsStorage": "UseDevelopmentStorage=true",
   "FUNCTIONS_WORKER_RUNTIME": "dotnet"
}

您可以看到该应用有两种设置。这两种设置出现在图 9-20 中,本地和远程值均可用。对于存储设置,指示在开发过程中应使用本地存储模拟器的值已被发布配置文件中指定的存储的连接字符串所替换。对于其他设置,复制了本地值。您可以更改已定义设置的值,包括附加设置(使用添加设置)链接,以及删除设置(使用每个设置右侧的 X。

除了在local.settings.json文件中明确定义的设置之外,还有其他可以访问的环境值。由于它们可以被访问,所以当使用相同的机制将函数应用部署到 Azure 时,您可以指定所使用的值。

摘要

Azure 是微软领域中的一项主要技术,所以在 Visual Studio 中对它有相当多的支持是不足为奇的,无论是开发还是管理部署的应用。

除了 Azure 之外,还有另一项技术正在大举进军开发和部署领域:容器。容器不仅允许您将应用捆绑在一起,还允许您将与应用相关的基础设施捆绑在一个包中。然后,可以在小型、可任意使用的虚拟机上部署和执行该包。下一章将更加详细地介绍容器背后的概念,更重要的是,微软如何通过 Visual Studio 2019 支持它们。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值