如何在Toast消息中消费点击事件?

问题描述 投票:0回答:1

我编写了一个 powershell 代码,显示带有“是/否”选项的 toast 消息。现在我正在寻找一种正确处理该点击事件的方法。请参阅下面我到目前为止的代码:

cls
Remove-Variable * -ea 0
$ErrorActionPreference = 'stop'

Add-Type -AssemblyName System.Runtime.WindowsRuntime
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]

# now lets define a toast-message:
$toastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()
$xmlString = @"
  <toast launch = "Test1" scenario='alarm'>
    <visual>
      <binding template="ToastGeneric">
        <text>Title</text>
        <text>Message</text>
      </binding>
    </visual>
    <audio src="ms-winsoundevent:Notification.Looping.Alarm" />
    <actions>
        <action content="yes" arguments="yes" />
        <action content="no"  arguments="no"  />
    </actions>
  </toast>
"@
$toastXml.LoadXml($XmlString)
$toast = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
$appId = '{1AC14E77-02E7-4E5D-B744-2EB1AE5198B7}\WindowsPowerShell\v1.0\powershell.exe'
$notify = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId)
$notify.Show($toast)

这里我需要一种方法来等待事件,当用户单击 toast 中的“是/否”按钮(或“x”来关闭所有按钮)时。它应该在没有外部 DLL 的情况下工作,但使用例如“add_Activated”和一个 eventHandler,如以下 c# 代码所示: https://github.com/david-risney/PoshWinRT/blob/master/PoshWinRT/EventWrapper.cs

我认为它应该与 PoshWinRT 项目中的其他 cs-Wrapper 类似,我最终可以将其转换为:

# replacement for PoshWinRT - AsyncOperationWrapper:
Add-Type -AssemblyName System.Runtime.WindowsRuntime
$asTaskGeneric = foreach($method in [System.WindowsRuntimeSystemExtensions].GetMethods()) {
    if ($method.name -ne 'AsTask') {continue}
    if ($method.GetParameters().Count -ne 1) {continue}
    if ($method.GetParameters().ParameterType.Name -ne 'IAsyncOperation`1') {continue}
    $method
    break
}

function Await($WinRtTask, $ResultType) {
    $asTask  = $asTaskGeneric.MakeGenericMethod($ResultType)
    $netTask = $asTask.Invoke($null, @($WinRtTask))
    $null    = $netTask.Wait(-1)
    $netTask.Result
}

# sample for async operation:
$null = [Windows.Storage.StorageFile, Windows.Storage, ContentType = WindowsRuntime]
$file = 'c:\windows\notepad.exe'
$info = await ([Windows.Storage.StorageFile]::GetFileFromPathAsync($file)) ([Windows.Storage.StorageFile])
$info

不幸的是,该 eventWrapper 的编码似乎有点棘手。这些是我无法实现的代码片段,但它们可能指向正确的方向:

$method  = [Windows.UI.Notifications.ToastNotification].GetMethod('add_Activated')
$handler = [Windows.Foundation.TypedEventHandler[Windows.UI.Notifications.ToastNotification,System.Object]]::new($toast, $intPtr1)
$handler = [System.EventHandler]::new($toast, $intPtr2)

特别是创建 eventHandler 所需的第二个 IntPtr 参数让我完全困惑。

欢迎任何意见。非常感谢。

powershell event-handling toast
1个回答
0
投票

经过几天的调查和测试不同的选项后,我现在很高兴终于分享了一个 Powershell 代码片段,它能够对 Toast-GUI 中按下的任何按钮做出反应。这是代码...

Param($data)

cls
$ErrorActionPreference = 'stop'

# here we handle any input-parameter coming from the below Toast-Action:
if ($data) {
    # (optional) show the value of the parameter for 5 seconds:
    $objShell = New-Object -ComObject "WScript.Shell"
    $objShell.Popup("Parameter from Toast-GUI: $data", 5)

    # insert your own code here...

}

# make sure not to run into a loop:
if ($data) {break}

# define global variables:
$temp = $env:Temp
$launchFile = "$temp\ToastAction.exe"

# make sure we re-create a new launchFile:
if (Test-Path $launchFile -PathType Leaf){Remove-Item $launchFile -Force}
if (Test-Path $launchFile -PathType Leaf){break}

# get the full path of this script:
$script = $MyInvocation.PSCommandPath
if (!$script) {$script = $psISE.CurrentFile.Fullpath}

# create the VBS-file as a hidden launcher for Powershell:
$vbs = @"
set objWsh = CreateObject("WScript.Shell")
powershell = objWsh.ExpandEnvironmentStrings("%windir%\system32\WindowsPowershell\v1.0\powershell.exe")
set objFs  = CreateObject("Scripting.FileSystemObject")
if WScript.Arguments.Count > 0 Then
   arg = " """ + wscript.arguments(0) + """"
   objWsh.Run powershell + " -NoP -NonI -W Hidden -Exec Bypass -File ""$script""" + arg, 0
   wscript.sleep 1000
end if
"@
$vbs | out-file -LiteralPath "$temp\start.vbs" -Encoding ascii -Force

# create an IEXPRESS SED-file:
$SedFile = [System.IO.Path]::GetTempFileName()
$body = @"
[Version]
Class=IEXPRESS
SEDVersion=3
[Options]
ShowInstallProgramWindow=0
HideExtractAnimation=1
UseLongFileName=1
RebootMode=N
TargetName=$launchFile
FriendlyName=ToastAction
AppLaunched=wscript.exe /b
PostInstallCmd=<None>
SourceFiles=SourceFiles
[Strings]
FILE0="start.vbs"
[SourceFiles]
SourceFiles0=$temp\
[SourceFiles0]
%FILE0%=
"@
$body | out-file -LiteralPath $SedFile -Encoding ascii -Force

# create an executable via IEXPRESS as a target for our custom protocol:
$fso = New-Object -ComObject Scripting.FileSystemObject
$shortName = $fso.getfile($SedFile).ShortPath
start-process -FilePath "$env:windir\SYstem32\iexpress.exe" -ArgumentList "/N $shortName /Q" -Wait

# cleanup temporary files:
Remove-Item -LiteralPath $SedFile
Remove-Item -LiteralPath "$temp\start.vbs"

# register launchFile as a handler for the custom protocol:
$protocolName = "ToastAction"
$regPath = "HKCU:\Software\Classes\$protocolName"
$fullName = [System.IO.FileInfo]::new($launchfile).FullName
New-Item "$regPath\shell\open\command" -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -LiteralPath $regPath -Name 'URL Protocol' -Value '' -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -LiteralPath $regPath -Name '(default)' -Value "URL:$($protocolName)" -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null
New-ItemProperty -LiteralPath "$regPath\shell\open\command" -Name '(default)' -Value """$fullname"" /C:""wscript start.vbs """"%1""""""" -PropertyType String -Force -ErrorAction SilentlyContinue | Out-Null

Add-Type -AssemblyName System.Runtime.WindowsRuntime
$null = [Windows.UI.Notifications.ToastNotificationManager, Windows.UI.Notifications, ContentType = WindowsRuntime]
$null = [Windows.Data.Xml.Dom.XmlDocument, Windows.Data.Xml.Dom.XmlDocument, ContentType = WindowsRuntime]

# now lets define a toast-message:
$toastXml = [Windows.Data.Xml.Dom.XmlDocument]::new()

# here comes the toast-message using the custom protocol:
$xmlString = @"
<toast scenario="reminder">
    <visual>
        <binding template="ToastGeneric">
            <image placement="hero" src="file:///C:\Windows\Web\Wallpaper\Spotlight\img50.jpg"/>
            <image id="1" placement="appLogoOverride" hint-crop="circle" src="file:///C:\Windows\System32\WindowsSecurityIcon.png"/>
            <text>Good evening</text>
            <text placement="attribution">www.lakesidesoftware.com</text>
            <group>
                <subgroup>
                    <text hint-style="title" hint-wrap="true">Make your choice!</text>
                </subgroup>
            </group>
            <group>
                <subgroup>
                    <text hint-style="body" hint-wrap="true">Take the blue Pill and remain a slave to the illusion. </text>
                </subgroup>
            </group>
            <group>
                <subgroup>
                    <text hint-style="body" hint-wrap="true">Take the red Pill and become a slave to reality.</text>
                </subgroup>
            </group>
        </binding>
    </visual>
    <actions>
        <action activationType="protocol" arguments="ToastAction://bluePill?value=123" content="Blue Pill"/>
        <action activationType="protocol" arguments="ToastAction://redPill?value=456"  content="Red Pill"/>
        <action activationType="system" arguments="dismiss" content="Dismiss"/>
    </actions>
</toast>
"@

# (optional) set custom Toast app-Id:
$appId = 'Toast.Systrack.App'
$AppDisplayName = 'Systrack User Notification'
$IconUri = "C:\Windows\System32\InputSystemToastIcon.png"
$RegPath = "HKCU:\Software\Classes\AppUserModelId\$appId"
if (!(Test-Path $RegPath)) {$null = New-Item -Path $AppRegPath -Name $appId -Force}
$null = New-ItemProperty -Path $RegPath -Name DisplayName -Value 'Lakeside User Notification' -PropertyType String -Force
$null = New-ItemProperty -Path $RegPath -Name ShowInSettings -Value 0 -PropertyType DWORD -Force
$null = New-ItemProperty -Path $RegPath -Name IconUri -Value $IconUri -PropertyType ExpandString -Force
$null = New-ItemProperty -Path $RegPath -Name IconBackgroundColor -Value 0 -PropertyType ExpandString -Force

# create/launch the Toast-GUI:
$toastXml.LoadXml($XmlString)
$toast  = [Windows.UI.Notifications.ToastNotification]::new($toastXml)
$toast.ExpirationTime = [datetime]::Now.AddSeconds(30)
$notify = [Windows.UI.Notifications.ToastNotificationManager]::CreateToastNotifier($appId)
$notify.Show($toast) 
© www.soinside.com 2019 - 2024. All rights reserved.