Странное поведение сценария Powershell при вызове из CMD / CLI - PullRequest
2 голосов
/ 08 октября 2019

Этот сценарий отлично работает при запуске из консоли Powershell ...
, но не работает при выполнении с Powershell.exe из CMD.exe ...
(Powershell 5.1.17763.771)

# display Windows Shell Folder propertes
$App  = New-Object -ComObject Shell.Application;
$AppNS = $App.NameSpace( "c:\windows" );
$AppNS.Self.InvokeVerb( "Properties" );

Я тестировал другие объекты GUI (Winforms & WPF)
, и они отлично работают ...

? Есть идеи ...

Ответы [ 2 ]

0 голосов
/ 09 октября 2019

Проблема в том, что создаваемый внутрипроцессный COM-объект выходит из области видимости, когда вызывающий процесс выходит из , что в вашем случае при вызове из cmd.exe через CLI PowerShell означает, чтоокно, как правило, даже не имеет возможности отображаться или автоматически закрывается после очень краткого появления.

  • В интерактивном сеансе PowerShell ,процесс продолжается после выхода из скрипта - вот почему наш код работает там.

  • Когда вы вызываете скрипт через PowerShell's CLI (powershell.exe для Windows PowerShell , pwsh для PowerShell Core , без переключателя -NoExit, чтобы поддерживать процесс в течение неопределенного времени), процесс PowerShell завершает работу после завершения сценария.


Использование -NoExit в лучшем случае будет временным промежутком, поскольку при этом процесс PowerShell будет удерживаться на неопределенно долго, хотя вы, вероятно,и чтобы он жил только до тех пор, пока открыто диалоговое окно Свойства - всякий раз, когда пользователь решает закрыть его.

Поэтому вам нужно синхронно ждать (а)откройте диалоговое окно Свойства и затем (b) дождитесь его закрытия перед выходом из сценария.

Вы можете сделать это с помощью библиотеки .NET UI Automation какследующим образом;обратите внимание, что в коде используется синтаксис PowerShell v5 +:

using namespace System.Windows.Automation

# Load the UI Automation client assemblies.
# Requires Windows PowerShell or PowerShell Core v7+ (on Windows only).
Add-Type -AssemblyName UIAutomationClient; Add-Type -AssemblyName UIAutomationTypes

# Initiate display of the Windows folder's Properties dialog.
$App = New-Object -ComObject Shell.Application
$AppNS = $App.NameSpace('c:\windows')
$AppNS.Self.InvokeVerb('Properties')

# Comment out this line to suppress the verbose messages.
$VerbosePreference = 'Continue'

Write-Verbose 'Wating for the window''s creation...'
do {
  # Search among the current process' top-level windows for a winow
  # with class name '#32770', which is what the Properties dialog windows
  # use (don't know why, but it has been stable over time).
  $w = [AutomationElement]::RootElement.FindFirst([TreeScope]::Children, 
    [AndCondition]::new(
      [PropertyCondition]::new([AutomationElement]::ClassNameProperty, '#32770'),
      [PropertyCondition]::new([AutomationElement]::ProcessIdProperty, $PID)
    )
  )
  Start-Sleep -Milliseconds 100
} while (-not $w)

Write-Verbose 'Window has appeared, waiting for it to close...'

while ($w.Current.ProcessId) {
  Start-Sleep -Milliseconds 100
}

Write-Verbose 'Window is now closed, moving on.'

# At this point, if the script was invoked via PowerShell's CLI (powershell.exe -file ...)
# the PowerShell process terminates.

Теперь при вызове сценария PowerShell, как показано ниже из вашего пакетного файла, появится диалоговое окно «Свойства» и дождитесь его закрытия , прежде чем продолжить:

@echo off

::  # ... your batch file

::  # Pop up the Properties dialog and *wait for it to close*.
powershell.exe -file script.ps1

::  # ...

Если, напротив, вы просто хотите запустить диалоговое окно Свойства, продолжая при этом запускать ваш пакетный файл (сначала обязательно отключите подробные сообщения):

:: # Only *initiate* display of the Properties dialog and *continue execution*.
start /B powershell.exe -file script.ps1
0 голосов
/ 09 октября 2019

Похоже, придется ждать окончания графики. get-childitem | out-gridview делает то же самое. Или добавьте «сон 120» в конец сценария, или найдите другой способ ожидания. Убийство сценария убивает окно.

powershell -noexit .\explorer.ps1
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...