我正在尝试构建一个脚本,向用户显示WPF窗口,指示进度。脚本本身将从系统帐户运行,但需要向最终用户显示进度。该脚本将通过PSExec或SCCM在系统帐户中启动(请注意,在这两种情况下,初始脚本都无法启用'用户交互'启用。是的。我知道。虽然它是一个要求)。
有没有办法从System上下文创建该窗口,以便用户可以与它进行交互?或者,可以在另一个用户的上下文中打开Runspace吗?或者这些都不是可行的途径?
答案 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
}
不幸的是,消息框的设计非常有限。实际上看起来很丑:-)