【问题标题】:Msgbox in PowerShell script run from task scheduler not working从任务计划程序运行的 PowerShell 脚本中的 Msgbox 不起作用
【发布时间】:2019-06-18 19:57:52
【问题描述】:

我有一个 PowerShell 脚本,它创建一个计划任务来启动该脚本。这个想法是脚本中有一些需要重新启动的任务。在 PowerShell 结束时,一个消息框应提示用户让用户知道所有任务都已完成。我究竟做错了什么?

Add-Type -AssemblyName PresentationFramework

TaskName = "Run Agents Install Script"
$TaskDescription = "Run Agents Install Script at logon"
$Action = New-ScheduledTaskAction -Execute 'Powershell.exe' `
  -Argument "-executionpolicy remotesigned -File $PSScriptRoot\AgentInstall.ps1"
$Trigger =  New-ScheduledTaskTrigger -AtLogOn

Register-ScheduledTask -Action $Action -Trigger $Trigger -TaskName $TaskName -Description $TaskDescription -User "System"


$MsgBoxInput =  [System.Windows.MessageBox]::Show('Installation completed successfully.','Agent Install','OK')
Switch  ($MsgBoxInput) {
    'OK' 
   {

$MsgBoxInput =  [System.Windows.MessageBox]::Show('WARNING! Please install Imprivata agent manually if applicable.','Agent Install','OK')
   }
}

【问题讨论】:

  • 任务是否以用户身份运行?我的理解是用户永远不会看到其他任何东西......
  • 好吧,任务作为系统运行,因为我希望正在执行的脚本以管理权限运行,并且在执行后不要求用户执行任何操作。
  • 那么我的理解是您将需要第二个任务 [以当前登录用户身份运行] 向用户发送通知。 [咧嘴]
  • 很遗憾我也这么认为。我将拭目以待,如果没有其他人可以提出另一个想法,那么我会将您的答案标记为解决方案。我希望这不是我唯一的选择
  • 祝你好运! [咧嘴]

标签: powershell scheduled-tasks msgbox


【解决方案1】:

一种选择是使用终端服务 API 向控制台发送消息。不幸的是,它是原生 API,因此您需要使用 .NET 互操作来调用它,但在这种情况下它并不太棘手:

$typeDefinition = @"
using System;
using System.Runtime.InteropServices;

public class WTSMessage {
    [DllImport("wtsapi32.dll", SetLastError = true)]
    public static extern bool WTSSendMessage(
        IntPtr hServer,
        [MarshalAs(UnmanagedType.I4)] int SessionId,
        String pTitle,
        [MarshalAs(UnmanagedType.U4)] int TitleLength,
        String pMessage,
        [MarshalAs(UnmanagedType.U4)] int MessageLength,
        [MarshalAs(UnmanagedType.U4)] int Style,
        [MarshalAs(UnmanagedType.U4)] int Timeout,
        [MarshalAs(UnmanagedType.U4)] out int pResponse,
        bool bWait
     );

     static int response = 0;

     public static int SendMessage(int SessionID, String Title, String Message, int Timeout, int MessageBoxType) {
        WTSSendMessage(IntPtr.Zero, SessionID, Title, Title.Length, Message, Message.Length, MessageBoxType, Timeout, out response, true);

        return response;
     }

}
"@

Add-Type -TypeDefinition $typeDefinition

[WTSMessage]::SendMessage(1, "Message Title", "Message body", 30, 36)

这本质上是WTSSendMessage 函数的薄包装。

您需要通过query 等工具获取SessionID。此脚本可能对此有所帮助:Get-UserSession

这里的TimeOut 值为 30,这意味着弹出窗口将等待 30 秒,然后返回值为“32000”。设置为“0”以永久等待。

MessageBoxTypeuType 值的组合:MessageBox Function。因此示例中的“36”是“MB_YESNO”和“MB_ICONQUESTION”值的组合,因此将显示带有问号图标和“是”/“否”按钮的消息。请注意,文档以十六进制形式提供了值,因此您需要对其进行转换。

我将此作为以管理员身份运行的计划任务进行了测试,它能够在不同登录用户的桌面上显示一条消息。希望有帮助。

【讨论】:

    猜你喜欢
    • 2020-08-07
    • 1970-01-01
    • 2017-08-01
    • 2020-07-13
    • 1970-01-01
    • 2019-05-08
    • 2019-10-31
    • 2015-07-22
    • 2023-02-07
    相关资源
    最近更新 更多