为什么Powershell Start-Process在从go(golang)调用时不起作用?

Pet*_*ore 7 windows powershell batch-file go

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

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

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

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

C:\计算器\ 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
Run Code Online (Sandbox Code Playgroud)

C:\计算器\ 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
Run Code Online (Sandbox Code Playgroud)

C:\计算器\ 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")
}
Run Code Online (Sandbox Code Playgroud)

C:\计算器\ whoami.bat:

whoami > C:\Users\Tom\whoami.txt
Run Code Online (Sandbox Code Playgroud)

现在,结果 - 在这里你看到从批处理脚本调用时,文件的start.txt,whoami.txt,finished.txt都被创建了.从go调用时,只创建了starts.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>
Run Code Online (Sandbox Code Playgroud)

Eri*_*ris 1

修复。

  1. 默认情况下,用户 Tom 无法访问该C:\Stackoverflow文件夹,为了运行任何内容,我必须授予每个人对该文件夹中的读取/执行项目的访问权限,否则启动过程会严重失败

  2. 将 profilepath 添加到 net user 命令中。这可以防止创建我在评论中提到的额外文件夹:

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

  3. 将该行替换Start-Process为:

    Start-Process C:\stackoverflow\whoami.bat -WorkingDirectory C:\Users\Tom -Credential ($credentials) -Wait

为什么?

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

选择:

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