Powershell: Powershell -WindowStyle Hidden ainda mostra uma janela brevemente

Criado em 22 jan. 2017  ·  90Comentários  ·  Fonte: PowerShell/PowerShell

Passos para reproduzir

Na caixa de diálogo Executar do Windows, digite o seguinte:
PowerShell.exe -WindowStyle Hidden -Command ping www.microsoft.com

Comportamento esperado

Não deve haver nenhuma janela, agora você não pode iniciar o PowerShell sem a janela piscando, tornando-o bastante inútil, por exemplo, para tarefas agendadas.

Observação : acho que esse é o comportamento pretendido, mas é confuso e provavelmente é necessária uma nova opção. Se você pesquisar como executar um PowerShell em uma tarefa agendada, a solução alternativa é fazer um script vbs de todas as coisas! Tal como:

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

Isso não é uma coisa boa, o PowerShell precisa desse recurso no próprio shell, as tarefas agendadas são um recurso importante e ter um flash de janela na tarefa agendada é uma experiência realmente ruim.

Comportamento real

A janela do PowerShell pisca brevemente.

Dados ambientais

> $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

Comentários muito úteis

Você poderia ter um powershellw.exe que seria um aplicativo GUI que não mostra uma janela de console. O mesmo que javaw.exe e pythonw.exe fazem.

Todos 90 comentários

powershell.exe é um aplicativo de console. A janela do console é criada automaticamente pelo sistema operacional quando o processo é iniciado. O código powershell.exe que processa -WindowStyle Hidden é, portanto, executado depois que a janela do console é aberta e, portanto, o flash. Para corrigir isso, precisaríamos do equivalente a wscript, ou seja, um aplicativo host win32 em vez de um aplicativo host de console.

Dado que não há alteração de código que possamos fazer no powershell.exe para resolver isso, mudei esse problema para uma solicitação de recurso para ter um host do tipo wscript para oferecer suporte a esse tipo de cenário

http://www.f2ko.de/en/p2e.php
e Power Shell Studio tem um host personalizado

Você poderia ter um powershellw.exe que seria um aplicativo GUI que não mostra uma janela de console. O mesmo que javaw.exe e pythonw.exe fazem.

pwsh.exe obter suporte para isso ou obter o pwshw.exe conforme sugerido acima? Com este exe pwsh sendo novo, parece ser um ótimo momento para mudar o comportamento de -windowstyle hidden . Ninguém nunca usou hidden e pensou "sim, é isso que eu queria, mostre alguma tela por um segundo".

Faz sentido que o powershell.exe não possa ser alterado depois de todo esse tempo e seu legado.

Eu apoiaria uma contribuição da comunidade para adicionar pwshw.exe

Concordo .. isso seria consistente com outros executáveis ​​de linguagem e me resolveria tendo que atualmente embrulhar meus scripts do PowerShell em scripts de vbs.

Tecnicamente, poderíamos fazer como https://github.com/AvaloniaUI/Avalonia/wiki/Hide-console-window-for-self-contained-.NET-Core-application
c# editbin.exe /subsystem:windows yourapp.exe

Mas eu me pergunto - se o PowerShell Core é portátil, qual é o comportamento esperado no Unix? Podemos ser unificados em todas as plataformas?
Discussão relacionada https://github.com/dotnet/cli/issues/296 Também menciona que poderíamos usar o subsistema GUI.

Talvez @ mklement0 tenha alguma

@iSazonov -WindowStyle não é compatível com sistemas que não sejam Windows

Sim, eu quis dizer - temos o mesmo comportamento no Unix ao criar um console? Temos cenários em que não queremos criar o console no Unix?

@iSazonov : Eu realmente não investiguei isso; a única coisa que posso dizer, por experiência pessoal, é que invocar pwsh invisivelmente funciona bem com utilitários como Alfred 3 e TextExpander

O que tenho usado até agora é um atalho chamado PS com o destino: C: \ Windows \ System32 \ WindowsPowerShell \ v1.0powershell.exe e a opção Executar: Minimizado
Como isso:
C:\Windows\PS Start-Process .
A barra de tarefas pisca, mas não há mais console.

Parece que -WindowStyle Hidden tem que ser o primeiro parâmetro de sua linha de comando.

Então, estamos começando a oferecer suporte ao Windows PowerShell agora ??

Apenas um lembrete amigável, se este é um problema do PowerShell Core? Forneça a versão do PowerShell Core conforme necessário ao enviar problemas.

Caso contrário, o Windows PowerShell precisa acessar o UserVoice em: https://windowsserver.uservoice.com/forums/301869-powershell

Para obter mais informações, consulte: https://github.com/PowerShell/PowerShell#windows -powershell-vs-powershell-core

:)

@aresowj : Embora o posicionamento dos argumentos importe ao chamar o _CLI_ do PowerShell (dado que qualquer coisa após -Command é interpretado como parte do comando a ser executado), (a) a tentativa do OP já o coloca antes de -Command e (b) que não evita o piscar, pelos motivos explicados no comentário anterior de @BrucePay .

@MaximoTrinidad : Embora esse problema possa ter começado focado apenas no Windows PowerShell, há muito tempo ele se transformou em uma solicitação de recurso PS Core (que também merece retrocesso para o Windows PowerShell).

Para recapitular: Para obter invocações totalmente invisíveis por meio da CLI do PowerShell:

  • No _Windows_, um novo executável PowerShell separado ( pwshw.exe / powershellw.exe ) é necessário que seja um aplicativo _GUI_, seguindo o modelo do python.exe / pythonw.exe par

  • No macOS e no Linux, onde o problema não existe, _presumo_ que não há necessidade de um executável separado. Para simetria com o Windows, um simples _symlink_ pode ser implementado que simplesmente aponta para o pwsh executável normal.

Obrigado @ mklement0!
:)

Desculpe pessoal, confundi os dois Powershells e obrigado pelo seu esclarecimento. :)

Que tal iniciar o Powershell em segundo plano com um console invisível e, em seguida, verificar os argumentos da janela do console -WindowStyle e implementá-los.
Mas, se nenhum for encontrado, ele pode iniciar uma janela de console visível.

Eu criei um problema no repositório de problemas da equipe do console do Windows aqui: https://github.com/Microsoft/console/issues/249

@ zero77 :

pwsh.exe deve permanecer um aplicativo de subsistema de console para garantir a execução síncrona e conectada a fluxos padrão a partir de uma janela de console existente.

Portanto, precisamos do _separate_ previamente discutido, executável do subsistema GUI, pwshw.exe . Se quisermos que o executável suporte a criação _condicional_ de uma (n invariavelmente nova) janela de console, o link de @iSazonov é um ponto de partida útil.

@ Jawz84 : Não acho que a equipe do console possa ajudar aqui:

  • Um aplicativo _console-subsystem_ como pwsh.exe invariavelmente cria uma nova janela de console, o que acontece antes que o aplicativo veja qualquer um de seus argumentos.

  • A única maneira de _ocultar_ ou _impedir a criação_ desta janela do console é ter um aplicativo de _sistema GUI_ como ponto de entrada. No caso mais simples, este aplicativo de subsistema GUI pode ser um _stub_ que retransmite argumentos para o aplicativo de console, mas o inicia _hidden_.

Vou deixar o problema do console em aberto, ver o que eles acham. Eu entendo o que você quer dizer e sei que pode ser totalmente impossível. Mesmo assim, pode ser algo que eles gostariam de considerar.

[Edit:] Eu tenho a resposta de que isso não é viável para consertar no console. Um pwshw.exe separado seria o caminho a seguir por enquanto.

Caramba! Aberto há quase dois anos? Este é um recurso muito importante para SysAdmins.

@Chiramisu Sinta-se à vontade para oferecer uma proposta de RP no meu comentário acima.

Concordo com esta solicitação de recurso, o comportamento padrão do Powershell quando executado como um comando é confuso

Começo a ver isso depois de aplicar as atualizações do Windows. algo mudou recentemente?

Alguém viu o que isso exigiria na prática?

Estou olhando para o powershell.exe, e parece bastante simples:

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

Agora, para torná-lo sem console, é apenas uma configuração de projeto danada como alterar o tipo de saída para "aplicativo do Windows" em vez de aplicativo de console?

Não houve uma decisão de fazer pwsh w .exe e backport powershell w .exe, que parece ser a única escolha razoável após o feedback das equipes de console acima.

Isso não seria tão incomum, dado que C:\windows\System32\taskhostw.exe existe. Parece haver alguns itens usando este padrão no Windows, pesquisando *w.exe em C:\windows\System32\

Pessoalmente, eu teria pensado que apenas alterar o pwsh.exe para corrigir -windowstyle sem backport para powershell.exe é aceitável, pois é novo, mas nada é tão simples quanto parece.

@Ciantic, o trabalho deve ser replicar powershell-win-core e atualizar o arquivo .csproj para que Assembly seja pwshw e OutputType seja winexe . Em seguida, mude build.psm1 para que possamos construir ambos.

Criei uma pequena ferramenta passando a chamada para qualquer ferramenta de console que você deseja iniciar sem janela para o arquivo original:

https://github.com/Vittel/RunHiddenConsole

Após a compilação, basta renomear o executável para "<targetExecutableName> w.exe" (anexar um "w") e colocá-lo próximo ao executável original.
Você pode então chamar eG powershellw.exe ou pwshw.exe com os parâmetros usuais e não aparecerá uma janela.

Se alguém tiver uma ideia de como verificar se o processo criado está aguardando entrada, ficarei feliz em incluir sua solução :)
EDITAR:
encontrou uma solução para esse problema

Compile uma versão e eu tentarei algum dia! Trabalho muito bom, Vittel :) 👍 💯

Compile uma versão e eu tentarei algum dia! Trabalho muito bom, Vittel :) 👍 💯

boa ideia. fiz assim.

Para esse problema específico do PowerShell (ocorrido em minhas tarefas agendadas), acabei usando https://github.com/stbrenner/SilentCMD (também C #), vou dar uma chance ao RunHiddenConsole ...

@Vittel Obrigado pelo projeto! Você precisa prestar atenção ao redirecionamento de entrada / saída / erro e talvez ao escape de argumento.

Se vamos fazer um novo projeto pwshw, devemos pensar sobre os padrões: talvez -Noprofile deva ser.

Simplesmente mudar OutputType para WinExe não é suficiente, pois netcoreapp2x não suporta isso atualmente. Por https://github.com/dotnet/core-setup/issues/196#issuecomment -394786860 parece que precisamos esperar por netcoreapp30.

Como @iSazonov aludiu, simplesmente construir como winexe em vez de exe não será uma solução completa. Alguns dos parâmetros existentes permitidos por pwsh.exe não funcionariam corretamente em pwshw.exe (como -NoExit pois uma janela de console nunca aparecerá, é apenas para automação). Portanto, coisas como -NoProfile por padrão e outros padrões específicos para automação vs interativo deveriam ser considerados.

| Parâmetro | Status
| - | -
| -File |
| -Command |
| -ConfigurationName |
| -EncodedCommand |
| -ExecutionPolicy |
| -InputFormat |
| -Interactive | Remover (não usado)
| -NoExit | Remover (não usado)
| -NoLogo | Remover (não usado)
| -NonInteractive | Remover (por padrão)
| -NoProfile | Remover (por padrão)
| -OutputFormat | Remover (não usado)
| -Version | Retirar
| -WindowStyle | Remover (não usado)
| -WorkingDirectory |

Se pwshw.exe for para um cenário sem console, qual exe será para GUI?

Para referência. De https://github.com/dotnet/core-setup/pull/3888 :

Capacidade de um apphost ser renomeado.

mas não encontrei docs como renomear.

Obrigado pela útil tabela de parâmetros, @iSazonov.

Eu acho que -NonInteractive e -WindowStyle podem ser removidos, pois eles só têm significado no contexto de uma janela _console_ - que o executável do subsistema GUI por definição não terá.

Se pwshw.exe for para um cenário sem console, qual exe será para GUI?

pwshw.exe pode cumprir uma tarefa dupla:

  • Para automação (executar oculto de uma tarefa agendada, por exemplo)
  • Para iniciar scripts somente de interação com o usuário da GUI sem uma janela de console indesejada (por exemplo, scripts que criam interfaces de usuário do WinForms).

Para iniciar scripts apenas de interação com o usuário da GUI ...

Devemos manter -WindowStyle para eles?

E quanto ao console GUI?

Devemos manter -WindowStyle para eles?

Não acho isso útil, porque não há como dizer com antecedência em que ponto e por meio de qual mecanismo uma janela GUI - se houver - será criada, e o código que a cria teria que consultar o PowerShell para seus parâmetros de inicialização de alguma forma para respeitar o valor.

O que você quer dizer com _GUI console_?

@iSazonov pwshw por definição não terá um console interativo. -WindowStyle é especificamente para a janela do console. Scripts que aproveitam WinForms / WPF são independentes do host pwshw.

Obrigado! A tabela acima foi atualizada.

Prefiro evitar a criação de um novo host para isso, e prefiro muito mais resolver isso com PTYs onde estiverem disponíveis.

Aqui está uma solução alternativa por enquanto - a única coisa que aparece é uma instância do PowerShell na barra de tarefas que desaparece rapidamente - chega de conhost.exe piscando na tela.

$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

Indivíduos empreendedores podem combinar esta técnica com psexec.exe -i para executar scripts remotamente na sessão de usuários atualmente conectados.

  • Isso ainda abre uma janela rápida visível em meus sistemas
  • Eu tentei o silentCMD acima, mas isso requer net3.5 que não está instalado em alguns dos sistemas de terceiros em que o executo

Não parece haver uma solução, eu acho

Você verificou o meu projeto GitHub de console oculto de execução?
Usei intencionalmente os requisitos mais baixos possíveis. Deve funcionar em quase todas as versões do Windows

Como @Ciantic mencionou, a melhor maneira de contornar esse problema é usar um script VB:

Em, diga ps-run.vbs put

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

Em seguida, use-o para executar o comando que você deseja, por exemplo, a partir de tarefas agendadas do Windows como este

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

Eu uso algo assim para executar uma tarefa com frequência sem ver nenhuma janela piscando.

Você verificou o meu projeto GitHub de console oculto de execução?
Usei intencionalmente os requisitos mais baixos possíveis. Deve funcionar em quase todas as versões do Windows

Eu tentei esta semana e funciona sem surgir requisitos net3.5. Obrigado! Agradável. Manterá o VBS em mente.

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? O que é isso?

Envoyé de mon iPhone

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

Prefiro evitar a criação de um novo host para isso, e prefiro muito mais resolver isso com PTYs onde estiverem disponíveis.

-
Você está recebendo isto porque está inscrito neste tópico.
Responda a este e-mail diretamente, visualize-o no GitHub ou ignore a conversa.

Versão simplificada do VBScript de @Roy-Orbison:

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

Testado em minha máquina com um script no qual estou trabalhando, parece funcionar quando executado com wscript no prompt do PS ou tarefa agendada.

Positivo:

  • Não é necessário colocar o caminho do script na linha de comando wscript .
  • Não define ExecutionPolicy para Bypass .

Desvantagens:

  • Precisa de scripts VBScript separados para cada comando do PowerShell.

Eu pessoalmente prefiro a solução VBScript a RunHiddenConsole , uma vez que não envolve a implantação de um executável não assinado em um diretório do sistema. No entanto, ter um pwshw.exe / powershellw.exe oficial obviamente seria preferível a ambos.

Eu pessoalmente prefiro a solução VBScript a RunHiddenConsole , uma vez que não envolve a implantação de um executável não assinado em um diretório do sistema.

assinar não deve ser um grande negócio. você pode até fazer isso sozinho com um pouco de esforço para construí-lo sozinho
ps: também adicionei a opção de implantar a ferramenta ao lado dos scripts que você deseja executar. então não é mais necessário configurá-lo no sistema próximo ao executável do PowerShell

É bom ter soluções alternativas e uma solução de terceiros, mas para enfatizar o último comentário de @alexbuzzbee :

É necessária uma solução que _vinda com PowerShell_.


Quanto às soluções alternativas: observe que uma solução baseada em VBScript é possível até mesmo sem um arquivo de script auxiliar, mas é misterioso:

O seguinte, que você pode executar na caixa de diálogo Run (ou cmd.exe ), cria uma instância invisível do PowerShell que exibe uma caixa de mensagem (sem mostrar uma janela de console):

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

Advertência : @alexbuzzbee observa que "[esta] solução gera alertas no sistema Defender ATP Endpoint Protection [...] então pode não ser adequada em um ambiente corporativo".

Não seria razoável transformar a solução da @Vittel na solução oficial? Não deve ser difícil mover o código para o repositório do PowerShell, modificá-lo para iniciar apenas powershell.exe ou pwsh.exe e construí-lo / distribuí-lo com o PowerShell.

.NET Core 3.0 oferece suporte à construção de winexe, que não mostra o console. Já tenho um protótipo funcionando, só preciso limpá-lo como PR.

Eu já tenho um protótipo funcionando

Eu também estava a caminho :-) Espero que você simplifique CommandLineParameterParser (remover EarlyParse?).

A solução de @ mklement0 gera alertas no sistema Defender ATP Endpoint Protection (não gosta de mshta executando o código do PowerShell), portanto, pode não ser adequado em um ambiente empresarial.

Obrigado, @alexbuzzbee , adicionei sua advertência ao meu comentário anterior. Acho que é realmente a chamada VBScript CreateObject() / JScript new ActiveXObject() que dispara o alerta; aparentemente, mshta.exe foi usado em malware no passado.

@ mklement0 ATP parece suspeitar especificamente de mshta começando pwsh , em vez da chamada CreateObject() .

É bom saber, @alexbuzzbee.

Baseei meu comentário no fato de que executar o seguinte (por exemplo, de cmd.exe ) produz um Access is denied error. e dispara um alerta do Windows Defender.

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

O resultado final é que a solução alternativa provavelmente é tirar proveito de uma brecha, que - como você relatou - pode acionar o software de segurança existente e, talvez, ser totalmente fechada no futuro.

Oba pela tentativa de @ SteveL-MSFT de implementar uma solução adequada.

@ SteveL-MSFT, 20/02/2018

Eu apoiaria uma contribuição da comunidade para adicionar pwshw.exe

@ SteveL-MSFT, 31/10/2019

.NET Core 3.0 oferece suporte à construção de winexe, que não mostra o console. Já tenho um protótipo funcionando, só preciso limpá-lo como PR.

Isso já faz muito tempo e será maravilhoso para scripts, especialmente com o Agendador de tarefas (talvez cron?), Etc. Como o PowerShell Core é multiplataforma , isso também funcionará em outras plataformas compatíveis? Que tal WSL?

O protótipo winexe funcionou, mas é muito áspero nas bordas para torná-lo 7.0. Por exemplo, se você cometeu um erro com os argumentos da linha de comando, você não saberá, pois não há janela de saída. Se seguirmos outras ferramentas como wscript.exe, devemos mostrar uma caixa de diálogo com a mensagem de erro apropriada.

Quanto ao não Windows, Linux e macOS não precisam do equivalente a winexe, pois acredito que o processo pwsh pode ser iniciado sem criar uma janela de console, enquanto o Windows exige porque ele diferencia explicitamente entre aplicativos de console e windows. Você certamente pode usar o pwsh com o Agendador de tarefas hoje ou cron, etc ... já.

Ainda outra versão do shim VBScript com aprimoramento: suporte a passagem de argumentos para o script Powershell. Isso nos dará mais flexibilidade no script a ser chamado. Tudo sem janela pop-up!

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

Por exemplo, eu tenho um script do PowerShell ouvindo um evento específico do Windows, uso o Agendador de Tarefas para extrair dados do evento e chamo um script do PowerShell para enviar notificação sobre o evento. Eu criei uma tarefa agendada personalizada com um EventTrigger personalizado (consulte uma postagem da 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>

Depois disso, poderíamos usar a variável $(Path) $(ProcessName) $(User) dentro da ação do evento. Para este caso, poderíamos chamar o script conforme abaixo. O Windows chamará meu notifier.ps1 sempre que um evento for acionado.

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

O powershell.vbs é absolutamente reutilizável. 😏

Original: https://github.com/PowerShell/PowerShell/issues/3028#issuecomment -522375489

Como @Ciantic mencionou, a melhor maneira de contornar esse problema é usar um script VB:

Em, digamos ps-run.vbs put

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

Em seguida, use-o para executar o comando que você deseja, por exemplo, a partir de tarefas agendadas do Windows como este

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

Eu uso algo assim para executar uma tarefa com frequência sem ver nenhuma janela piscando.

Você pode usar o QB64 para criar um pequeno EXE para ocultar o script. QB64 é um interpretador C ++ que pega o código QBASIC e o compila em um exe C ++. Se você usar os comandos _SHELLHIDE ou SHELL _HIDE , poderá chamar um script do PowerShell de dentro do EXE sem nunca mostrar uma janela do PowerShell. Eu uso isso em conjunto com -WindowStyle Hidden apenas por segurança, mas nunca tive problemas com isso. Exemplo: SHELL$ = "PowerShell -WindowStyle Hidden -ExecutionPolicy Bypass " + CHR$(34) + "&'" + _STARTDIR$ + "\GetNewDate.ps1';exit $LASTEXITCODE" + CHR$(34): a = _SHELLHIDE(SHELL$)
Você também pode ocultar todo o EXE que compilou usando $SCREENHIDE para que eles não tenham que ver nenhuma parte do programa.
Se você tiver um código de saída que deseja passar de volta para uma área diferente do código, pode usar exit $LASTEXITCODE ao chamar o script do PowerShell para passá-lo de volta ao EXE QB64. Se você deseja passar o código do EXE QB64, você pode usar o comando SYSTEM seguido pelo código que deseja passar de volta para o resto do seu programa / script. Espero que isso ajude alguém.

Usando isso agora para que cada invocação obtenha todos os argumentos, em vez de cada argumento ser um script separado, como o de @ttimasdf , mas usando uma matriz simples:

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

Eu mantive o -ExecutionPolicy Bypass porque obtenho falhas silenciosas, a menos que também use Set-ExecutionPolicy . Mal posso esperar por pwshw.exe .

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

@ Roy-Orbison
Ai está. Só preciso renomear 😉😅
(Srsly. Chame-o de pwshw.exe, coloque-o em seu caminho e ele deve funcionar)

Realmente não sei o que leva tanto tempo para a equipe pwsh.
Não é um grande negócio

Realmente não sei o que leva tanto tempo para a equipe pwsh.

Falta de recursos. Precisamos de mais revisores e colaboradores de código.

Eu configurei um script do PowerShell para ser executado no Elgato Stream Deck e ele abre uma janela. Tentei usar -Noninteractive e -WindowStyle hidden , mas ainda aparece brevemente.

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

Espero ter pwshw na próxima prévia.

Eu configurei um script do PowerShell para ser executado no Elgato Stream Deck e ele abre uma janela. Tentei usar -Noninteractive e -WindowStyle hidden , mas ainda aparece brevemente.

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

Você poderia facilmente contornar esse pop-up usando a ferramenta que postei acima. Usando-o todos os dias com meu deck de vapor e scripts de inicialização

Para sua informação: Na equipe do console, estamos propondo uma maneira para aplicativos futuros (e versões futuras de aplicativos existentes) lidar com isso. Haveria uma pequena sobrecarga [1], mas daria ao PowerShell a capacidade de _escolher se aloca uma janela de console_ quando iniciado em um contexto de GUI.

Solicitação de pull de especificação: https://github.com/microsoft/terminal/pull/7337

@DHowett estou tão feliz por saber disso antes de fundir meu RP! Seria melhor para o cliente ter um único exe e não se preocupar com as versões winexe e muito menos com os custos de manutenção para a equipe.

Mas e se eu estiver chamando o PowerShell sem o Terminal do Windows? Por exemplo, estou chamando pwsh.exe diretamente do Elgato Stream Deck. A opção proposta pela equipe do Terminal não resolveria este cenário, ou outros semelhantes, resolveria?

@ pcgeek86 não se deixe enganar pelo nome! Minha equipe e eu possuímos todo o subsistema do console do Windows, incluindo como os aplicativos do console são iniciados e conversam entre si.

@DHowett Presumo que isso significa que a funcionalidade só estará disponível em versões futuras do Windows? Então, alguém que ainda usa versões de nível inferior do Windows está essencialmente sem sorte? 🤔

Um aplicativo que está no subsistema do console com um consoleAllocationPolicy de inheritOnly não apresentará um console quando iniciado a partir do Explorer .

Qual é o comportamento do Agendador de tarefas?

@DHowett para pwsh, precisaria de um sinalizador para especificar que queremos um conpty alocado para que os scripts que chamam APIs de console ainda funcionem

Aplicativos como o PowerShell podem desejar reter a alocação "automática" do console e o inheritOnly não seria adequado para eles.

Portanto, a política não resolve todos os cenários do PowerShell e o PowerShell deve usar uma solução alternativa novamente?

Isso me lembra do meu PR, onde tentei usar diretamente o AllocConsole.

nível inferior (@ vexx32)

Infelizmente, essa é uma limitação de tudo o que minha equipe produz que faz parte do subsistema do console e não pode ser fornecido como parte do Terminal. Estamos tentando trabalhar nisso 😉

Qual é o comportamento do Agendador de Tarefas (@iSazonov)

Dizer "Explorer" era uma maneira conveniente de dizer "qualquer contexto que ainda não tenha um console" com menos palavras. Fique tranquilo, _qualquer coisa que inicie um aplicativo inheritOnly sem um console não causará a alocação de um console._

Precisaria de um sinalizador para especificar (@ SteveL-MSFT)

Felizmente, o PowerShell já tem isso na forma de WindowStyle . O modo padrão pode ser "_i deve chamar AllocConsole() _" (que atenderá todas as necessidades da API do console!), A menos que o usuário solicite uma inicialização oculta. A especificação apenas move a responsabilidade de alocar um console para (pwsh) para que ele possa obter o controle final sobre se há um conhost. Uma vez que o PowerShell já está configurado para lidar com este caso, são apenas algumas linhas delta antes / depois da verificação "oculta".

não resolve todos os cenários do PowerShell (@iSazonov)

A especificação explica ainda como o PowerShell lidaria com isso (veja acima, minha resposta a Steve). Pelo que entendi, isso resolve _todos os cenários mencionados neste problema e problemas vinculados._

A principal diferença entre chamar AllocConsole() / AttachConsole() como você fez em seu PR e chamar AllocConsole() quando seu aplicativo é manifestado para uma política de alocação de console diferente é que o bit do subsistema indica que o shell de geração (cmd, pwsh, bash, ish) deve _esperar_ para que o shell gerado ( pwshw ) saia, o que reduz a interferência nas alças de I / O do console.

Se você tiver um aplicativo de subsistema do Windows que chama AttachConsole() para voltar ao console de hospedagem, o shell de spawn e o novo aplicativo vão lutar para ver quem lê a entrada / grava a saída. É por isso que chamar Attach _nunca_ pode ser trabalhado em um aplicativo de subsistema do Windows, a menos que você possa controlar totalmente o shell que o gerou (você não pode.)

Obrigado @DHowett ! Para deixar claro, a proposta do PowerShell é usar SUBSYSTEM_GUI e inheritOnly?

Acredito que SUBSYSTEM_CUI e inheritOnly seriam corretos para PowerShell. Ele oferece os seguintes comportamentos:

  1. cmd ( $SHELL ) esperará que o pwsh saia antes de retornar ( SUBSYSTEM_CUI )
  2. quando você o executa a partir do explorer / tasksched, o pwsh pode tomar a decisão sobre a criação de uma nova janela do console ( inheritOnly )
  3. ao executá-lo em cmd / pwsh / (um shell de console), o pwsh receberá automaticamente uma janela de console

quando você o executa a partir do explorer / tasksched, o pwsh pode tomar a decisão sobre a criação de uma nova janela do console (inheritOnly)

Hmm, como o PowerShell poderia saber que é o proprietário do processo - explorador ou tarefa?

Não acredito que precise saber.

Aqui está o motivo (C ++):

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

O PowerShell já sabe se deve gerar uma janela com base na solicitação do usuário para não fazê-lo. Esse recurso já existe - e, portanto, esta é a alteração incremental mínima no código que corrige esse bug _and_ mantém o comportamento original para todos os outros casos de uso.

Isso fornece uma boa plataforma para construir novos comportamentos.

@DHowett como @ vexx32 mencionou, ainda há muitos Server 2012 / R2 e 2016 à solta, então, embora para as variantes do sistema operacional Win10 e Server 2019, isso parece ótimo daqui para a frente, acho que para o PowerShell precisaríamos pensar em uma maneira em torno disso que é mais elegante do que a solução sugerida atualmente @ SteveL-MSFT

A menos que você também possa transportar essa mudança para o sistema operacional de nível inferior como parte de um patch de segurança, já que você não está fazendo atualizações de recursos para eles (o que duvido muito que faça)

que o bit do subsistema indica que o shell de geração (cmd, pwsh, bash, ish) deve esperar que o shell gerado (pwshw) saia, o que reduz a interferência nas alças de E / S do console.

Deve funcionar para PowerShell também. Quero dizer, se o PowerShell chamar um aplicativo de console externo, ele também deverá seguir a nova política. O PowerShell obterá isso automaticamente ou precisamos adicionar algo no PowerShell?

O PowerShell teria que aceitar conforme mencionado nas especificações. Você levantou um ponto importante: eu acredito que os aplicativos gerados _por_ um aplicativo "somente herdado" abrirão janelas de console pop-up, e isso é _terrível_. Vou revisitar isso nas especificações, porque acredito que sei como podemos resolver isso.

A menos que você também possa portar essa mudança para o sistema operacional de nível inferior

Temos que concluir o recurso antes mesmo de avaliá-lo para backporting 😉 mas concordo 100% que isso limita sua utilidade.

Só quero dizer que se você estiver iniciando o PowerShell de outro programa, há uma chance de que ele suporte a ocultação de processos filho. Por exemplo, Autohotkey tem um sinalizador "Ocultar" para o comando de execução.

Esta página foi útil?
0 / 5 - 0 avaliações

Questões relacionadas

SteveL-MSFT picture SteveL-MSFT  ·  3Comentários

HumanEquivalentUnit picture HumanEquivalentUnit  ·  3Comentários

JohnLBevan picture JohnLBevan  ·  3Comentários

rkeithhill picture rkeithhill  ·  3Comentários

pcgeek86 picture pcgeek86  ·  3Comentários