c# - 尝试从 TFS 工作区检索文件会使应用程序停止

标签 c# tfs tfs-sdk

所以我试图从 TFS 的工作区中检索文件。不幸的是,我为此所做的每一次尝试都会导致应用程序停滞。截至目前,这是代码:

    public void GetWorkspaceFiles(string workspaceName)
    {
        VersionControlServer sourceControl = (VersionControlServer)TfsServer.GetService(typeof(VersionControlServer));

        var items = sourceControl.GetItems(workspaceName, VersionSpec.Latest, RecursionType.Full)
                                 .Items
                                 .Where(x => x.ItemType == ItemType.File)
                                 .ToList();

        for (int x = 0; x < items.Count; x++)
            items[x].DownloadFile();

每次我运行此应用程序(在多台机器上)时,它都会在 items[x].DownloadFile() 上停止。 TFS 中的所有文件都没有被锁定,一切正常。尝试使用 Workspace.Get() 方法会产生同样的结果。

如果我点击暂停,x 将是一个特定值,但我无法访问项目集合,因为当我这样做时我得到“无法计算表达式,因为当前线程处于 sleep 、等待或加入状态”。当我评估调用堆栈时,我得到:

[In a sleep, wait, or join]
[External Code]
GetWorkspaceFiles(string workspaceName) Line 55

我不知道该怎么做。每当我暂停应用程序时,x 始终处于相同的值(它停止的值对于每个运行的应用程序都是不同的)。

有人有什么想法吗?


编辑: 添加诊断逻辑(基于 Grant 回答中的链接)后,我比以往任何时候都更加困惑。

我传递给这个方法的工作区是$/QA/Automated Test Scripts/Regression or System Test Scripts/RDE or Condo(通过调试器验证)。

但是,当我查看 tfs 日志时,它看起来正在下载我正在运行的代码文件,如它所说:

02/10/2011 12:26:58 (pid 5808, tid 5968, 42180 ms) Recording OperationStatus.Getting for $/QA/Automated Test Scripts/QA Tools/Test Manager/Test Polling Server/fmMain.cs

在该条目之后是:

02/10/2011 12:26:58 (pid 5808, tid 5968, 42180 ms) DownloadFiles: 18 ms
02/10/2011 12:26:58 (pid 5808, tid 5968, 42181 ms) Acknowledgements: 0 ms

此后日志文件没有进一步更新,我的应用程序停止了。我困惑的是

1) 当我指定一个完全不同的 TFS 工作区时,为什么要尝试从 TFS 中提取应用程序代码

2) 为什么在尝试检索文件后会停止?可能是因为 fmMain.cs 在 Visual Studio 中打开了,但它应该仍然会异常输出并且不会挂断。当文件正常通过 visual studio 打开时,我可以获得最新信息。



编辑2:

好的,我在阅读 MSDN 时注意到工作区名称可以是文件的本地路径。因此,我将作为 workspaceName 参数传入的内容修改为文件的本地目录。我仍然遇到停顿,但日志文件并不清楚原因。我已经上传了 tf.log 文件 here (我显然已经更改了专有信息,例如服务器和项目名称,但其他一切都没有改变)。在最后一个日志条目之后,没有进一步的数据写入日志。

最佳答案

GetItems 不采用工作区名称,它采用服务器路径来获取文件列表。如果您想从特定区域获取文件副本,您需要做的是:

  var items = sourceControl.GetItems("$/Project/Path/subpath"/et cetera", VersionSpec.Latest, RecursionType.Full)
                                 .Items
                                 .Where(x => x.ItemType == ItemType.File)
                                 .ToList();

当你打电话时

items[x].DownloadFile();

它向您返回一个流,而不是实际将文件下载到磁盘。如果您想在此时将文件写入磁盘,则需要进行正常的流处理才能将其写出。

如果您实际上是在尝试将文件从 TFS 获取到工作区,则情况有所不同。

        VersionControlServer sourceControl = coll.GetService<VersionControlServer>();

        var ws = sourceControl.QueryWorkspaces(workspaceName, null, null);

        var status = ws[0].Get();

(需要添加错误处理)

这将使用来自服务器的文件刷新您的工作区。它将像 Visual Studio UI 一样工作,因为它将比较当前磁盘上的内容与存储库中的内容,如果存在更新版本,则会更新本地版本。

Get() 方法有许多重载,您可以使用它们来指定您正在寻找的确切行为。

--编辑--

当您调用 Workspace.Get() 时,它所做的第一件事是转到 TFS(使用 Web 服务调用)并获取文件列表。然后,它遍历这些文件,将您在该工作区中已经“获得”的内容与您请求的修订版本(或 VersionSpec.Latest,如果您未指定任何其他修订版本)进行比较。

此过程可能需要一段时间。这就像右键单击并获取工作区中每个映射目录的最新信息。

如果您的工作区映射到 $/,它将遍历 TFS 中的所有文件。如果您有多个路径到本地路径的映射,它会遍历每个路径,并且会在本地检索并保存您尚未获得的任何文件。

刷新整个工作区可能会花费很长时间,除非您对映射的内容非常小心。

-- 编辑 2 --

如果您希望限制获得的数量,您有多种选择。第一个选项是限制您正在访问的工作区内的映射。例如,如果您的工作区只有一个到 $/Project/Branch/Source/Utilities/MyUtility 的映射,则只会获取该映射中的文件。

在我们的一些内部实用程序中,我们甚至做到了:

  • 动态创建工作空间
  • 仅为我们需要获取的那些路径将路径映射到目录
  • 做一个获取
  • 编辑某些文件(使用 PendEdit() 方法)
  • checkin 更改的文件
  • 最后,删除工作区

如果您只是尝试自动刷新一组文件,这将是一项繁重的工作,因此您可以将路径传递给 Get() 方法:

var status = ws[0].Get(new GetRequest("$/path/to/subfolder", RecursionType.Full, VersionSpec.Latest),
                   GetOptions.Overwrite);

关于c# - 尝试从 TFS 工作区检索文件会使应用程序停止,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4958113/

相关文章:

testing - 想去掉 TFS 中的 Test Hub 并与 Test Rail 集成

tfs - 将工作项导入 TFS 2010

c# - 更改事件项目中 TFS 解决方案的结构?

c# - 使用 TFS API 和 SSRS 以编程方式生成报告

c# - 不要在外壳托盘上显示窗口

c# - .NET 正则表达式匹配方法中一致的字符串开头 anchor 行为

c# - 与 ILMerge 合并后找不到 Entity Framework

c# - 具有 "has property X"约束的通用函数?

visual-studio-2010 - 通过 API 创建新工作项时,无法在 TFS 中获取分配给字段的有效用户列表

c# - 限制 TFS WorkItemStore.Query 的结果