Powershell script strange behaviour when invoked from CMD/CLI

天涯浪子 提交于 2020-04-11 07:40:14

问题


This scripts works fine when executed from Powershell console...
but does not work when executed with Powershell.exe from CMD.exe...
(powershell.exe -file script.ps1, using 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" );

I tested other GUI objects (Winforms & WPF)
and they work fine...

?any ideas...


回答1:


Seems like it has to wait for the graphics to finish. "get-childitem | out-gridview" does a similar thing. Or add "sleep 120" to the end of the script, or find some other way to wait. Killing the script kills the window.

powershell -noexit .\explorer.ps1



回答2:


The problem is that the in-process COM object you're creating goes out of scope when the calling process exits, which in your case, when called from cmd.exe via PowerShell's CLI, means that the window typically never even gets a chance to display or is automatically closed after a very brief appearance.

  • In an interactive PowerShell session, the process lives on after exiting the script - that's why your code works there.

  • When you invoke a script via via PowerShell's CLI (powershell.exe for Windows PowerShell, pwsh for PowerShell Core, without the -NoExit switch to keep the process alive indefinitely), the PowerShell process exits when the script terminates.


Use of -NoExit would be a stopgap at best, because it would keep the PowerShell process around indefinitely, even though you presumably want it to live only for as long as the Properties dialog window is open - whenever the user chooses to close it.

Therefore, you need to synchronously wait for (a) the Properties dialog window to open and then (b) wait for it close before exiting the script.

You can do this with the help of the .NET UI Automation library as follows; note that the code uses PowerShell v5+ syntax:

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.

Now, invoking your PowerShell script as follows from your batch file will pop up the Properties dialog and wait for it to close before continuing:

@echo off

::  # ... your batch file

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

::  # ...

If, by contrast, you simply want to launch the Properties dialog while continuing to run your batch file (be sure to disable the verbose messages first):

:: # Only *initiate* display of the Properties dialog and *continue execution*.
start /B powershell.exe -file script.ps1


来源:https://stackoverflow.com/questions/58293133/powershell-script-strange-behaviour-when-invoked-from-cmd-cli

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!