2016-03-10 1 views
3

Скажем, у меня есть простой объем, который книга состава с Push-Location и Pop-Location:Как автоматически вызывать Pop-Location в конце объема

Function MyFunction($Location) 
{ 
    Push-Location $Location 
    # do other stuff here 
    Pop-Location 
} 

Есть ли способ, чтобы установить его в начале области, так что мне не нужно забывать поставить Pop-Location в конце? Что-то вроде этого:

Function MyFunction($Location) 
{ 
    Setup-BothPushAndPopHere $Location 
    # do other stuff here 
    # at the end of the scope, Pop-Location is automatically called 
} 

ответ

6

Короткий ответ: Нет

Мое взятие на Push-Location и Pop-Location является то, что вы должны вообще избегать их, и адаптировать сценарий использовать имена путей в командах вместо; Другими словами, вместо того, чтобы:

Push-Location $Location 
Get-ChildItem 
Pop-Location 

Вобще:

Get-ChildItem $Location 

(упрощенный пример)

Если вы должны использовать шаблон, рассмотрим try/finally:

Push-Location $Location 
try { 
    # ... 
} finally { 
    Pop-Location 
} 

Так как это помогает с неожиданными исключениями или пользователь, прерывающий прог ram исполнение.

Обычно я использую шаблон try/finally, когда код находится вне моего контроля; чаще всего при загрузке модуля SQLPS, поскольку он меняет текущее местоположение на поставщика SQL-сервера, который по моему опыту приводит к тому, что все, что использует текущее местоположение, становится намного медленнее.

Как указывает Eris, это также полезно при работе с родными приложениями. Это может быть особенно актуально, если больно избегать цитат вокруг имен путей с пробелами или приложение не будет обрабатывать его правильно в любом случае.

+0

Я думаю, что лично я бы использовал структуру BEGIN {} PROCESS {} END {}. Это только стилистический выбор с моей стороны. – EBGreen

+0

Я использую версию 'try/finally' довольно много. Это намного чище, чем добавление аргумента папки к * каждой * команде, которую я хочу запустить в этой папке. – Eris

+0

@ EBGreen это больше, чем стилистический выбор; это может кардинально изменить выполнение. Может потребоваться нажимать и нажимать на каждый элемент конвейера, который потребовал бы, чтобы все были в блоке 'process'. И в этом случае 'try' /' finally' все еще может быть действительным. Трудно учитывать исключения или прерывания конвейера с этим шаблоном, если 'begin' и' end' имеют смысл для 'push' и' pop'. Это не решительное решение, имо. – briantist

0

В зависимости от того, что вы пытаетесь сделать в коде #do other stuff here, вы можете попробовать выполнить эти команды как блок сценария в дочернем процессе. Пример из каркасно-код:

$ScriptBlock = { 
    Push-Location $Location 
    #commands 
} 

$Job = Start-Job -ScriptBlock $ScriptBlock # Add other arguments if needed 

# Check the status of the task: 
Get-Job $Job 

# Wait for the job state to be 'Completed' (do-while, maybe?) 

# If your ScriptBlock writes any output, collect in a variable: 
$Output = Receive-Job $Job 

# Clean up: 
Remove-Job $Job 

Суть этого подхода заключается в том, что вы икру на работу, чтобы сделать работу (в фоновом режиме), и вам не нужно беспокоиться о том, как Pop-Location вы просто позволить этому ребенку области видимости выход то время как вы продолжаете делать все, что вам нужно сделать в своем главном скрипте.

На StackExchange есть другие сообщения, которые более подробно расскажут о .

Смежные вопросы