суббота, 4 февраля 2012 г.

PowerShell: Запуск оконных приложений

В PowerShell консольные приложения запускаются синхронно, а оконные - асинхронно. Это означает, что если запущенное приложение является консольным, PowerShell не перейдёт к выполнению следующей команды, пока не будет завершена предыдущая. Если же приложение оконное - оно запускается в отдельном процессе и существует само по себе, не влияя на работу PowerShell который в это время переходит к выполнению очередной команды. Рассмотрим нюансы запуска оконных приложений из PowerShell. Предположим, что нам нужно запустить wordpad.

Вариант 1:
>PS C:\Users\user> & "C:\Program Files\Windows NT\Accessories\wordpad.exe"
Символ "&" перед полным строковым именем исполняемого файла указывает на то, что сделующую за ним строку следует трактовать как команду. Двойные или одинарные (смотря по обстоятельствам) кавычки необходимы, т.к. в пути содержатся пробелы. Для тех кто не в курсе, поясняю: если использовать двойные кавычки, то все имена переменных (определённых в PowerShell, а так же созданных нами), указанных в тексте, будут заменены их значениями. Если использовать одинарные кавычки - замена производиться не будет. Пример:
PS D:\> "Домашний каталог пользователя: $Home"
Домашний каталог пользователя: C:\Users\user

В строке переменная была заменена своим значением.
PS D:\> 'Домашний каталог пользователя: $Home'
Домашний каталог пользователя: $Home

Строка осталась без изменений.
Вариант 2:
PS C:\Users\user> cd "C:\Program Files\Windows NT\Accessories"
PS C:\Program Files\Windows NT\Accessories> .\wordpad
Наличие ".\" перед файлом необходимо (данное требование присутствует в PowerShell из соображений безопасности), а расширение файла можно не указывать.
Если развернуть свойство ярлыка, указывающего на файл wordpad.exe, то можно увидеть, что в пути используется системная переменная %ProgramFiles%. Однако, если мы просмотрим перечень переменных, доступных на диске "variable:", то увидим что переменной с таким именем там нет.

PS D:\> ls variable:
 
Name                           Value
----                           -----
$                              Домашний каталог пользователя: $Home
?                              True
^                              Домашний каталог пользователя: $Home
_
a                              C:\Program Files\Windows NT\Accessories\wordpad.exe
args                           {}
ConfirmPreference              High
ConsoleFileName
DebugPreference                SilentlyContinue
Error                          {Не удается найти путь "C:\Users\user\variable", так как он не существует., Имя "vari...
ErrorActionPreference          Continue
ErrorView                      NormalView
ExecutionContext               System.Management.Automation.EngineIntrinsics
false                          False
FormatEnumerationLimit         4
HOME                           C:\Users\user
Host                           System.Management.Automation.Internal.Host.InternalHost
input                          System.Collections.ArrayList+ArrayListEnumeratorSimple
LASTEXITCODE                   1
MaximumAliasCount              4096
MaximumDriveCount              4096
MaximumErrorCount              256
MaximumFunctionCount           4096
MaximumHistoryCount            64
MaximumVariableCount           4096
MyInvocation                   System.Management.Automation.InvocationInfo
NestedPromptLevel              0
null
OutputEncoding                 System.Text.ASCIIEncoding
PID                            5840
PROFILE                        C:\Users\user\Documents\WindowsPowerShell\Microsoft.PowerShell_profile.ps1
ProgressPreference             Continue
PSBoundParameters              {}
PSCulture                      ru-RU
PSEmailServer
PSHOME                         C:\Windows\System32\WindowsPowerShell\v1.0
PSSessionApplicationName       wsman
PSSessionConfigurationName     <a href="http://schemas.microsoft.com/powershell/Microsoft.PowerShell
PSSessionOption">http://schemas.microsoft.com/powershell/Microsoft.PowerShell
PSSessionOption</a>                System.Management.Automation.Remoting.PSSessionOption
PSUICulture                    ru-RU
PSVersionTable                 {CLRVersion, BuildVersion, PSVersion, WSManStackVersion...}
PWD                            D:\
ReportErrorShowExceptionClass  0
ReportErrorShowInnerException  0
ReportErrorShowSource          1
ReportErrorShowStackTrace      0
ShellId                        Microsoft.PowerShell
StackTrace                        в System.Management.Automation.CommandDiscovery.LookupCommandInfo(String commandNa...
true                           True
VerbosePreference              SilentlyContinue
WarningPreference              Continue
WhatIfPreference               False


Соответственно нам не удастся в пути к файлу использовать переменную $ProgramFiles (т.к. её нет в приведённом выше списке). В подобных ситуациях следует использовать синтаксис $env:ИмяПеременной, тем самым указывая PowerShell, что речь идёт о переменной операционной системы:
Вариант 3:
PS C:\Users\user> & "$env:ProgramFiles\Windows NT\Accessories\wordpad.exe"
В принципе, можно воспользоваться и средствами .NET (на любителя):
Вариант 4:
>PS C:\Users\user> & $([System.Environment]::ExpandEnvironmentVariables("%ProgramFiles%\Windows NT\Accessories\wordpad.exe"))
Наличие в данном выражении блока "$(...)" необходимо, т.к. этот синтаксис сообщает PowerShell о том, что сначала следует вычислить выражение, находящееся внутри этого оператора и уже затем результат передать далее (в нашем случае - "&").

Комментариев нет: