如何使用Python发送Windows 10通知并在通知中添加按钮?

8
我该如何使用Python发送支持按钮的通知,并保持在操作/通知中心?
我正在尝试制作一个提醒我做事情的应用程序,通知将具有完成和推迟按钮。我尝试使用win10toast包,但通知没有停留在操作中心,并且不支持在上面放置按钮。
通知应类似于这样:

enter image description here

谢谢!


那是一个弹出式通知,而不仅仅是一条消息。您可以使用类似“win10toast”这样的软件包。 - Panagiotis Kanavos
我已经尝试过win10toast包了。它不支持我需要的按钮。 - Alexander
2
你忘了提到这两件事情。编辑问题并添加你实际想要的内容,你尝试过什么以及缺少什么。否则人们会浪费时间试图回答错误的问题。 - Panagiotis Kanavos
关于 win10toast,它是欺骗Toast的。Toast是由操作系统而非应用程序显示的。如果您检查win10toast的代码,您会发现它进行了一些Win32调用以显示旧式通知而非Toast。这就是为什么它无法显示任何新的UI元素。 - Panagiotis Kanavos
1
看起来有人使用Python/WinRT发布了一个真正的答案。 这里有一个gist。 - Panagiotis Kanavos
6个回答

13

也许有点晚了,但是这段代码应该可以展示一个带有按钮的通知样例:

import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom

app = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\\WindowsPowerShell\\v1.0\\powershell.exe'

#create notifier
nManager = notifications.ToastNotificationManager
notifier = nManager.create_toast_notifier(app)

#define your notification as string
tString = """
  <toast>
    <visual>
      <binding template='ToastGeneric'>
        <text>Sample toast</text>
        <text>Sample content</text>
      </binding>
    </visual>
    <actions>
      <action
        content="Delete"
        arguments="action=delete"/>
      <action
        content="Dismiss"
        arguments="action=dismiss"/>
    </actions>        
  </toast>
"""

#convert notification to an XmlDocument
xDoc = dom.XmlDocument()
xDoc.load_xml(tString)

#display notification
notifier.show(notifications.ToastNotification(xDoc))

3
抱歉打扰你,但你似乎是唯一了解应用程序 ID 工作原理的网上人士,能否请您向我解释一下。我想将 app = '{1AC14E77-0... 替换为更相关的内容。 - Isiah
5
你可以通过以管理员身份启动PowerShell并运行以下命令“get-StartApps”来获取任何Windows应用程序的应用用户模型ID(AUMID)。此命令将获取所有AUMIDs。如果你想要获取特定应用程序的AUMID,比如Windows PowerShell,请运行以下命令:“get-StartApps Windows PowerShell”。 - Tes3awy

5

很不幸,win10toast欺骗并显示旧式的Windows XP通知,而不是Toast。通过XML指定Toast的内容,可以包含按钮、格式和图像等。

要显示Toast,必须使用WinRT。幸运的是,最近有人写了一个真正的答案,使用Python/WinRT包。

我不会投票关闭作为重复,因为该问题的得到赞同的答案都使用通知而不是Toast。请去点赞那个答案。

链接的答案解释了如何安装Python/WinRT:

pip install winrt

然后用非常少的代码使用它:


import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom

#create notifier
nManager = notifications.ToastNotificationManager
notifier = nManager.create_toast_notifier();

#define your notification as string
tString = """
<toast>
    <visual>
        <binding template='ToastGeneric'>
            <text>Sample toast</text>
            <text>Sample content</text>
        </binding>
    </visual>
</toast>
"""

#convert notification to an XmlDocument
xDoc = dom.XmlDocument()
xDoc.load_xml(tString)

#display notification
notifier.show(notifications.ToastNotification(xDoc))

Toast内容文章介绍了如何通过代码或XML创建内容。按钮在这里进行了描述,例如:

    <actions>

        <action
            content="See more details"
            arguments="action=viewdetails&amp;contentId=351"
            activationType="foreground"/>

        <action
            content="Remind me later"
            arguments="action=remindlater&amp;contentId=351"
            activationType="background"/>

    </actions>

一旦选择了一个操作,参数就会被发送到应用程序


当我尝试运行第一部分时,它会给我这个错误: Traceback (most recent call last): File "c:/Users/Alexander/Desktop/python projects/notification/b.py", line 6, in <module> notifier = nManager.create_toast_notifier(); RuntimeError: 找不到元素。 - Alexander
1
我通过更改为 notifier = nManager.create_toast_notifier("App-id"); 修复了错误,但现在没有通知显示出来。 - Alexander
1
你还做了其他步骤吗?因为仅运行此脚本将会出现@Alexander提到的错误。如果您能提供其他必要的步骤,那就太好了。 - sanders

4
我将使用win10toast模块。首先使用:
pip install win10toast

在命令提示符(cmd)中安装它。
然后导入它:
from win10toast import ToastNotifier

一个示例通知:
toast = ToastNotifier()
toast.show_toast("Notification title","Notification body",duration=DURATION,icon_path="ICON PATH")

我已经尝试过了,但似乎它不支持在通知上放置按钮。 - Alexander
很遗憾,那个库作弊并显示旧式通知而不是 Toast。通知无法显示任何其他 UI 元素。 - Panagiotis Kanavos
是的,@PanagiotisKanavos,我使用过WinForms并有同样的经历。 - Wasif
@ Panagiotis Kanavos,我能使用其他支持其他UI元素的库吗? - Alexander

2
我没有足够的声望来评论我的另一个答案链接...但是我找到了一个使用WinRT的解决方案,它显示可以从您的Python代码中使用的按钮(不像其他答案只提供“关闭”选项)。我从这里的另一个WinRT答案开始,但那个答案有错误并且缺少关键步骤。
我在这里写了更多详细信息,但对于那些只想要解决方案的人,我将仅提供该代码。作为一个有用的示例,以下代码(Python 3.9)将使用子进程调用在handle_activated函数中打开Windows资源管理器窗口中的“文档”文件夹。
import os,sys,time
import subprocess
import threading
import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom

# this is not called on the main thread!
def handle_activated(sender, _):
    path = os.path.expanduser("~\Documents")
    subprocess.Popen('explorer "{}"'.format(path))

def test_notification():
    #define your notification as
    tString = """
    <toast duration="short">

        <visual>
            <binding template='ToastGeneric'>
                <text>New notifications</text>
                <text>Text</text>
                <text>Second text</text>
            </binding>
        </visual>

        <actions>
            <action
                content="Test Button!"
                arguments=""
                activationType="foreground"/>
        </actions>

    </toast>
    """

    #convert notification to an XmlDocument
    xDoc = dom.XmlDocument()
    xDoc.load_xml(tString)
    notification = notifications.ToastNotification(xDoc)

    # add the activation token.
    notification.add_activated(handle_activated)

    #create notifier
    nManager = notifications.ToastNotificationManager
    #link it to your Python executable (or whatever you want I guess?)
    notifier = nManager.create_toast_notifier(sys.executable)

    #display notification
    notifier.show(notification)
    duration = 7 # "short" duration for Toast notifications

    # We have to wait for the results from the notification
    # If we don't, the program will just continue and maybe even end before a button is clicked
    thread = threading.Thread(target=lambda: time.sleep(duration))
    thread.start()
    print("We can still do things while the notification is displayed")

if __name__=="__main__":
    test_notification()

1
您可以在 winrt 中像这样使用按钮:

import winrt.windows.ui.notifications as notifications
import winrt.windows.data.xml.dom as dom
import sys

# get python path
path = sys.executable

#create notifier
nManager = notifications.ToastNotificationManager
notifier = nManager.create_toast_notifier(path)

#define your notification as

tString = """
<toast>

    <visual>
        <binding template='ToastGeneric'>
            <text>New notifications</text>
            <text>Text</text>
            <text>Second text</text>
        </binding>
    </visual>

    <actions>
        <input id="textBox" type="text" placeHolderContent="Type a reply"/>
        <action
            content="Send"
            arguments="action=reply&amp;convId=01"
            activationType="background"
            hint-inputId="textBox"/>
            
        <action
            content="Button 1"
            arguments="action=viewdetails&amp;contentId=02"
            activationType="foreground"/>
    </actions>

</toast>
"""

#convert notification to an XmlDocument
xDoc = dom.XmlDocument()
xDoc.load_xml(tString)

# this is not called on the main thread.
def handle_activated(sender, _):
    print([sender, _])
    print('Button was pressed!')

# add the activation token.
activated_token = notification.add_activated(handle_activated)

#display notification
notifier.show(notifications.ToastNotification(xDoc))

我从这里了解到的:这个问题


1
你可以使用 https://github.com/go-toast/toast 中的 toast64.exe 应用程序。它支持按钮、应用名称、通知持续时间和通知声音且易于使用。这比类似 plyer、win10toast、py-notifier、pynotify 等其他 Python 模块要好得多。
以下是来自上述 Github 页面的代码片段:
C:\Users\Example\Downloads\toast64.exe \
  --app-id "Example App" \
  --title "Hello World" \
  --message "Lorem ipsum dolor sit amet, consectetur adipiscing elit." \
  --icon "C:\Users\Example\Pictures\icon.png" \
  --audio "default" --loop \
  --duration "long" \
  --activation-arg "https://google.com" \
  --action "Open maps" --action-arg "bingmaps:?q=sushi" \
  --action "Open browser" --action-arg "http://..."

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接