追記
CreationFlags に直接指定出来ますね...
package main
import (
"log"
"os/exec"
"syscall"
)
const (
_IDLE_PRIORITY_CLASS = 0x40
)
func main() {
cmd := exec.Command("notepad")
cmd.SysProcAttr = &syscall.SysProcAttr{
CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT | _IDLE_PRIORITY_CLASS,
}
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
cmd.Wait()
}
追記ここまで
先日 GoCon に参加した際、牛乳を吹いてるアイコンの人に「Golang で優先度を変えてプロセスを起動するにはどうしたらいいんでしょうね」というお題を貰ったので書いてみました。
syscall には必要な API しか持ってないので API を持ってくるところが若干めんどくさいですが、出来る事は出来ます。プロセスをサスペンド状態で起動しておき、優先度を変更後にリジュームします。(起動後いきなり激しい動きをするヤバい奴がいない事もない)
package main
import (
"log"
"os/exec"
"syscall"
"unsafe"
)
const (
_CREATE_SUSPENDED = 0x00000004
_IDLE_PRIORITY_CLASS = 0x40
_PROCESS_SET_INFORMATION = 0x0200
)
var (
kernel32 = syscall.NewLazyDLL("kernel32")
procSetPriorityClass = kernel32.NewProc("SetPriorityClass")
procOpenThread = kernel32.NewProc("OpenThread")
procResumeThread = kernel32.NewProc("ResumeThread")
procThread32First = kernel32.NewProc("Thread32First")
procThread32Next = kernel32.NewProc("Thread32Next")
)
func resumeChildThread(childpid int) error {
snapshot, err := syscall.CreateToolhelp32Snapshot(syscall.TH32CS_SNAPTHREAD, 0)
if err != nil {
return err
}
defer syscall.CloseHandle(snapshot)
const _THREAD_SUSPEND_RESUME = 0x0002
type ThreadEntry32 struct {
Size uint32
tUsage uint32
ThreadID uint32
OwnerProcessID uint32
BasePri int32
DeltaPri int32
Flags uint32
}
var te ThreadEntry32
te.Size = uint32(unsafe.Sizeof(te))
ret, _, err := procThread32First.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
if ret == 0 {
return err
}
for te.OwnerProcessID != uint32(childpid) {
ret, _, err = procThread32Next.Call(uintptr(snapshot), uintptr(unsafe.Pointer(&te)))
if ret == 0 {
return err
}
}
h, _, err := procOpenThread.Call(_THREAD_SUSPEND_RESUME, 1, uintptr(te.ThreadID))
if h == 0 {
return err
}
defer syscall.Close(syscall.Handle(h))
ret, _, err = procResumeThread.Call(h)
if ret == 0xffffffff {
return err
}
return nil
}
func main() {
cmd := exec.Command("notepad")
cmd.SysProcAttr = &syscall.SysProcAttr{
CreationFlags: syscall.CREATE_UNICODE_ENVIRONMENT | _CREATE_SUSPENDED,
}
err := cmd.Start()
if err != nil {
log.Fatal(err)
}
hProcess, err := syscall.OpenProcess(_PROCESS_SET_INFORMATION, true, uint32(cmd.Process.Pid))
if err != nil {
log.Fatal(err)
}
r1, _, err := procSetPriorityClass.Call(uintptr(hProcess), uintptr(_IDLE_PRIORITY_CLASS))
if r1 == 0 {
log.Fatal(err)
}
syscall.CloseHandle(hProcess)
resumeChildThread(cmd.Process.Pid)
cmd.Wait()
}