golang 隐藏启动其他程序,包含cmd窗口(黑窗口)程序,GUI程序隐藏

最近工作中需要做一个开机自动启动其他应用的程序。并且要求可以设置是静默启动还是正常启动。这本来是一个比较常见的需求,如果用c++这种底层语言编写,只需要设置窗口属性为SW_HIDE就搞定了。但是公司要求用GO语言实现。虽然golang语言有提供windows系统包,但实际使用起来好像并不是那么好用(可能是自己没有使用好吧)。
网上有人说,隐藏调用的外部程序的cmd窗口,设置cmd属性,可以实现,代码如下:

cmd := exec.Command("cmd")
if runtime.GOOS == "windows" {
    cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}
}

经过多次尝试,没有达到项目需求,我需要寻找新的方法。
后来,我发现在上面exec.Command 参数里面添加start参数,可以显示启动程序,不添加start参数,就是静默启动(母程序本身静默启动)。代码如下:

func StartOtherApp(targetapp string, arg []string, bsilence bool) {

	var temArg []string
	temArg = append(temArg, "/c")
	// 非静默启动,添加start参数
	if !bsilence {
		temArg = append(temArg, "start")
	}
	temArg = append(temArg, targetapp)
	temArg = append(temArg, arg...)
	cmd := exec.Command("cmd", temArg...)
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: bsilence}

	err := cmd.Run()
	if nil != err {
		fmt.Println(err)
		lwlog.Logs.Error(fmt.Sprintf("start exe error:%v", err))
		return
	}
	lwlog.Logs.Info(fmt.Sprintf("start exe:%s", targetapp))
	fmt.Println("start exe:", targetapp)
}

这样,算是勉强达到需求吧!因为以上代码对带GUI程序是不生效的------不能隐藏GUI程序。虽然,项目上面没有隐藏GUI程序的需求,但是自己总感觉,不完美。
所以,我继续寻找可以隐藏GUI程序的方法。
经过查资料,发现powershell功能十分强大,可以隐藏启动外部程序。这让我十分高兴。
方案是这样的:
第一步,把powershell程序拉起来
第二步,给powershell传入执行参数。powershell支持Command参数,这个参数是“执行指定的命令,就好像他们是在windows powershell 命令提示符下键入的一样”,所以只需要把powershell 中隐藏程序的命令当参数传入即可。
好了,说完了解题思路,还是老规矩----贴上代码.

// 启动其他程序
// 参数1:targetapp,待启动程序路径+名称
// 参数2:arg,待启动程序传入参数
// 参数3:bsilence ,静默启动标识
func StartOtherApp(targetapp string, arg string, bsilence bool) {

	var temArg []string

	// 隐藏powershell窗口
	temArg = append(temArg, "-WindowStyle")
	temArg = append(temArg, "Hidden")
	
    // 启动目标程序
	temArg = append(temArg, "-Command")
	temArg = append(temArg, "Start-Process")
	temArg = append(temArg, targetapp)
    // 目标程序参数
	if len(arg) > 0 {
		temArg = append(temArg, "-ArgumentList")
		temArg = append(temArg, arg)
	}

	// 静默启动参数
	if bsilence {
		temArg = append(temArg, "-WindowStyle")
		temArg = append(temArg, "Hidden")

	}
	cmd := exec.Command("PowerShell.exe", temArg...)

    // 启动时隐藏powershell窗口,没有这句会闪一下powershell窗口
	cmd.SysProcAttr = &syscall.SysProcAttr{HideWindow: true}

	err := cmd.Run()
	if nil != err {
		fmt.Println(err)
		lwlog.Logs.Error(fmt.Sprintf("start exe error:%v", err))
		return
	}
	lwlog.Logs.Info(fmt.Sprintf("start exe:%s", targetapp))
	fmt.Println("start exe:", targetapp)
}

通过本次优化,可以达到隐藏大部分GUI程序了。有很少一部分程序,任然无法被隐藏。通过powershell都无法隐藏程序启动,它既然这么顽强,我们就放过它吧!
如果有朋友恰好需要这个功能,欢迎直接拷贝。

你可能感兴趣的:(源码分享,问题记录)