macos - 当屏幕锁定/关闭时,cmd.Run() 在 Macos 上的 golang 中永远挂起

标签 macos go osascript

我正在 Macos 上运行 golang 应用程序。它有一些代码如下:

for {
    time.Sleep(time.Second * 5)
    cmd := exec.Command("/usr/bin/osascript", "-e", `display dialog "hello" with title "hello"`)
    err := cmd.Run()
}

如果我不锁定屏幕(屏幕始终打开时),它就可以正常工作。但是,如果该行执行时屏幕被锁定并关闭,则代码 err := cmd.Run() 将永远挂起。当我解锁屏幕(打开屏幕)时,for 循环会永远卡在那里,并且永远不会继续执行。

我不确定这个问题是否属于 golang 或者 MacOS 如何处理 osascript。谁能告诉我如何解决它?非常感谢。

PS:我在 Linux 中使用相同的代码并将 /usr/bin/osascript 替换为 /usr/bin/xmessage 并且这总是工作正常,甚至没有任何问题如果 Linux 中屏幕被锁定/关闭。

已编辑:

我的解决方案,改用chrome:

cmd := exec.Command(`/Applications/Google Chrome.app/Contents/MacOS/Google Chrome`, "-new-window", "/path/hello.html")

最佳答案

这似乎与 MacOS 在屏幕锁定时如何将进程置于空闲状态有关。它使 osasscript 子进程永远无法完成执行并阻塞 for 循环。

您可以做的一件事是在超时上下文中运行命令。我已经尝试过并且有效。当屏幕解锁并且超时到期时,执行将恢复。

示例:

package main

import (
    "context"
    "fmt"
    "os/exec"
    "time"
)

func main() {
    for {
        time.Sleep(time.Second * 5)

        // run your command with a timeout
        ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
        cmd := exec.CommandContext(
            ctx,
            "/usr/bin/osascript",
            "-e",
            `display dialog "hello" with title "hello"`,
        )

        err := cmd.Run()
        if err != nil {
            fmt.Println(err)
        }
        // don't forget to cancel your context to avoid context leak
        cancel()
    }
}

或者,如果您不希望超时,您可以在尝试调用显示对话框之前检查屏幕是否已锁定。

package main

import (
    "context"
    "fmt"
    "os"
    "os/exec"
    "strings"
    "time"
)

func main() {
    for {
        time.Sleep(time.Second * 5)

        ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second)
        cmd := exec.CommandContext(
            ctx,
            "python",
            "-c",
            "import sys,Quartz; d=Quartz.CGSessionCopyCurrentDictionary(); print d",
        )

        var err error
        var b []byte
        if b, err = cmd.CombinedOutput(); err != nil {
            cancel()
            continue
        }
        cancel()

        // if screen is not locked
        if !strings.Contains(string(b), "CGSSessionScreenIsLocked = 1") {
            cmd = exec.Command(
                "/usr/bin/osascript",
                "-e",
                "display dialog \"Hello\"",
            )
            cmd.Stdout = os.Stdout
            cmd.Stderr = os.Stderr

            err = cmd.Run()
            if err != nil {
                fmt.Println("err: ", err)
            }
        }
    }
}

关于macos - 当屏幕锁定/关闭时,cmd.Run() 在 Macos 上的 golang 中永远挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55321573/

相关文章:

applescript - 将 AppleScript 编译成带参数的应用程序

c++ - 在 Mac OS-X 上编译 C++ 程序时出现 "framework not found"

java - 从 Java 打印失败并显示 'pstopdffilter/pstocupsraster failed with err number -31000'

go - 如何让 golang 中的解码函数处理多种类型?

bash - bash 中的 ${1-1} 是什么意思?

java - 通过 osascript 将您的 java 应用程序提升为 MAC OSX 上的管理员权限

objective-c - 报告 OSX 中的大小写不敏感(使用 OSXFuse)

linux - 'per process' 是否也计入共享库/动态库?

python - golang gdb - 打印变量

go - gocov不会将完整的测试覆盖率结果上传到codeclimate中