试图从TFS工作区停止应用程序检索文件

时间:2011-02-10 14:10:17

标签: c# tfs tfs2010 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将是一个特定值,但我无法访问items集合,因为当我这样做时,我得到“无法计算表达式,因为当前线程处于休眠状态,等待或加入”。当我评估调用堆栈时,我得到:

[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正常打开时,我能够获得最新信息。

<小时/> <小时/> EDIT2:

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

3 个答案:

答案 0 :(得分:7)

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()方法)
  • 签入更改的文件
  • 最后,删除工作区

如果您只是尝试自动刷新一组文件,那么这是很多工作,所以您可以做的是传递Get()方法的路径:

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

答案 1 :(得分:2)

使用TFS命令行工具时,相同的命令/参数是否有效?例如TF.exe get

您是否安装了任何防病毒软件?是否有可能阻碍它?尝试暂时禁用它。

您还可以在app.config中启用TFS客户端跟踪,以查看网络上的内容: http://blogs.msdn.com/b/edhintz/archive/2007/03/30/tfs-client-tracing.aspx

答案 2 :(得分:0)

以下是使用该示例的工作示例,您可以从服务器路径

获取最新版本的代码
var status = workspace.Get(new GetRequest("$/XXXX/Development/Subfolder/",
            RecursionType.Full, VersionSpec.Latest),
            GetOptions.GetAll| GetOptions.Overwrite);