Проблема в том, что создаваемый внутрипроцессный 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