为了账号安全,请及时绑定邮箱和手机立即绑定

如何从 Windows 服务运行另一个可执行文件

如何从 Windows 服务运行另一个可执行文件

Go
犯罪嫌疑人X 2023-07-10 18:00:29
除了一些关于 Go 的教程之外,我没有任何实际经验。我正在尝试将一个用 Go 编写的项目并将其转换为 Windows 服务。老实说,除了试图找到可以阅读的内容之外,我还没有尝试过任何其他事情。我找到了一些线程并选择了我认为可以满足我们所有需求的最佳库https://github.com/golang/sys所以我花了一些时间仔细研究这段代码。对其进行测试,看看它有什么作用。它按其应有的方式执行。我的问题是,我们目前有一个 Go 程序,它接受参数,并且对于我们的服务,我们在服务器中传递。这会在本地主机网页上启动我们的东西。我相信上面的代码可能与此有关,但我不知道如何用正确的论点将它从我们的 exe 中分离出来。这是调用 main 的正确位置吗?如果这含糊不清,我很抱歉。我不知道如何让它与我们已经存在的 exe 交互。如果我知道需要更改什么,我可以对其进行修改。我感谢任何帮助。
查看完整描述

1 回答

?
呼啦一阵风

TA贡献1802条经验 获得超6个赞

好的,现在清楚多了。好吧,理想情况下,您应该从一些有关 Windows 服务的构成的教程开始 - 我打赌这可能已经为您解决了问题。但无论如何我们还是要尝试一下。

一些理论

Windows 服务有两个方面:它执行一些有用的任务并与SCM 设施进行通信。当您使用命令或通过控制面板操作服务时sc,您可以使用该软件代表您与 SCM 进行对话,而 SCM 则与该服务进行对话。

SCM 和服务使用的确切协议是低级且复杂的,您使用的 Go 包的目的是向您隐藏这种复杂性,并为这些东西提供一个合理的以 Go 为中心的接口。

正如您可能从自己的示例中了解到的那样,Execute您创建的类型的方法在很大程度上与与 SCM 的通信有关:它运行一个无限for循环,在每次迭代时都会休眠从r通道读取数据,并且该通道将 SCM 命令传送到您的服务。

所以你基本上拥有了所谓的“SCM 命令处理循环”。

现在回想一下上面的两个方面。您已经拥有其中之一:您的服务与 SCM 交互,因此您需要另一个 — 实际执行有用任务的代码。

事实上,它已经部分存在:您获取的示例代码创建了一个时间行情指示器,它提供了一个通道,当另一个时间行情通过时,它在该通道上传递值。for该方法中的循环也Execute从该通道读取数据,每次发出另一个刻度信号时都会“工作”。

好吧,这对于一个玩具示例来说很好,但对于真正的作品来说却很糟糕。

接近解决方案

因此,让我们暂停一下并考虑一下我们的需求。

  1. 我们需要一些代码来运行并执行我们的实际任务。

  2. 我们需要现有的命令处理循环才能继续工作。

  3. 我们需要这两段代码同时工作。

在这个玩具示例中,第三点是“免费”的,因为时间计时器自动执行等待下一个计时的任务,并且与其余代码完全并发。

你真正的代码很可能不会有那么奢侈,那么你该怎么办?

在 Go 中,当你需要同时做某件事和其他事情时,一个明显的答案是“使用 goroutine”。

因此,第一步是获取现有代码,将其转换为可调用函数,然后在进入循环之前在单独的 goroutine 中调用它for。这样,您将同时运行两个部分。

困难的部分

好吧,那并不难。

困难的部分是:

  • 如何配置执行任务的代码。

  • 如何使单片机命令处理循环和执行任务的代码进行通信。

配置

这实际上取决于您的 $dayjob 或 $current_project 的政策,但有一些提示:

  • Windows 服务可以接收命令行参数——无论是单次运行还是永久(在每次运行时传递给服务)。

    缺点是从 UI/UX 的角度来看使用它们并不方便。

  • 通常 Windows 服务用于读取注册表。

  • 如今(在 .NET 及其普遍的 xml-ity 出现之后)服务倾向于读取配置文件。

  • 大多数时候,操作系统环境并不适合该任务。

  • 您可以合并其中几个场地。

我想我会从配置文件开始,但话又说回来,我认为你应该选择阻力最小的路径。

需要记住的一件事是,配置的读取和处理最好在服务向 SCM 发出它已启动的信号之前完成:如果配置无效或无法加载,服务应广泛记录该情况并发出信号失败,并且运行实际的任务处理代码。

命令处理循环和携带代码的任务之间的通信

在我看来,这是最难的部分。

在这里写一整本书是可能的,但现在让我们保持简单。

为了使其尽可能简单,我会执行以下操作:

  • 考虑暂停、停止和关闭几乎相同:所有这些信号都必须告诉您的任务处理代码退出,然后等待它实际执行此操作。

  • 将“继续”信号视为与启动任务处理函数相同:在新的 goroutine 中再次运行它。

  • 进行单向通信:从控制循环到任务处理代码,而不是其他方式 - 这将大大简化服务状态管理。

这样,您可以创建一个任务处理代码侦听或定期检查的通道,当一个值来自该通道时,代码停止运行,关闭通道并退出

当 SCM 告诉控制循环暂停、停止或关闭时,控制循环会在该通道上发送任何内容,然后等待其关闭。当发生这种情况时,它知道任务处理代码已完成。

在 Go 中,仅用于信令的通道的范例是具有类型struct{}(空struct)的通道。

如何在运行代码的任务中监视此控制通道的问题是一个开放的问题,并且在很大程度上取决于它执行的任务的性质。

这里的任何进一步帮助都可以背诵 Go 书籍中有关并发的内容,因此您应该首先了解这一点。


还有一个有趣的问题是如何使控制循环和任务处理循环之间的通信能够适应后者可能出现的处理停顿,但话又说回来,在我看来,现在讨论这个问题还为时过早。


查看完整回答
反对 回复 2023-07-10
  • 1 回答
  • 0 关注
  • 135 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信