Windows 为什么从go(golang)调用Powershell时启动进程不工作?

Windows 为什么从go(golang)调用Powershell时启动进程不工作?,windows,powershell,batch-file,go,Windows,Powershell,Batch File,Go,我希望在运行go程序的用户的不同用户下,从go运行Windows批处理脚本。运行go的用户比应该运行批处理脚本的用户拥有更多权限 从go,有几个选项可用于在Windows上的不同用户下执行进程,例如使用go中的syscall包直接编写Windows调用。我还没有尝试过,但我已经尝试过使用PsExec和Powershell。Powershell是首选,因为它作为Windows 2008 R2上的标准配置安装 下面的代码演示了我遇到的问题。在下面的演示中,我运行了一个批处理脚本。此批处理脚本直接调用

我希望在运行go程序的用户的不同用户下,从go运行Windows批处理脚本。运行go的用户比应该运行批处理脚本的用户拥有更多权限

从go,有几个选项可用于在Windows上的不同用户下执行进程,例如使用go中的syscall包直接编写Windows调用。我还没有尝试过,但我已经尝试过使用PsExec和Powershell。Powershell是首选,因为它作为Windows 2008 R2上的标准配置安装

下面的代码演示了我遇到的问题。在下面的演示中,我运行了一个批处理脚本。此批处理脚本直接调用Powershell脚本,然后从go程序调用它。结果是不同的。Powershell脚本输出3个文件,但从go调用时,仅输出2个文件

为了完整起见,我还展示了用户是如何创建的

C:\stackoverflow\demo.bat:

::::: create a new user for the demo :::::

:: first create a home directory
mkdir C:\Users\Tom
:: remove Users group
icacls C:\Users\Tom /remove:g Users
:: remove Everyone
icacls C:\Users\Tom /remove:g Everyone
:: create user Tom and set his home directory
net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /y
:: Give Tom access to his home directory
icacls C:\Users\Tom /grant:r Tom:(CI)F SYSTEM:(CI)F Administrators:(CI)F
:: give him access to Remote Desktop
net localgroup "Remote Desktop Users" /add Tom

::::: now call powershell directly :::::

powershell -command C:\stackoverflow\demo.ps1
:: show which files were created
dir C:\Users\Tom
:: cleanup
del /f /q C:\Users\Tom\*

::::: run the go version to do the same thing :::::

go run C:\stackoverflow\demo.go
:: compare results
dir C:\Users\Tom
:: cleanup
del /f /s /q C:\Users\Tom
rmdir /s /q C:\Users\Tom
:: delete user
net user Tom /delete
C:\stackoverflow\demo.ps1

write-output "test output" | out-file C:\Users\Tom\started.txt
$credentials = New-Object System.Management.Automation.PSCredential -ArgumentList @("Tom",(ConvertTo-SecureString -String "_Jerry123_" -AsPlainText -Force))
Start-Process C:\stackoverflow\whoami.bat -WorkingDirectory C:\stackoverflow -Credential ($credentials) -Wait
write-output "test output" | out-file C:\Users\Tom\finished.txt
C:\stackoverflow\demo.go

package main

import (
    "fmt"
    "os"
    "os/exec"
)

func main() {
    run(exec.Command("PowerShell", "-Command", "C:\\stackoverflow\\demo.ps1"))
}

func run(cmd *exec.Cmd) {
    cmd.Stdout = os.Stdout
    cmd.Stderr = os.Stderr
    cmd.Stdin = os.Stdin
    err := cmd.Start()
    if err != nil {
        panic(err)
    }
    err = cmd.Wait()
    if err != nil {
        panic(err)
    }
    fmt.Println("Done")
}
C:\stackoverflow\whoami.bat:

whoami > C:\Users\Tom\whoami.txt
现在,结果——在这里,当从批处理脚本调用时,文件started.txt、whoami.txt、finished.txt都被创建。从go调用时,只创建started.txt和finished.txt。为什么呢

输出:

C:\stackoverflow>demo.bat

C:\stackoverflow>mkdir C:\Users\Tom

C:\stackoverflow>icacls C:\Users\Tom /remove:g Users
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files

C:\stackoverflow>icacls C:\Users\Tom /remove:g Everyone
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files

C:\stackoverflow>net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /y
The command completed successfully.


C:\stackoverflow>icacls C:\Users\Tom /grant:r Tom:(CI)F SYSTEM:(CI)F Administrators:(CI)F
processed file: C:\Users\Tom
Successfully processed 1 files; Failed processing 0 files

C:\stackoverflow>net localgroup "Remote Desktop Users" /add Tom
The command completed successfully.


C:\stackoverflow>powershell -command C:\stackoverflow\demo.ps1

C:\stackoverflow>dir C:\Users\Tom
 Volume in drive C is OSDisk
 Volume Serial Number is CCD6-C9E7

 Directory of C:\Users\Tom

06/18/2015  06:36 AM    <DIR>          .
06/18/2015  06:36 AM    <DIR>          ..
06/18/2015  06:36 AM                28 finished.txt
06/18/2015  06:36 AM                28 started.txt
06/18/2015  06:36 AM                55 whoami.txt
               3 File(s)            111 bytes
               2 Dir(s)  16,489,889,792 bytes free

C:\stackoverflow>del /f /q C:\Users\Tom\*

C:\stackoverflow>go run C:\stackoverflow\demo.go
Done

C:\stackoverflow>dir C:\Users\Tom
 Volume in drive C is OSDisk
 Volume Serial Number is CCD6-C9E7

 Directory of C:\Users\Tom

06/18/2015  06:36 AM    <DIR>          .
06/18/2015  06:36 AM    <DIR>          ..
06/18/2015  06:36 AM                28 finished.txt
06/18/2015  06:36 AM                28 started.txt
               2 File(s)             56 bytes
               2 Dir(s)  16,489,889,792 bytes free

C:\stackoverflow>del /f /s /q C:\Users\Tom
Deleted file - C:\Users\Tom\finished.txt
Deleted file - C:\Users\Tom\started.txt

C:\stackoverflow>rmdir /s /q C:\Users\Tom

C:\stackoverflow>net user Tom /delete
The command completed successfully.


C:\stackoverflow>
C:\stackoverflow>demo.bat
C:\stackoverflow>mkdir C:\Users\Tom
C:\stackoverflow>icacls C:\Users\Tom/remove:g Users
已处理文件:C:\Users\Tom
成功处理1个文件;处理0个文件失败
C:\stackoverflow>icacls C:\Users\Tom/remove:g Everyone
已处理文件:C:\Users\Tom
成功处理1个文件;处理0个文件失败
C:\stackoverflow>net用户Tom\u Jerry123\u/add/expires:never/passwordchg:no/homedir:C:\Users\Tom/y
命令已成功完成。
C:\stackoverflow>icacls C:\Users\Tom/grant:r Tom:(CI)F SYSTEM:(CI)F Administrators:(CI)F
已处理文件:C:\Users\Tom
成功处理1个文件;处理0个文件失败
C:\stackoverflow>net localgroup“远程桌面用户”/“添加Tom”
命令已成功完成。
C:\stackoverflow>powershell-命令C:\stackoverflow\demo.ps1
C:\stackoverflow>目录C:\Users\Tom
驱动器C中的卷是OSDisk
卷序列号为CCD6-C9E7
C:\Users\Tom目录
2015年6月18日上午6:36。
2015年6月18日06:36。。
2015年6月18日06:36 AM 28 finished.txt
2015年6月18日06:36 AM 28 started.txt
2015年6月18日06:36 AM 55 whoami.txt
3个文件111字节
2个目录16489889792个可用字节
C:\stackoverflow>del/f/q C:\Users\Tom\*
C:\stackoverflow>go运行C:\stackoverflow\demo.go
多恩
C:\stackoverflow>目录C:\Users\Tom
驱动器C中的卷是OSDisk
卷序列号为CCD6-C9E7
C:\Users\Tom目录
2015年6月18日上午6:36。
2015年6月18日06:36。。
2015年6月18日06:36 AM 28 finished.txt
2015年6月18日06:36 AM 28 started.txt
2个文件56字节
2个目录16489889792个可用字节
C:\stackoverflow>del/f/s/q C:\Users\Tom
已删除文件-C:\Users\Tom\finished.txt
已删除文件-C:\Users\Tom\started.txt
C:\stackoverflow>rmdir/s/q C:\Users\Tom
C:\stackoverflow>net用户Tom/delete
命令已成功完成。
C:\stackoverflow>
修复了它

  • 默认情况下,用户Tom无法访问
    C:\Stackoverflow
    文件夹,为了运行任何东西,我必须让每个人都可以访问该文件夹中的读取/执行项目,否则启动过程将失败

  • 将profilepath添加到net用户命令。这阻止了创建我在评论中提到的额外文件夹:

    net user Tom\u Jerry123\u/add/expires:never/passwordchg:no/homedir:C:\Users\Tom/profilepath:C:\Users\Tom/y

  • 启动流程
    行替换为:

    启动进程C:\stackoverflow\whoami.bat-工作目录C:\Users\Tom-凭证($credentials)-等待

  • 为什么?

    当工作目录设置为C:\StackOverflow时,执行批处理文件的命令解释器会在内置文件之前找到
    whoami.bat
    ,并且会发生各种各样的中断。一旦我将工作目录移到Tom的文件夹中,一切都完全按照您的要求进行

    备选方案:


    不要将批处理文件命名为与内置命令相同的名称。

    我发现两个
    dir
    命令之间的“无字节”计数器没有更改,而应该更改,因为在运行Powershell后文件夹中有三个文件,在运行Go后有两个文件。因此,创建了该文件,尽管该文件不可见(请检查
    attrib-r-h-s c:\users\tom\whoami.txt
    ),或者位于其他位置。运行go命令后,请搜索名称包含
    whoami
    的文件,可能是文件权限或文件夹重定向问题。谢谢Vesper,这是个好主意。不幸的是,这不是原因;
    attrib
    命令返回了
    File not found
    ,并且该文件没有在搜索中出现。然后我做了一个快速测试并创建了一些小文件,在运行
    dir
    时,可用的
    字节数也没有改变,所以我认为这可能是一个误导。我猜
    空闲字节数
    并不总是立即更新。是不是
    go
    的作用域让PowerShell忘记了这一点。bat脚本与
    cmd/c
    相关联,而批处理脚本中调用的PowerShell保持了这种关联?如果
    启动进程cmd.exe”/c:\stackoverflow\whoami.bat“-otherargs
    ,会有什么区别吗?如果没有,在demo.ps1的顶部插入
    set executionpolicy remotesigned
    有什么区别吗?非常感谢rojo,我尝试了这两个建议,但不幸的是都没有解决,我仍然得到了相同的结果