有没有办法在不同的用户上下文中启动PowerShell Runspace?

时间:2014-08-05 19:52:20

标签: wpf windows powershell sccm

我正在尝试构建一个脚本,向用户显示WPF窗口,指示进度。脚本本身将从系统帐户运行,但需要向最终用户显示进度。该脚本将通过PSExec或SCCM在系统帐户中启动(请注意,在这两种情况下,初始脚本都无法启用'用户交互'启用。是的。我知道。虽然它是一个要求)。

有没有办法从System上下文创建该窗口,以便用户可以与它进行交互?或者,可以在另一个用户的上下文中打开Runspace吗?或者这些都不是可行的途径?

2 个答案:

答案 0 :(得分:0)

类似的东西:

Start-Process powershell.exe -credential {cred. maybe a stored cred?} -nonewwindow -working directory {wherever you want it to start from. cred value must have access} -argumentlist "-file yourfile.ps1"

" yourfile.ps1"将有用于与用户交互的代码块。 -nonewwindow当然取决于你。我不确定你是如何跨用户空间进行通信的。我还是比程序员更多的系统管理员,所以我做了一些hacky。就像每10%重新绘制窗口一样。取决于您想要的用户反馈。

答案 1 :(得分:0)

我发现的唯一解决方案是此功能:Send-TSMessageBox。 http://pinvoke.net/default.aspx/wtsapi32.WTSSendMessage

这可以作为SYSTEM运行,但显示在用户的桌面上。 缺点:在虚拟机上,消息框显示在会话0(这是Hyper-V“集成”的连接窗口)中。如果通过RDP(mstc)会话进行连接,则不会看到该消息框。 但是在Citrix桌面上它可以工作。该消息框将在用户会话中弹出,而不是在Citrix主机上弹出。

这是全部功能:

Function Send-TSMessageBox {
    <#
    .SYNOPSIS   
        Send a message or prompt to the interactive user with the ability to get the results.

    .DESCRIPTION
        Allows the administrator to send a message / prompt to an interactive user. 

    .EXAMPLE   
        "Send a message immediately w/o waiting for a responce."
        Send-TSMessageBox -Title "Email Problem" -Message "We are currently having delays and are working on the issue."

        "Send a message waiting 60 seconds for a reponse of [Yes / No]."
        $Result = Send-TSMessageBox -Title "System Updated" -Message "System requires a reboot. Would you like to the reboot system now?" `
        -ButtonSet 4 -Timeout 60 -WaitResponse $true 

    .ButtonSets
        0 = OK
        1 = Ok/Cancel
        2 = Abort/Retry/Ignore
        3 = Yes/No/Cancel
        4 = Yes/No
        5 = Retry/Cancel
        6 = Cancel/Try Again/Continue    

    .Results
        "" = 0
        "Ok" = 1
        "Cancel" = 2  
        "Abort" = 3
        "Retry" = 4    
        "Ignore" = 5
        "Yes" = 6
        "No" = 7
        "Try Again" = 10
        "Continue" = 11
        "Timed out" = 32000
        "Not set to wait" = 32001 

    .NOTES   
        Author: Raymond H Clark
        Twitter: @Rowdybullgaming

    .RESOURCES
        http://technet.microsoft.com/en-us/query/aa383488 
        http://technet.microsoft.com/en-us/query/aa383842
        http://pinvoke.net/default.aspx/wtsapi32.WTSSendMessage
    #> 
    Param([string]$Title = "Title", [string]$Message = "Message", [int]$ButtonSet = 0, [int]$Timeout = 0, [bool]$WaitResponse = $false)

        $Signature = @"
        [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);

            [DllImport("kernel32.dll")]
            public static extern uint WTSGetActiveConsoleSessionId();
"@

            [int]$TitleLength = $Title.Length;
            [int]$MessageLength = $Message.Length;
            [int]$Response = 0;

            $MessageBox = Add-Type -memberDefinition $Signature -name "WTSAPISendMessage" -namespace "WTSAPI" -passThru   
            $SessionId = $MessageBox::WTSGetActiveConsoleSessionId()

            $MessageBox::WTSSendMessage(0, $SessionId, $Title, $TitleLength, $Message, $MessageLength, $ButtonSet, $Timeout, [ref] $Response, $WaitResponse)

            $Response
}


不幸的是,消息框的设计非常有限。实际上看起来很丑:-)