简体   繁体   English

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

[英]Is there a way to start a PowerShell Runspace in a different User's Context?

I'm trying to build a script that will display a WPF window to a user indicating progress. 我正在尝试构建一个脚本,该脚本将向用户显示WPF窗口以指示进度。 The script itself will run from the system account, but will need to show progress to the end user. 该脚本本身将通过系统帐户运行,但需要向最终用户显示进度。 The script will be launched in the System account either through PSExec or SCCM (Note in both cases the initial script can't be run with 'user interaction' enabled. Yeah. I know. Its a requirement though). 该脚本将通过PSExec或SCCM在系统帐户中启动(请注意,在两种情况下,初始脚本都无法在启用“用户交互”的情况下运行。是的,我知道。但这是必需的)。

Is there a way to create that window from the System context so that a user can interact with it? 有没有一种方法可以从系统上下文中创建该窗口,以便用户可以与之交互? Alternatively, can a Runspace be opened in another User's context? 或者,可以在另一个用户的上下文中打开运行空间吗? Or are neither of these a viable route? 还是这都不是一条可行的路线?

Something like: 就像是:

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" would have the code block for interacting with the user. “ yourfile.ps1”将具有用于与用户进行交互的代码块。 -nonewwindow is of course up to you. -nonewwindow当然取决于您。 I'm not sure how you'd communicate across userspace. 我不确定您如何跨用户空间进行交流。 Im still more sysadmin than programmer so I'd do something hacky. 我的系统管理员人数比程序员还多,所以我会做一些骇人听闻的事情。 Like re-draw the window every 10% or something. 就像每隔10%左右重画一次窗口。 Depends what feedback you want from the user. 取决于您要从用户那里得到什么反馈。

The only solution I found was this function: Send-TSMessageBox. 我发现的唯一解决方案是此功能:Send-TSMessageBox。 http://pinvoke.net/default.aspx/wtsapi32.WTSSendMessage http://pinvoke.net/default.aspx/wtsapi32.WTSSendMessage

This could be run as SYSTEM but shows up on the user's desktop. 这可以作为SYSTEM运行,但显示在用户的桌面上。 One downside: On a virtual machine, the message box shows up in session 0 (which is the Hyper-V "integrated" connection window). 缺点:在虚拟机上,消息框显示在会话0(这是Hyper-V“集成”的连接窗口)中。 If you are connected via RDP (mstc) session you will not see the message box. 如果通过RDP(mstc)会话进行连接,则不会看到该消息框。 But on a Citrix desktop it works. 但是在Citrix桌面上它可以工作。 The message box pops up within the user session and not on the Citrix host. 该消息框将在用户会话中而不是在Citrix主机上弹出。

Here's the full function: 这是全部功能:

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
}


Unfortunately the design of the messsage box is very limited. 不幸的是,消息盒的设计非常有限。 Actually it looks ugly :-) 其实看起来很丑:-)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM