Reputation: 348
package main
import "os"
func main() {
err := os.Remove(os.Args[1])
if err != nil {
panic(err)
}
}
Compile this
GOOS=windows GOARCH=386 go build test.go
Then run on wine
Z:\tmp>test.exe test.exe
fixme:process:SetProcessPriorityBoost (0xffffffff,1): stub
panic: remove test.exe: Access denied.
goroutine 1 [running]:
panic(0x462c40, 0x5b3f9ca0)
/usr/local/go/src/runtime/panic.go:500 +0x331
main.main()
/tmp/test.go:8 +0x70
Z:\tmp>fixme:console:CONSOLE_DefaultHandler Terminating process 8 on event 0
I think "ok, it's wine" and run in Win XP on VirtualBox. But that's error in Windows return.
//Sorry for my english.
Upvotes: 1
Views: 2980
Reputation: 8078
For windows you can use system API: shell32.dll.ShellExecuteW. It's running at another process, so even if your main program has terminated, it will continue to run. Therefore, you only need to call it to delete the program before the program exits. To ensure that the delete command is called after the program has terminated, you can wait for a period of time before deleting it (using start-sleep).
Start-Sleep 2; del "C:\xxx.exe"
package main
import (
"fmt"
"log"
"os"
"syscall"
"unicode/utf16"
"unsafe"
)
func main() {
defer func() { // delete exe
shell32dll := syscall.NewLazyDLL("Shell32.dll")
shellExecuteWProc := shell32dll.NewProc("ShellExecuteW")
const deleteExeAfterNSec = 2
const swHide = 0
const swShow = 1
log.Println(os.Args[0]) // os.Args[0] is the path of the executable file itself
_, _, _ = syscall.SyscallN(shellExecuteWProc.Addr(),
uintptr(0), // hwnd
uintptr(unsafe.Pointer(&(utf16.Encode([]rune("runas" + "\x00")))[0])),
uintptr(unsafe.Pointer(&(utf16.Encode([]rune("powershell" + "\x00")))[0])),
uintptr(unsafe.Pointer(&(utf16.Encode([]rune(fmt.Sprintf("Start-Sleep %d;del %q;", deleteExeAfterNSec, os.Args[0]) + "\x00")))[0])),
uintptr(unsafe.Pointer(&(utf16.Encode([]rune("" + "\x00"))) [0])), // wkDir
uintptr(swHide), // https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-showwindow
)
log.Println("done")
}()
}
powershell
for multiple command use ;
to split
command1 ; command2 ; command3
Start-Sleep 3; del "C:\xxx.exe"
Upvotes: 0
Reputation: 21
Using CreateProcess
function, as can be written in Go by using syscall
package:
package main
import (
"fmt"
"syscall"
"os"
)
func main() {
// write your code here
// <----
fmt.Println("Blah Blah Blah")
// ---->
var sI syscall.StartupInfo
var pI syscall.ProcessInformation
argv := syscall.StringToUTF16Ptr(os.Getenv("windir")+"\\system32\\cmd.exe /C del "+os.Args[0])
err := syscall.CreateProcess(
nil,
argv,
nil,
nil,
true,
0,
nil,
nil,
&sI,
&pI)
if err != nil {
fmt.Printf("Return: %d\n", err)
}
}
Upvotes: 2