Chcę uruchomić skrypt wsadowy Windows od go, pod innym użytkownikiem, do użytkownika uruchomionego programu go. Użytkownik uruchamiający go ma więcej uprawnień niż użytkownik, który powinien uruchomić skrypt wsadowy.Dlaczego Powershell Start-Process nie działa po wywołaniu z go (golang)?
Od tej pory istnieje kilka opcji wykonania procesu pod innym użytkownikiem w systemie Windows, na przykład podczas pisania wywołań okien bezpośrednio przy użyciu pakietu syscall w programie. Nie próbowałem jeszcze tego, ale próbowałem zarówno przy użyciu PsExec, jak i Powershell. Powershell jest preferowany, ponieważ jest instalowany jako standard w systemie Windows 2008 R2.
Poniższy kod ilustruje problem, który mam. W poniższym demo uruchamiam skrypt wsadowy. Ten skrypt wsadowy wywołuje bezpośrednio skrypt Powershell, a następnie wywołuje go z programu go. Wyniki są różne. Skrypt Powershell wyprowadza 3 pliki, ale po wywołaniu z wyjścia, wyprowadza tylko 2 pliki.
W celu uzupełnienia, pokazuję również, w jaki sposób został utworzony użytkownik.
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
A teraz wyniki - tutaj widzimy, gdy wywoływane ze skryptu wsadowego, pliki start.txt, whoami.txt, finished.txt wszystkie zostaną utworzone. Po wywołaniu z pliku tworzone są tylko pliki begin.txt i finished.txt. Dlaczego?
wyjściowa:
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>
Widzę, że licznik "wolnych bajtów" nie jest zmieniany między dwoma komendami 'dir', podczas gdy powinien, ponieważ w programie były trzy pliki po uruchomieniu Powershell, a dwa po uruchomieniu Go. Dlatego plik został utworzony, chociaż nie jest widoczny (sprawdź "attrib -r -h -s c: \ users \ tom \ whoami.txt") lub znajduje się w innym miejscu. Proszę poszukać pliku (ów) o nazwie zawierającej 'whoami' po uruchomieniu polecenia go, prawdopodobnie istnieje problem z uprawnieniami do pliku lub przekierowaniem folderu. – Vesper
Dzięki Vesper, to był dobry pomysł. Niestety nie jest to powód; komenda 'attrib' zwróciła' File not found', a plik nie pojawił się podczas wyszukiwania. Następnie zrobiłem szybki test i utworzyłem kilka małych plików, a "bajtów za darmo" również się nie zmieniło podczas uruchamiania 'dir' - więc myślę, że może to być czerwony śledzia. Domyślam się, że 'bytes free' nie zawsze jest od razu aktualizowane. –
Czy możliwe jest, że zakres 'go' sprawia, że PowerShell zapomina, że skrypty .bat są powiązane z' cmd/c', podczas gdy PowerShell wywoływany wewnątrz skryptu wsadowego utrzymuje skojarzenie? Czy robi to różnicę, jeśli uruchomisz "Start-Process cmd.exe"/c c: \ stackoverflow \ whoami.bat "-otherargs'? Jeśli nie, czy robi to różnicę, wstawiając 'set-executionpolicy remotesigned' na początku pliku demo.ps1? – rojo