0

我怎样才能通过执行我的sc命令exec.Command

代码:

cmd := exec.Command("cmd.exe", "sc", "create", "Simpler", "binpath="+os.Getenv("APPDATA")+"\\Simpler\\cc.exe", "displayname=MY SERVICE");
cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true};
out, _ := cmd.Output(); fmt.Println(string(out))

这是我在命令提示符下得到的(在当前命令提示符中打开命令提示符-_-):

Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

C:\WINDOWS\system32>cd c:\prog\logs

c:\prog\logs>go build test.go

c:\prog\logs>test.exe
Microsoft Windows [Version 6.3.9600]
(c) 2013 Microsoft Corporation. All rights reserved.

c:\prog\logs>

c:\prog\logs>

后面的命令无法执行。我什么也得不到!问题出在哪里?

如果我在当前命令提示符下执行命令已启动sc.exe,但如果我在新命令提示符下执行则未启动。

也就是说,如果我删除第一个参数"cmd.exe",我的程序会以异常结果成功执行。但是如何在新窗口中执行呢?

4

2 回答 2

2

好吧,最直接的问题是,你所做的并不是cmd.exe告诉你应该如何执行一个外部命令——为了让它执行一个,你应该传递cmd.exeor/C命令/K行选项,比如

C:\>cmd.exe /C sc whatever sc_arg1 sc_arg2 ...

您在调用中观察到的是,它cmd.exe忽略了您传递给它的其余参数并只是运行——这正是您所观察到的。

从研究 Windows 帮助系统的输出cmd.exe /?和内置帮助系统开始,以更好地了解它的工作原理。

下一个问题是,绝对没有理由cmd.exe参与sc运行——sc直接运行而不是跳来跳去cmd.exe让它执行sc

下一个问题是您忽略了调用返回的错误值os/exec.Cmd.Output。由于 Go(幸运的是)没有异常,处理所有错误值至关重要——最好忽略其他所有内容,但不要忽略错误。如果你正在编写高度实验性的代码,你可能会 一个愚蠢的助手开始,比如

func check(err error) {
    if err != nil {
        panic(err)
    }
}

然后像滚动

out, err := cmd.Output()
check(err)

这种方法不适用于生产级代码,但在试验时允许更快的代码搅动。

您也可以考虑直接调用 Win32 API 来管理服务,因为这将使错误处理变得更加容易。

于 2018-06-17T11:13:45.690 回答
2

有点晚了,并不是真的关于运行 sc.exe。虽然@kostix 提供的答案中解决了使用 SC.exe 的问题,但我看到您正在尝试创建 Go 应用程序的服务并认为这是一个 XY 问题。

单个调用不太可能sc.exe成功创建 Windows 服务。但是,有一个库可以提供帮助:golang.org/x/sys/windows/svc.

github上还有一个例子:https ://github.com/golang/sys/tree/master/windows/svc/example

于 2018-06-18T16:06:21.157 回答