将 VB6 编译为 Server 2016 上的后台进程

Posted

技术标签:

【中文标题】将 VB6 编译为 Server 2016 上的后台进程【英文标题】:Compile VB6 as background process on Server 2016 【发布时间】:2019-05-06 01:09:17 【问题描述】:

我们遇到了一种非常奇怪的行为,我无法确定其根本原因。我们使用 TFS (2017.U2) 编译我们的遗留系统,并尝试将我们的构建农场从 2008R2 更新到 2016。构建系统使用 PowerShell (v5) 循环浏览 VBP 项目列表并运行 VBS 脚本以编译项目。

首先是一些基础知识。 UAC 完全禁用(在注册表中,不仅仅是滑块控件),VB6.EXE 也设置为 XP SP3 兼容性,并且也以管理员身份运行。

不幸的是,虽然我们可以看到 VB6.EXE 在任务管理器中启动 - 它只是挂起。零活动。以交互方式运行相同的编译对相同的用户来说效果很好。这使我推测这是一个环境问题,但是进程资源管理器向我显示了 VB6.EXE 进程上的有效用户环境。

我不认为这是由于 VB6 引发错误,因为(至少在以前版本的 Windows Server 中)当后台进程打开 UI 元素时,操作系统会向前台指示后台想要闯入. 我们没有看到。

我们已将其返回到我称之为“test.ps1”的最简代码示例:

$vb6="C:\Program Files (x86)\Microsoft Visual Studio\VB98\vb6.exe"
Set-Location D:\Builds\27\s\path\prjdir
start-process $vb6 -ArgumentList "/make /out errors.txt project.vbp"  -wait

我们一直在使用“start-process”来触发 VB6 编译,因为通过 PowerShell 直接调用无法正确获取参数(它们实际上是由在完整过程中传递到主脚本的字符串构建的。 ..这是简化版)。

以交互方式运行 (.\test.ps1) 时,此功能正常。项目编译后,我得到了一个 errors.txt 文件。

当作为进程启动时 (start-process .\test.ps1),它再次正常运行。

当通过 TFS“PowerShell 脚本”任务触发时,这无法完成 VB6 步骤 - 可以在任务查看器中看到带有适当参数的 VB6.EXE,并且没有 CPU 或 IO 与任务关联。没有写入errors.txt 文件。没有创建新的 DLL。

我可以通过在另一台机器上运行测试脚本来进一步降低 TFS 并从堆栈中删除 TFS。我运行了脚本的远程调用,并使用以下命令复制了结果:

PS C:\Users\svc_build> Invoke-Command –ComputerName TestBuild02 –ScriptBlock powershell  C:\Users\svc_build\desktop\test.ps1 

同样,没有errors.txt,也没有新的DLL。 VB6.EXE 启动,只是坐在那里。进程监视器不提供任何帮助来诊断可能是什么问题。

现在我闻到了安全门被关上的味道——即使同一个域用户正在运行同一个作业,不同之处在于这是一个后台进程......并且有些东西阻止了后台进程在与前台进程相同的上下文。

假设这个假设是正确的,有人可以指出远程触发(后台)会话无法运行 VB6.EXE 的原因吗? (当然,对于这种情况的解决方法将不胜感激:))

如果这不是一个安全问题 - 有人可以找出真正的罪魁祸首,以及让 VB6 作为后台进程运行的解决方案,就像我们习惯看到它在 W2K8R2 上运行一样?

【问题讨论】:

挂起的VB6进程是否消耗CPU? 不,它不消耗任何 CPU,也不执行任何 I/O。 Process Explorer 不能“带到前面”,这(我假设)意味着后台没有待处理的 UI 元素。事件日志中没有任何内容表明任何有用的信息。当 VB6.EXE 进程被杀死时,VSTSAgentService 会记录一个应用程序错误,我们假设这是被杀死的进程的副作用。 【参考方案1】:

我参加聚会有点晚了,但这听起来与我刚刚遇到的情况非常相似。

Windows 10 v2004 UAC 已禁用 通过 PowerShell 脚本运行 VB6.exe 进行编译。 使用 Bamboo 作为构建服务器,作为托管服务帐户运行。

当通过 Bamboo 在服务器上运行构建时,它会挂起。当登录到构建服务器并手动运行构建时,它成功了。

削减代码后,我能够重现一个最小的失败案例。挂起是由操作 UI 控件的 UserControl 的 UserControl_Initialize 方法中的代码引起的,但当该 UserControl 放置在同一项目中的窗体上时。

在编译过程中,编译器会创建一个 Form 的实例(为什么,我不知道),然后创建一个 UserControl 的实例,然后运行 ​​UserControl_Initialize 方法。我只能假设此时运行代码会导致某种错误,从而导致编译器挂起。

UserControl_Resize 事件也可能导致相同的错误。通过在尝试调整子控件大小之前检查 Ambient.UserMode 是否为真,这种情况相当容易解决。

Private Sub UserControl_Resize()
    If UserControl.Ambient.UserMode Then
        ' Position the child controls
    End If
End Sub

修复UserControl_Initialize 方法要求这些方法中的代码在不同的点运行(例如,当给UserControl 提供要显示的数据时,我们现在运行之前在UserControl_Initialize 中的代码)。

另外值得注意的是我们必须使用的 VB6.exe 的兼容性设置。使用“Windows XP SP3”兼容模式导致VB6.exe 立即挂起。我们必须将其设置为不使用任何兼容模式,但我们确实必须设置以管理员身份运行此程序,并让所有用户都使用它。

【讨论】:

以上是关于将 VB6 编译为 Server 2016 上的后台进程的主要内容,如果未能解决你的问题,请参考以下文章

如何将 .hex 文件反编译为 Arduino 的 C++?

python编译文件(pyc)即使编译为字节码也需要系统上的导入库吗?

Visual Studio 2015 没有将 TypeScript 编译为 ASP.NET Core 项目的一部分?

为啥 gcc 将 _mm256_permute2f128_ps 编译为 Vinsertf128 指令?

“编译为”设置为“默认”时的外部符号链接错误[重复]

cx_Freeze 将 Python 和 Pygame 文档编译为 .exe 文件时出现奇怪的错误