我希望从一个不同的用户下运行一个Windows批处理脚本来运行go程序。 运行go的用户拥有比应该运行批处理脚本的用户更多的权限。
从开始有几个选项可用于在Windows上的不同用户下执行进程,例如直接使用syscall包在窗口中编写Windows调用。 我还没有尝试过,但我已经尝试使用PsExec和Powershell。 Powershell是首选,因为它在Windows 2008 R2上作为标准安装。
下面的代码演示了我有的问题。 在下面的演示中,我运行了一个批处理脚本。 这个批处理脚本直接调用Powershell脚本,然后从go程序调用它。 结果是不同的。 Powershell脚本输出3个文件,但是从go中调用时只输出2个文件。
为了完整起见,我还展示了用户是如何创build的。
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
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
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") }
C:\计算器\ whoami.bat:
whoami > C:\Users\Tom\whoami.txt
现在,结果 – 在批处理脚本中调用时,会看到文件starts.txt,whoami.txt,finished.txt全部被创build。 从go中调用时,只会创buildstarted.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>
修复。
用户Tom默认情况下不能访问C:\Stackoverflow
文件夹,为了运行任何东西,我必须让每个人都可以访问该文件夹中的Read / Execute项,否则启动进程失败
将net profile添加到net user命令。 这阻止了我在评论中提到的额外的文件夹:
net user Tom _Jerry123_ /add /expires:never /passwordchg:no /homedir:C:\Users\Tom /profilepath:C:\Users\Tom /y
将Start-Process
行替换为:
Start-Process C:\stackoverflow\whoami.bat -WorkingDirectory C:\Users\Tom -Credential ($credentials) -Wait
为什么?
将工作目录设置为C:\ StackOverflow,执行批处理文件的命令解释程序将在内建之前查找whoami.bat
,并发生各种破坏。 一旦我把工作目录移动到汤姆的文件夹,一切都按照你想要的方式工作。
替代方案:
不要将你的批处理文件命名为内建命令。