Powershell: Powershell -WindowStyle隐藏仍会短暂显示一个窗口

创建于 2017-01-22  ·  90评论  ·  资料来源: PowerShell/PowerShell

重现步骤

在“ Windows运行”对话框中,键入以下内容:
PowerShell.exe -WindowStyle Hidden -Command ping www.microsoft.com

预期行为

应该没有窗口,现在您不能在没有窗口闪烁的情况下启动Powershell,这使其变得毫无用处,例如用于计划任务。

请注意,我认为这是预期的行为,但令人困惑,可能需要新的选项。 如果您搜索如何在计划任务中运行Powershell,则可行的解决方法是对所有内容执行vbs脚本! 如:

Dim shell,command
command = "powershell.exe -nologo -File D:\myscript.ps1"
Set shell = CreateObject("WScript.Shell")
shell.Run command,0

这不是一件好事,powershell在shell本身中需要此功能,计划任务是重要的功能,对计划任务进行窗口刷新确实是一种糟糕的体验。

实际行为

它会短暂闪烁Powershell窗口。

环境数据

> $PSVersionTable
Name                           Value
----                           -----
PSVersion                      5.1.14393.693
PSEdition                      Desktop
PSCompatibleVersions           {1.0, 2.0, 3.0, 4.0...}
BuildVersion                   10.0.14393.693
CLRVersion                     4.0.30319.42000
WSManStackVersion              3.0
PSRemotingProtocolVersion      2.3
SerializationVersion           1.1.0.1
Issue-Enhancement OS-Windows WG-Interactive-Console

最有用的评论

您可能有一个powershellw.exe ,这将是一个不显示控制台窗口的GUI应用程序。 与javaw.exepythonw.exe操作相同。

所有90条评论

powershell.exe是一个控制台应用程序。 进程启动时,操作系统会自动创建控制台窗口。 因此,在打开控制台窗口(即刷新)之后,将执行处理-WindowStyle隐藏的powershell.exe代码。 要解决此问题,我们需要使用等效的wscript,即Win32主机应用程序而不是控制台主机应用程序。

鉴于我们无需在powershell.exe中进行任何代码更改即可解决此问题,因此我已将此问题更改为功能请求,以拥有类似wscript的主机来支持这种情况

http://www.f2ko.de/en/p2e.php
并且Power Shell Studio也有一个自定义主机

您可能有一个powershellw.exe ,这将是一个不显示控制台窗口的GUI应用程序。 与javaw.exepythonw.exe操作相同。

pwsh.exe可以为此提供支持或获取pwshw.exe? 随着这个新的pwsh exe的出现,似乎是更改-windowstyle hidden行为的好时机。 没有人曾经使用过hidden并认为“是的,这就是我想要的,刷新屏幕一秒钟”。

一直以来,不能更改powershell.exe及其旧有意义。

我会支持社区捐款以添加pwshw.exe

同意..这将与其他语言可执行文件保持一致,并解决了我目前必须将我的Powershell脚本包装在vbs脚本中的问题。

从技术上讲,我们可以像https://github.com/AvaloniaUI/Avalonia/wiki/Hide-console-window-for-self-contained-.NET-Core-application
c# editbin.exe /subsystem:windows yourapp.exe

但是我想知道-如果PowerShell Core是可移植的,在Unix上预期的行为是什么? 我们可以在所有平台上统一吗?
相关讨论https://github.com/dotnet/cli/issues/296它也提到我们可以使用GUI子系统。

也许@ mklement0有什么想法吗?

非Windows不支持@iSazonov -WindowStyle

是的,我的意思是-通过创建控制台,我们在Unix上是否具有相同的行为? 我们是否有不想在Unix上创建控制台的场景?

@iSazonov :我还没有真正研究过; 从我的个人经验来看,我唯一能告诉你的是,从Alfred 3TextExpander等实用程序中调用pwsh可以很好地工作

到目前为止,我一直在使用一个名为PS的快捷方式,其目标为:C:\ Windows \ System32 \ WindowsPowerShell \ v1.0powershell.exe和选项“运行:最小化”
像这样:
C:\Windows\PS Start-Process .
任务栏不会闪烁,但不再有控制台。

好像-WindowStyle Hidden必须是命令行的第一个参数。

因此,我们现在开始支持Windows PowerShell?

温馨提示,如果这是PowerShell Core问题? 提交问题时,请提供所需的PowerShell Core版本。

否则,Windows PowerShell需要通过UserVoice访问: https :

有关更多信息,请参见: https :

:)

@aresowj :尽管在调用PowerShell的_CLI_时参数的放置确实很重要(假设-Command任何内容都被解释为要执行的命令的一部分),但(a)OP的尝试已经将其放置在-Command和(b)不能阻止闪烁,原因是@BrucePay之前的注释中解释的原因。

@MaximoTrinidad :虽然此问题可能仅以Windows PowerShell为重点,但早已演变为PS Core功能请求(也应向后移植到Windows PowerShell)。

回顾一下:为了通过PowerShell CLI获得完全不可见的调用:

  • 在_Windows_上,需要遵循python.exe / pythonw.exe的模型,单独的新PowerShell可执行文件( pwshw.exe / powershellw.exe )是_GUI_应用程序。

  • 在不存在问题的macOS和Linux上,我_presume_不需要单独的可执行文件。 为了与Windows对称,可以实现一个简单的_symlink_,它指向常规的pwsh可执行文件。

谢谢@ mklement0!
:)

抱歉,弄错了两个Powershell,并感谢您的澄清。 :)

最初如何使用不可见的控制台在后台启动Powershell,然后检查任何控制台窗口参数-WindowStyle并实现它们,该怎么办?
但是,如果未找到,则可以启动一个可见的控制台窗口。

我在Windows控制台团队问题仓库中创建了一个问题: https :

@ zero77

pwsh.exe必须保留为控制台子系统应用程序,以确保从现有控制台窗口执行同步,标准流连接的执行。

因此,我们需要前面讨论过的_separate_ GUI子系统可执行文件pwshw.exe 。 如果我们希望该可执行文件支持(一个新的n个)控制台窗口的创建,则@iSazonov的链接是一个有用的起点。

@ Jawz84 :我认为控制台团队无法在这里提供帮助:

  • 诸如pwsh.exe类的_console-subsystem_应用程序总是会创建一个新的控制台窗口,该窗口发生在该应用程序看到其任何参数之前。

  • 唯一可以使用此控制台窗口的_hide_或_prevent creation_的方法是将_GUI-subsystem_应用程序作为入口点。 在最简单的情况下,此GUI子系统应用程序可以是_stub_,它将参数传递到控制台应用程序,但是将其启动_hidden_​​。

我将保留控制台问题,看看他们的想法。 我明白你的意思,我知道这可能是完全不可能的。 再说一遍,这可能是他们想考虑的事情。

[编辑:]我得到的答案是,当前无法在控制台中对此进行修改。 一个单独的pwshw.exe将是目前的方法。

kes! 开放近两年了? 对于SysAdmins来说,这是非常重要的功能。

@Chiramisu随时提供PR-我上面的评论中的建议。

我同意此功能请求,当以命令运行时,Powershell的默认行为令人困惑

应用Windows更新后,我开始看到这种情况。 最近有什么变化吗?

有没有人看过这实际上需要什么?

我正在查看powershell.exe,它看起来很简单:

https://github.com/PowerShell/PowerShell/blob/master/src/powershell/Program.cs

现在,要使其不使用控制台,是否只是像将Output type更改为“ Windows application”而不是Console application那样的项目设置?

尚未决定制作pwsh w .exe和backport powershell w .exe,这似乎是上述控制台团队反馈之后的唯一合理选择。

鉴于存在C:\windows\System32\taskhostw.exe ,这并不是异常。 在Windows搜索*w.exe中的C:\windows\System32\ *w.exe窗口中似乎有一些项目使用此模式

就我个人而言,我认为只需更改pwsh.exe即可修复-windowstyle而无需向后移植到powershell.exe,这是可以接受的,因为它是新的,但没有看起来那么简单。

@Ciantic的工作应该是复制powershell-win-core并更新.csproj文件,以便AssemblypwshwOutputTypewinexe 。 然后在build.psm1更改,以便我们同时构建两者。

我创建了一个小工具,将调用传递给您要从无窗口启动的任何控制台工具,并传递到原始文件:

https://github.com/Vittel/RunHiddenConsole

编译后,只需将可执行文件重命名为“ <targetExecutableName> w.exe”(附加“ w”),然后将其放在原始可执行文件旁边。
然后,您可以使用常规参数调用eG powershellw.exe或pwshw.exe,它不会弹出窗口。

如果有人对如何检查所创建的进程是否正在等待输入有所了解,不高兴包括您的解决方案:)
编辑:
找到了解决该问题的方法

编译发行版,我会在某个时候尝试! Vittel真的很棒!)

编译发行版,我会在某个时候尝试! Vittel真的很棒!)

好主意。 这样做了。

对于该特定的PowerShell问题(在我的计划任务中发生),我最终使用了https://github.com/stbrenner/SilentCMD (也是C#),我将尝试RunHiddenConsole ...

@Vittel谢谢您的项目! 您需要注意输入/输出/错误重定向以及参数转义。

如果我们要创建新的pwshw项目,我们应该考虑默认值:也许应该是-Noprofile

仅将OutputType更改WinExe是不够的,因为netcoreapp2x当前不支持此功能。 每个https://github.com/dotnet/core-setup/issues/196#issuecomment -394786860看起来我们需要等待netcoreapp30。

正如@iSazonov所暗示的那样,-NoExit因为控制台窗口将永远不会显示,仅用于自动化)。 因此,默认情况下需要考虑诸如-NoProfile类的东西以及针对自动化与交互式的其他默认值。

| 参数状态
| -| --
| 文件|
| -命令|
| -ConfigurationName |
| -EncodedCommand |
| -ExecutionPolicy |
| -InputFormat |
| 互动式| 删除(未使用)
| -NoExit | 删除(未使用)
| -NoLogo | 删除(未使用)
| -NonInteractive | 删除(默认情况下)
| -NoProfile | 删除(默认情况下)
| -OutputFormat | 删除(未使用)
| 版本| 去掉
| -WindowStyle | 删除(未使用)
| -WorkingDirectory |

如果pwshw.exe适用于没有控制台的情况,那么什么GUI将适用于GUI?

以供参考。 从https://github.com/dotnet/core-setup/pull/3888

重命名应用程序主机的能力。

但我找不到文档如何重命名。

感谢有用的参数表@iSazonov。

我认为-NonInteractive-WindowStyle也可以删除,因为它们仅在_console_窗口的上下文中具有含义-根据定义,GUI子系统可执行文件不具有此含义。

如果pwshw.exe适用于无主机座的情况,GUI将使用什么exe?

pwshw.exe可以做双重工作:

  • 用于自动化(例如,从计划任务中隐藏运行)
  • 用于在没有不需要的控制台窗口的情况下启动仅GUI用户交互的脚本(例如,创建WinForms UI的脚本)。

对于启动仅GUI用户交互的脚本……

我们应该为他们保留-WindowStyle吗?

那GUI控制台呢?

我们应该为他们保留-WindowStyle吗?

我认为这没有用,因为没有事先告知将在什么时候以何种机制创建GUI窗口(如果有的话),并且创建该窗口的代码必须以某种方式向PowerShell查询其启动参数。尊重价值。

_GUI console_是什么意思?

@iSazonov pwshw按照定义将没有交互式控制台。 -WindowStyle专用于控制台窗口。 利用WinForms / WPF的脚本独立于pwshw主机。

谢谢! 上表已更新。

我宁愿避免为此创建新的主机,而我更愿意使用可用的PTY解决此问题。

这是目前的解决方法-唯一出现的是任务栏中的PowerShell实例迅速消失-屏幕上不再闪烁conhost.exe。

$WshShell = New-Object -ComObject 'WScript.Shell'
$ShortcutPath = Join-Path -Path $ENV:Temp       -ChildPath 'Temp.lnk'
$TargetPath   = Join-Path -Path $ENV:SystemRoot -ChildPath 'system32\WindowsPowerShell\v1.0\powershell.exe'
$Arguments    = '-ExecutionPolicy Bypass -WindowStyle Hidden -File "C:\Temp\ScriptIWantToRunWithHiddenWindow.ps1"'

$Shortcut = $WshShell.CreateShortcut($ShortcutPath)
$Shortcut.TargetPath  = $TargetPath
$Shortcut.Arguments   = $Arguments
$Shortcut.WindowStyle = 7
$Shortcut.Save()

& explorer.exe $ShortcutPath

有进取心的个人可以将这项技术与psexec.exe -i结合使用,以在当前登录的用户会话中远程运行脚本。

  • 这仍然会在我的系统上弹出一个快速可见的闪存窗口
  • 我尝试了上面的silentCMD,但这需要net3.5,但我在某些第三方系统上未安装net3.5

我认为似乎没有解决方案

您是否签出了我的运行隐藏控制台GitHub项目?
我故意使用了最低要求。 它应该适用于几乎所有Windows版本

正如@Ciantic提到的,解决此问题的最佳方法是使用VB脚本:

放入ps-run.vbs

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
    objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

然后使用它来运行所需的命令,例如从Windows的计划任务中运行,例如

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

我使用类似的方法来频繁运行任务,而不会看到任何闪烁的窗口。

您是否签出了我的运行隐藏控制台GitHub项目?
我故意使用了最低要求。 它应该适用于几乎所有Windows版本

我在本周尝试过它,但它不会弹出net3.5要求。 谢谢! 真好也将牢记VBS。

if (!([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
    Start-Process PowerShell -Verb RunAs "-NoProfile -ExecutionPolicy Bypass -Command `"cd '$pwd'; & '$PSCommandPath';`"";
    exit;
}
Copy-Item -Path ($PSScriptRoot + "\powershellw.exe") -Destination "c:\windows\system32\WindowsPowerShell\v1.0" 
New-Item -ItemType File -Path ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
Copy-Item -Path ($PSScriptRoot + "\check.ps1") -Destination ('C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1') -Force
$tasks = Get-ScheduledTask
foreach($task in $tasks) {
    $taskexec = $task.actions.Execute -replace '.*\\'
    $taskname = $task.TaskName
    if ($taskexec.ToLower() -eq 'powershellw.exe' -or $taskexec.ToLower() -eq 'silentcmd.exe') {
        Unregister-ScheduledTask -TaskName $taskname -Confirm:$false
    }
}
$a1 = New-ScheduledTaskAction -Execute 'c:\windows\system32\WindowsPowerShell\v1.0\powershellw.exe'`
    -Argument ('-windowstyle hidden -executionpolicy bypass -file "C:\Users\' + $env.username  + '\AppData\Roaming\check\Local Store\scripts\check.ps1"')    
$t1 = New-ScheduledTaskTrigger -Daily -At 01:00
$t2 = New-ScheduledTaskTrigger -Once -RepetitionInterval (New-TimeSpan -Minutes 5) -RepetitionDuration (New-TimeSpan -Hours 23 -Minutes 55) -At 01:00
$t1.Repetition = $t2.Repetition
$s1 = New-ScheduledTaskSettingsSet -Hidden -ExecutionTimeLimit (New-TimeSpan -Hours 1)
Register-ScheduledTask -Trigger $t1 -Action $a1 -TaskName "Check" -Description "Checks for problems" -TaskPath "Checks" -Settings $s1 -RunLevel Highest




PTY? 那是什么?

iPhone特使

Le 18 mars 2019à21:51,Joey Aiello [email protected] aécrit:

我宁愿避免为此创建新的主机,而我更愿意使用可用的PTY解决此问题。

-
您收到此消息是因为您已订阅此线程。
直接回复此电子邮件,在GitHub上查看,或使该线程静音。

@ Roy-Orbison的VBScript的简化版本:

CreateObject("Wscript.Shell").Run("powershell -Command ""& '<PS command/script path>'"""),0

在我的机器上使用正在处理的脚本进行了测试,当通过PS提示符或计划任务中的wscript运行时,它似乎可以工作。

优点:

  • 无需将脚本路径放在wscript命令行中。
  • 不要将ExecutionPolicyBypass

缺点:

  • 每个PowerShell命令都需要单独的VBScript脚本。

我个人更喜欢VBScript解决方案而不是RunHiddenConsole ,因为它不涉及将未签名的可执行文件部署到系统目录。 但是,拥有正式的pwshw.exe / powershellw.exe显然比任何一个都更可取。

我个人更喜欢VBScript解决方案而不是RunHiddenConsole ,因为它不涉及将未签名的可执行文件部署到系统目录。

签名不应该是大问题。 您甚至可以自己动手做一些事情
ps:我还添加了在您要执行的脚本旁边部署工具的选项。 因此不再需要在powershell可执行文件旁边的系统中进行设置

最好有变通办法和第三方解决方案,但要强调@alexbuzzbee的最新评论:

需要_PowerShell_随附的解决方案。


至于解决方法:请注意,即使没有帮助脚本文件,也可以使用基于VBScript的解决方案,但这是不可思议的:

您可以在Run对话框(或cmd.exe )中运行以下命令,创建一个不可见的PowerShell实例,该实例弹出一个消息框(不显示控制台窗口):

mshta.exe vbscript:(CreateObject("WScript.Shell").Run("pwsh -c (New-Object -Com Wscript.Shell).Popup('hi')",0))(Window.Close)

警告@alexbuzzbee指出“此解决方案在Defender ATP端点保护系统中生成警报,因此可能不适用于企业环境”。

@Vittel的解决方案转换为官方解决方案是否不合理? 将代码移到PowerShell存储库中,对其进行修改以仅启动powershell.exepwsh.exe并使用PowerShell构建/分发应该不难。

.NET Core 3.0支持构建不会显示控制台的winexe。 我已经有一个可以使用的原型,只需要清理它作为PR。

我已经有一个可以正常工作的原型

我也在路上:-)我希望您能简化CommandLineParameterParser (删除EarlyParse?)。

@ mklement0的解决方案在Defender ATP Endpoint Protection系统中生成警报(它不像运行PowerShell代码的mshta ),因此它可能不适用于企业环境。

谢谢@alexbuzzbee ,我已在先前的评论中添加了您的警告。 我认为实际上是触发警报的VBScript CreateObject() / JScript new ActiveXObject()调用; 似乎mshta.exe过去曾被用于恶意软件。

@ mklement0 ATP特别是对于mshta始于pwsh而不是CreateObject()可疑。

很高兴知道,@ alexbuzzbee。

我基于以下事实(例如从cmd.exe )执行将产生Access is denied error.并触发Windows Defender警报这一事实。

mshta vbscript:Execute("CreateObject(\"WScript.Shell\"): Window.Close")

最重要的是,解决方法可能是利用了漏洞,正如您所报告的,漏洞可能触发现有的安全软件,并且有可能在将来完全关闭。

同意@ SteveL-MSFT尝试实施适当的解决方案。

@ SteveL-MSFT,2018-02-20

我会支持社区捐款以添加pwshw.exe

@ SteveL-MSFT,2019-10-31

.NET Core 3.0支持构建不会显示控制台的winexe。 我已经有一个可以使用的原型,只需要清理它作为PR。

这已经很长时间了,对于脚本编写来说将是很棒的,特别是对于Task Scheduler,(也许是cron?)等等。由于PowerShell Core是跨平台的,因此在其他受支持的平台上也可以使用吗? WSL呢?

winexe原型可以运行,但是边缘过于粗糙,无法安装到7.0。 例如,如果您在命令行args上犯了一个错误,您将不会知道,因为没有输出窗口。 如果我们使用其他工具,例如wscript.exe,则应显示一个对话框,其中包含适当的错误消息。

至于非Windows,Linux和macOS不需要等效的winexe,因为我相信可以在不创建控制台窗口的情况下启动pwsh进程,而Windows则需要它,因为它明确区分了控制台和Windows应用程序。 您当然可以在今天的Task Scheduler或cron等中使用pwsh。

带有增强功能的VBScript垫片的另一个版本:支持将参数传递给Powershell脚本。 这将使我们在要调用的脚本上更具灵活性。 全部没有窗口弹出!

powershell.vbs:

Set args = CreateObject("System.Collections.ArrayList")
For Each oItem In Wscript.Arguments: args.Add oItem: Next

CreateObject("Wscript.Shell").Run("powershell -windowstyle hidden -File """ & Join(args.ToArray, """ """) & """"),0

例如,我有一个Powershell脚本来监听特定的Windows事件,使用Task Scheduler提取事件数据并调用PowerShell脚本来发送有关事件的通知。 我使用自定义EventTrigger创建了自定义计划任务(请参阅Technet的文章):

    <EventTrigger>
      <Enabled>true</Enabled>
      <Subscription><!-- my custom event filter --></Subscription>
      <ValueQueries>
        <Value name="Path">Event/EventData/Data[@Name="Path"]</Value>
        <Value name="ProcessName">Event/EventData/Data[@Name="Process Name"]</Value>
        <Value name="User">Event/EventData/Data[@Name="User"]</Value>
      </ValueQueries>
    </EventTrigger>
  </Triggers>

之后,我们可以在事件操作中使用变量$(Path) $(ProcessName) $(User) 。 对于这种情况,我们可以如下调用脚本。 每当事件触发触发器时,Windows都会调用我的notifier.ps1

wscript.exe "C:\path\to\powershell.vbs" "C:\path\to\notifier.ps1" -User $(User) -ProcessName $(ProcessName) -Path $(Path)

powershell.vbs是绝对可重用的。 😏

原文: https :

正如@Ciantic提到的,解决此问题的最佳方法是使用VB脚本:

放入ps-run.vbs

Set objShell = CreateObject("Wscript.Shell")
Set args = Wscript.Arguments
For Each arg In args
  objShell.Run("powershell -windowstyle hidden -executionpolicy bypass -noninteractive ""&"" ""'" & arg & "'"""),0
Next

然后使用它来运行所需的命令,例如从Windows的计划任务中运行,例如

wscript "C:\Path\To\ps-run.vbs" "C:\Other\Path\To\your-script.ps1"

我使用类似的方法来频繁运行任务,而不会看到任何闪烁的窗口。

您可以使用QB64创建一个小的EXE来隐藏脚本。 QB64是使用QBASIC代码并将其编译为C ++ exe的C ++解释器。 如果使用_SHELLHIDESHELL _HIDE命令,则可以从EXE内调用PowerShell脚本,而根本不显示PowerShell窗口。 为了安全起见,我将其与-WindowStyle Hidden结合使用,但是我从未遇到过任何问题。 示例: SHELL$ = "PowerShell -WindowStyle Hidden -ExecutionPolicy Bypass " + CHR$(34) + "&'" + _STARTDIR$ + "\GetNewDate.ps1';exit $LASTEXITCODE" + CHR$(34): a = _SHELLHIDE(SHELL$)
您还可以隐藏使用$SCREENHIDE编译的整个EXE,以便他们不必查看程序的任何部分。
如果您有退出代码要传递回另一个代码区,则可以在调用PowerShell脚本将其传递回QB64 EXE时使用exit $LASTEXITCODE 。 如果要从QB64 EXE传递代码,则可以使用命令SYSTEM然后是要传递回程序/脚本其余部分的代码。 希望这对某人有帮助。

现在使用此方法,以便每个调用都获取所有参数,而不是每个参数都是单独的脚本,例如@ttimasdf ,但是使用纯数组:

Dim args()
Redim args(Wscript.Arguments.Count - 1)
For i = 0 To UBound(args): args(i) = Wscript.Arguments.Item(i): Next
CreateObject("Wscript.Shell").Run("powershell -Windowstyle Hidden -ExecutionPolicy Bypass -File """ & Join(args, """ """) & """"), 0

我保留-ExecutionPolicy Bypass原因是,除非我也使用Set-ExecutionPolicy否则我会遇到无声失败。 等不及pwshw.exe

https://github.com/SeidChr/RunHiddenConsole/releases/download/1.0.0-alpha.2/hiddenw.exe

@罗伊·奥比森
妳去只需要重命名😉😅
(不好意思。将其命名为pwshw.exe,放在您的路径中,它应该可以正常工作)

真的不知道pwsh团队花了这么长时间。
没什么大不了的

真的不知道pwsh团队花了这么长时间。

缺乏资源。 我们需要更多的代码审阅者和贡献者。

我将PowerShell脚本配置为从Elgato Stream Deck运行,并弹出一个打开的窗口。 我尝试使用-Noninteractive-WindowStyle hidden ,但是仍然会短暂弹出。

pwsh -Noninteractive -WindowStyle hidden -Command "...."

我希望我们在下一个预览中能够看到pwshw。

我将PowerShell脚本配置为从Elgato Stream Deck运行,并弹出一个打开的窗口。 我尝试使用-Noninteractive-WindowStyle hidden ,但是仍然会短暂弹出。

pwsh -Noninteractive -WindowStyle hidden -Command "...."

使用我上面发布的工具,您可以轻松解决该弹出窗口。 每天在Steam平台和启动脚本中使用它

仅供参考:在控制台团队中,我们正在为将来的应用程序(和现有应用程序的将来版本)提出一种解决方案。 会有一些开销[1],但是它将使PowerShell能够在GUI上下文中启动时_选择是否分配控制台窗口_。

规范拉取请求: https :

@DHowett很高兴我在合并PR之前就发现了这一点! 对于客户来说,拥有一个exe会更好,而不用担心winexe版本,更不用说团队的维护成本了。

但是,如果我在没有Windows终端的情况下调用PowerShell怎么办? 例如,我直接从Elgato Stream Deck调用pwsh.exe。 终端团队提议的选项无法解决这种情况,或者其他类似情况,会解决吗?

@ pcgeek86不要让这个名字骗了你! 我和我的团队拥有整个Windows控制台子系统,包括控制台应用程序如何启动以及如何彼此对话。

@DHowett我认为这意味着该功能仅在将来的Windows版本中可用吗? 因此,仍在使用较低版本Windows版本的人根本就不走运吗? 🤔

一个应用程序,与inheritOnly的consoleAllocationPolicy从资源管理器启动时不会出现一个控制台控制台子系统。

Task Scheduler的行为是什么?

@DHowett for pwsh,将需要一个标志来指定我们希望分配一个conpty,以便调用控制台API的脚本仍然可以工作

诸如PowerShell之类的应用程序可能希望保留“自动”控制台分配,而InheritOnly将不适合它们。

因此,该策略不能解决所有PowerShell场景,而PowerShell应该再次使用变通方法吗?

这让我想起了我试图直接使用AllocConsole的PR。

下层(@ vexx32)

不幸的是,这是对我的团队所产生的任何限制,这些限制是控制台子系统的一部分,不能作为Terminal的一部分提供。 我们正在努力解决😉

Task Scheduler(@iSazonov)的行为是什么

说“ Explorer”是一种方便的方式,可以用更少的单词来表达“任何尚未具有控制台的上下文”。 放心,_任何在没有控制台的情况下启动inheritOnly应用程序的操作都不会导致控制台的分配。

需要一个标志来指定(@ SteveL-MSFT)

幸运的是,PowerShell已经以WindowStyle的形式提供了此功能。 除非用户请求隐藏启动,否则默认模式可以是“ _i应该调用AllocConsole() _”(它将满足所有控制台API需求!)。 该规范仅将分配控制台的责任移到(pwsh)中,以便它可以最终控制是否有主机。 由于已经设置了powershell来处理这种情况,因此在“隐藏”检查之前/之后只有几行delta。

不能解决所有PowerShell方案(@iSazonov)

规范进一步解释了powershell如何处理此问题(请参见上文,我对Steve的答复)。 据我了解,这可以解决_本问题和相关问题中提到的所有情况。_

像在PR中那样调用AllocConsole() / AttachConsole()和在为不同的控制台分配策略显示应用程序时调用AllocConsole()的主要区别是,子系统位指示生成的外壳(cmd,pwsh,bash,ish)应该_wait_等待生成的外壳( pwshw )退出,这减少了对控制台I / O句柄的干扰。

如果您有一个Windows子系统应用程序,该应用程序调用AttachConsole()返回其托管控制台,则产生的外壳程序和新应用程序将为谁可以读取输入/写入输出而奋斗。 这就是为什么从Windows子系统应用程序_never_可以调用Attach的原因,除非您可以完全控制产生您的外壳(您不能)。

@DHowett谢谢! 要明确,PowerShell的建议是使用SUBSYSTEM_GUI和InheritedOnly?

我相信SUBSYSTEM_CUIinheritOnly对于PowerShell是正确的。 它为您提供以下行为:

  1. cmd( $SHELL )将等待pwsh退出,然后返回( SUBSYSTEM_CUI
  2. 从资源管理器/任务调度程序运行它时,pwsh可以决定创建新的控制台窗口( inheritOnly
  3. 当您从cmd / pwsh /(控制台外壳程序)运行它时,pwsh将自动收到一个控制台窗口

当您从资源管理器/任务计划中运行它时,pwsh可以做出有关创建新控制台窗口的决定(inheritOnly)

嗯,PowerShell如何知道进程所有者-资源管理器或任务计划表?

我不认为它需要知道。

这就是原因(C ++):

int main() {
    auto a{ _parseArgs() };
    if (a.WindowStyle != WindowStyle::Hidden)
    {
        AllocConsole();
    }
}

PowerShell已经根据用户是否要求生成窗口。 该功能已经存在-因此,这是对代码进行的最小增量更改,可修复此错误_,并且_保留了所有其他用例的原始行为。

这提供了一个良好的平台,可在此平台上建立新的行为。

@DHowett就像@ vexx32提到的那样,仍然有很多Server 2012 / R2和2016可供使用,因此对于Win10和Server 2019 OS变体来说,这似乎很好,我认为对于PowerShell,我们需要考虑一种方法这比当前建议的解决方案@ SteveL-MSFT更优雅

除非您还可以将该更改作为安全修补程序的一部分移植到下层操作系统中,

子系统位指示派生外壳(cmd,pwsh,bash,ish)应等待派生外壳(pwshw)退出,这减少了对控制台I / O句柄的干扰。

它也应该适用于PowerShell。 我的意思是,如果PowerShell调用外部控制台应用程序,它也应该遵循新策略。 PowerShell会自动获得此消息,还是需要在PowerShell中添加任何内容?

如规范中所述,PowerShell必须选择加入。 但是,您提出了一个要点:我相信应用程序_by_生成的“仅继承”应用程序将弹出控制台窗口,即_terrible_。 我将在规范中对此进行重新讨论,因为我相信我知道我们可以解决这个问题。

除非您也可以将该更改移植到下层操作系统

在我们甚至无法评估它的反向移植之前,一定要完成该功能,但是我100%同意这限制了它的实用性。

只是想说,如果您要从另一个程序启动powershell,则它有可能支持隐藏子进程。 例如,Autohotkey对运行命令具有“隐藏”标志。

此页面是否有帮助?
0 / 5 - 0 等级