Windows 通过Powershell或批处理序列化symstore的执行

Windows 通过Powershell或批处理序列化symstore的执行,windows,powershell,batch-file,debug-symbols,Windows,Powershell,Batch File,Debug Symbols,我们正在努力将一个步骤集成到我们的持续集成(CI)服务器(CruiseControl.NET)中。我们希望将生成过程中生成的调试符号*.pdb注册到Microsoft Symbol服务器中。由Microsoft实现的符号服务器是Visual Studio用于查找C++/C#可执行文件的*.pdb调试符号的目录结构。Microsoft提供了一个命令symstore,该命令在一个目录中获取调试符号,并根据需要填充中央符号存储目录 问题是symstore明确表示并发运行不安全 我们可以尝试哪些方法或策

我们正在努力将一个步骤集成到我们的持续集成(CI)服务器(CruiseControl.NET)中。我们希望将生成过程中生成的调试符号
*.pdb
注册到Microsoft Symbol服务器中。由Microsoft实现的符号服务器是Visual Studio用于查找C++/C#可执行文件的
*.pdb
调试符号的目录结构。Microsoft提供了一个命令
symstore
,该命令在一个目录中获取调试符号,并根据需要填充中央符号存储目录

问题是
symstore
明确表示并发运行不安全

我们可以尝试哪些方法或策略来禁止通过批处理或Powershell脚本并发执行
symstore
命令

我们在方法上是灵活的,但因为我们在Windows平台上运行,批处理和Powershell是首选解决方案

澄清:

对于我们的用例,
symstore
需要从两个不同的CI服务器上运行,这将把符号保存在一个公共网络驱动器上

资源:

符号库::
使用共享目录中的文件作为信号量,以避免并发执行

:checkfile
if exist %cidir%\sem.txt goto :wait10secs
echo gotit! >%cidir%\sem.txt
doit
del %cidir%\sem.txt
goto :eof
:wait10secs
ing 192.0.2.2 -n 1 -w 10000 > nul
goto :checkfile

准备好调试批处理失败的所有奇怪方式和所有恶劣的赛车条件。

为了锁定对网络驱动器的访问,您需要一个与您的CI服务对话的第三方。然后,该第三方将处理对网络驱动器的访问。该第三方可以是:

  • MSMQ
  • 数据库表中的行
  • 运行
    symstore
    的symbol服务器上的WCF服务以及您的CCNet构建与之对话以触发
    symstore
  • 符号服务器上具有可远程触发的项目/作业的CCNet
  • 可从CI服务器远程触发的符号服务器上的计划作业

您可以使用锁定的文件作为简单的信号量来序列化事件。当您将stdout重定向到批处理文件中的文件时,它会在该文件上建立独占写锁。没有其他进程可以打开相同的文件进行写访问。当进程结束时,锁将自动释放,无论它如何结束(清除退出、CTRL-C、异常失败等)

批处理文件可以尝试将9重定向到锁定文件,如果失败,则返回,直到成功。symstore命令仅在锁定到位时运行。使用非标准文件句柄(stream?),以便锁不会干扰stdin、stdout或stderr处理

因此,您只需确保从不直接致电symstore。相反,您总是通过批处理脚本调用它。类似于以下内容(serializeSymstore.bat):

没有注释,它就变成了一点点代码

@echo off
setlocal

:loop
8>&2 2>nul (
  9>"\\centralServer\somePath\symstore.lock" 2>&8 (
    symstore %*
    call set "rtnCd=%%errorlevel%%"
    (call )
  )
) || (
  timeout 1 /nobreak >nul
  goto loop
)
exit /b %rtnCd%
我发现这种原始而简单的策略在许多项目中都非常有效。我必须承认,我没有在远程机器上测试锁和释放特性。但我相信只要所有的机器都是Windows,它就应该是可靠的

我知道的唯一缺点是没有FIFO队列。若接收到多个重叠的请求,那个么下一个进程将进入哪个进程,这是随机的运气。但这些过程将被序列化


编辑:
编辑之前,我已经阅读了飞溅位的原始答案。他质疑远程机器上的文件锁定是否可靠。我做了一些快速的谷歌搜索,在UNC路径上的文件锁定似乎确实存在一些问题。如果遇到问题,您可能会更幸运地重定向到映射驱动器号上的文件,而不是直接通过UNC路径。这都是理论——我没有做任何测试。在提交此解决方案之前,请确保进行充分的测试。请注意,PUSHD是一种方便的方法,可以在不知道哪些驱动器号可用的情况下将驱动器号临时分配给UNC路径。POPD将取消映射驱动器分配。

如果两个进程在不同的主机上运行,则无法解决问题。@PA最初的问题没有提到任何关于跨机器要求的内容。你是对的,它没有提到,我只是根据以前的类似情况假设它(顺便说一句,我没有否决你的答案)@这看起来是一个很好的解决方案!在得到最初的答案(以及您的澄清请求)后,我意识到我需要澄清我的需求,因为它实质上改变了解决方案。但是,如果我的要求是在一台计算机上阻止并发,我认为这是正确的。@EricWebb我已经更新了我的答案,因为使用互斥不能跨计算机工作。对我来说,这看起来像一个竞争条件。检查sem.txt是否存在并创建(锁定)它需要是原子的,这样才能工作,否则创建
sem.txt
失败,如果它已经存在。是的,我将此详细实现留给OP或第二个SO问题。该详细信息是所述问题的基础!也就是说,关于跨机器并发的观点是一个很好的观点。你是对的,但是我们没有足够的信息来说明如何避免并发。可能是symstore拒绝或忽略了第二次尝试。或者可能是更严重的情况。如果OP需要帮助,则由OP评估并返回给我们。通过依赖文件上的锁而不是文件的存在来避免竞争条件。请参阅是否需要在同一台计算机上跨不同进程运行
symstore
?或者您是否需要在不同的计算机上运行
symstore
,在中央计算机上管理符号存储?使用TFS及其生成过程模板,可以同步对符号存储的访问。请参阅此处的“SharedResourceScope活动”:这正是我希望能够实现的范例……一个批处理/powershell包装器,提供了相互exc
@echo off
setlocal

:loop
8>&2 2>nul (
  9>"\\centralServer\somePath\symstore.lock" 2>&8 (
    symstore %*
    call set "rtnCd=%%errorlevel%%"
    (call )
  )
) || (
  timeout 1 /nobreak >nul
  goto loop
)
exit /b %rtnCd%