亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

如何運行用Golang編寫的應用程序作為Windows服務

如何運行用Golang編寫的應用程序作為Windows服務

Go
偶然的你 2022-08-01 16:33:01
我無法使用我使用Win32 api開發的屏幕截圖應用程序作為Windows后臺服務。我將其作為Windows后臺服務安裝并運行,到目前為止我沒有問題。我的問題:該服務沒有給我打印輸出。不截取屏幕截圖。我嘗試制作另一個簡單的應用程序。我嘗試使用 OutputDebugStringW 函數發送消息,但我的問題沒有得到解決。無法使用 Win32 api 開發 Windows 后臺應用程序?為什么我會遇到此問題?如何使用win32 api將屏幕截圖應用程序作為Windows后臺服務運行?我的 Windows 后臺服務未生成輸出   package main        import (        "fmt"        "log"        "time"            "github.com/checkgo/win"        "github.com/kardianos/service"    )        var logger service.Logger        type program struct {        exit chan struct{}    }        func (p *program) Start(s service.Service) error {        if service.Interactive() {            logger.Info("Running in terminal.")        } else {            logger.Info("Running under service manager.")        }        p.exit = make(chan struct{})            // Start should not block. Do the actual work async.        go p.run()        return nil    }    func (p *program) run() {        logger.Infof("I'm running %v.", service.Platform())        ticker := time.NewTicker(2 * time.Second)        for {            select {            case tm := <-ticker.C:                win.OutputDebugString(fmt.Sprintf("%s : %v", "This is test message", tm))            case <-p.exit:                ticker.Stop()            }        } // link to whaterver image from the web        }    func (p *program) Stop(s service.Service) error {        // Stop should not block. Return with a few seconds.        return nil    }        func main() {        svcConfig := &service.Config{            Name:        "GoServiceExampleSimple",            DisplayName: "Go Service Example",            Description: "This is an example Go service.",        }            prg := &program{}        s, err := service.New(prg, svcConfig)        if err != nil {            log.Fatal(err)        }        logger, err = s.Logger(nil)        if err != nil {            log.Fatal(err)        }        err = s.Run()        if err != nil {            logger.Error(err)        }    }屏幕截圖:調試視圖和 Windows 服務屏幕捕獲
查看完整描述

2 回答

?
慕碼人2483693

TA貢獻1860條經驗 獲得超9個贊

如果服務在 LocalSystem 帳戶的安全上下文中運行,但不包括SERVICE_INTERACTIVE_PROCESS屬性,則它使用以下窗口工作站和桌面:Service-0x0-3e7$\default。此窗口站不是交互式的,因此服務無法顯示用戶界面。此外,由服務創建的進程無法顯示用戶界面。

參考:窗口站和桌面創建

交互式窗口站是唯一可以顯示用戶界面或接收用戶輸入的窗口站。它被分配給交互式用戶的登錄會話,并包含鍵盤、鼠標和顯示設備。它總是被命名為“WinSta0”。所有其他窗口站都是非交互式的,這意味著它們無法顯示用戶界面或接收用戶輸入。

參考:窗口站

據說您要捕獲的屏幕位于交互式窗口站的默認桌面(Winsta0\default)。您可以在 中創建子進程,子進程用于屏幕截圖。使用 CreateProcessAsUser 調用服務中的子進程。Winsta0\default

請參閱以下C++代碼。雖然這不是一門圍棋語言,但我認為熟悉winapi的呼喚就足夠了。

DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)

{

    OutputDebugString(_T("My Sample Service: ServiceWorkerThread: Entry"));

    WCHAR station[] = L"Winsta0\\default";

    SECURITY_ATTRIBUTES saAttr;

    saAttr.nLength = sizeof(SECURITY_ATTRIBUTES);

    saAttr.bInheritHandle = TRUE;

    saAttr.lpSecurityDescriptor = NULL;

     

    STARTUPINFO si;

    ZeroMemory(&si, sizeof(STARTUPINFO));

    si.cb = sizeof(STARTUPINFO);

    si.lpDesktop = station;

    si.dwFlags = STARTF_USESTDHANDLES;

    PROCESS_INFORMATION pi;


    HANDLE hToken;

    bool err = WTSQueryUserToken(WTSGetActiveConsoleSessionId(), &hToken);

    WCHAR path[] = L"D:\\child.exe";  //child.exe is used to take screenshots

    if (CreateProcessAsUser(hToken, path, NULL, 0, 0, true, CREATE_NO_WINDOW, 0, 0, &si, &pi))

    {

        ...


查看完整回答
反對 回復 2022-08-01
?
慕蓋茨4494581

TA貢獻1850條經驗 獲得超11個贊

使用CreateProcessAsUser函數解決。

我用來解決問題的GOO源代碼。

Windows 后臺服務應用程序的源代碼:

package main


import (

    "log"

    "reflect"

    "sync"

    "syscall"


    "github.com/checkgo/win"

    "github.com/kardianos/service"

    "golang.org/x/sys/windows"

)


var logger service.Logger


type program struct {

    exit chan struct{}

}


func (p *program) Start(s service.Service) error {

    if service.Interactive() {

        logger.Info("Running in terminal.")

    } else {

        logger.Info("Running under service manager.")

    }

    p.exit = make(chan struct{})


    // Start should not block. Do the actual work async.

    go p.run()

    return nil

}

func (p *program) run() {

    var wgT sync.WaitGroup

    wgT.Add(1)

    test(&wgT)

    wgT.Wait()

}


func test(wg *sync.WaitGroup) {

    var saAttr win.SECURITY_ATTRIBUTES

    saAttr.NLength = uint32(reflect.TypeOf(syscall.SecurityAttributes{}).Size())

    saAttr.BInheritHandle = win.TRUE

    saAttr.LpSecurityDescriptor = uintptr(0)


    var si syscall.StartupInfo

    si.Cb = uint32(reflect.TypeOf(syscall.SecurityAttributes{}).Size())

    si.Desktop = windows.StringToUTF16Ptr("Winsta0\\default")

    si.Flags = windows.STARTF_USESTDHANDLES

    var hToken windows.Token

    id := win.WTSGetActiveConsoleSessionId()

    err := windows.WTSQueryUserToken(uint32(id), &hToken)

    if err != nil {

        logger.Info(err)

    }

    path := windows.StringToUTF16Ptr("C:\\Users\\cingo\\go\\src\\srv\\agent\\test_agent.exe")


    var pi syscall.ProcessInformation

    syscall.CreateProcessAsUser(syscall.Token(hToken),

        path,

        nil,

        nil,

        nil,

        true,

        windows.CREATE_NO_WINDOW,

        nil,

        nil,

        &si,

        &pi)


}


func (p *program) Stop(s service.Service) error {

    // Stop should not block. Return with a few seconds.

    return nil

}


func main() {

    svcConfig := &service.Config{

        Name:        "GoServiceExampleSimple",

        DisplayName: "Go Service Example",

        Description: "This is an example Go service.",

    }


    prg := &program{}

    s, err := service.New(prg, svcConfig)

    if err != nil {

        log.Fatal(err)

    }

    logger, err = s.Logger(nil)

    if err != nil {

        log.Fatal(err)

    }

    err = s.Run()

    if err != nil {

        logger.Error(err)

    }

}

正在運行的應用程序


package main


import (

    "fmt"

    "github.com/checkgo/win"

    "time"

)


func main() {

    for {

        time.Sleep(time.Second * 1)

        win.OutputDebugString(fmt.Sprintf("%s", "This is test message"))

    }

}


查看完整回答
反對 回復 2022-08-01
  • 2 回答
  • 0 關注
  • 397 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號