系统用户和登录用户之间的Powershell交互

系统用户和登录用户之间的Powershell交互,powershell,automation,symantec,Powershell,Automation,Symantec,我想要一个以系统用户身份运行的powershell脚本在另一个用户会话上显示Windowsform,并与它的控件进行交互 我正在尝试使用Solarwinds N-Able自动安装/修复Symantec Endpoint Protection。该平台使用安装在客户端上的代理软件来监视和执行客户端上的任务 代理使用NT AUTHORITY\SYSTEM用户在计算机上执行任务。到目前为止,SEP的安装工作正常,但作为机器上的普通用户,卸载/安装阶段之间的重新启动仍然无法控制。我希望当前活动用户能够控制

我想要一个以系统用户身份运行的powershell脚本在另一个用户会话上显示Windowsform,并与它的控件进行交互

我正在尝试使用Solarwinds N-Able自动安装/修复Symantec Endpoint Protection。该平台使用安装在客户端上的代理软件来监视和执行客户端上的任务

代理使用NT AUTHORITY\SYSTEM用户在计算机上执行任务。到目前为止,SEP的安装工作正常,但作为机器上的普通用户,卸载/安装阶段之间的重新启动仍然无法控制。我希望当前活动用户能够控制此重新启动周期。类似于Windows update重新启动提示

我的想法是在登录用户的桌面上显示一个windowsform,并在其上显示控件以执行或延迟重新启动。我现在的问题是如何在另一个用户的会话上显示powershell中定义的windowsform,以及如何在系统用户上运行的脚本中恢复控件的操作


我已经尝试使用msg命令向系统上的所有用户发送消息。但这只是单向的沟通,并不是真的要在这种情况下使用。这是猜测。

我找到了解决问题的方法。我使用了boxdog在评论中建议的WTSSendMessage函数。我将其与获取登录用户会话ID的脚本相结合。我最小化了这个脚本,只获取“活动”用户的sessionID。然后,这将用于向用户发送消息。我在Solarwinds中测试了它,到目前为止,它工作得完美无缺

我的编码技能非常基本,但这是最终的结果

function Send-MessageBox
{
[CmdletBinding()]
[OutputType([string])]
Param
(        
    [Parameter(Mandatory=$true, Position=0)]
    [string]$title,
    [Parameter(Mandatory=$true, Position=1)]
    [string]$message,
    [Parameter(Mandatory=$true, Position=2)]
    [int]$duration,
    [Parameter(Mandatory=$true, Position=3)]
    [int]$style
)

Begin
{
    $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;
            }
        }
"@
}

Process
{
    if (-not ([System.Management.Automation.PSTypeName]'WTSMessage').Type)
    {
        Add-Type -TypeDefinition $typeDefinition
    }

    $RawOuput = (quser) -replace '\s{2,}', ',' | ConvertFrom-Csv
    $sessionID = $null

    Foreach ($session in $RawOuput) {  
        if(($session.sessionname -notlike "console") -AND ($session.sessionname -notlike "rdp-tcp*")) {
            if($session.ID -eq "Active"){    
                $sessionID = $session.SESSIONNAME
            }                        
        }else{
            if($session.STATE -eq "Active"){      
                $sessionID = $session.ID
            }        
        }   
    }
    $response = [WTSMessage]::SendMessage($sessionID, $title, $message, $duration, $style )
}
End
{
    Return $response
}
}

Send-MessageBox -title "Title" -message "Message" -duration 60 -style 0x00001034L

阅读Powershell,开始,获取一些代码,在这里粘贴不起作用的内容,然后人们可以提供帮助。您想要的可能是可编写脚本的,但不是脚本编写服务。这是您在PowerShell中很难做到的事情。从常规流程来看,跨会话通信已经够棘手的了,更不用说PowerShell了。它归结为必须在另一个会话中运行代码;您不能远程操纵UI,因为这正是会话划分所阻止的。您可以与该函数进行有限的双向通信,但它不允许自定义UI。A展示了如何在PowerShell中使用它。@怀疑论者感谢您的建议,这是我第一篇关于SO的帖子。我将尝试更具体一些,并在以后的文章中提供示例。我是否可以以某种方式修改此脚本,以便在远程机器上执行相同的操作?