2016-04-14 3 views
4

Microsoft.PowerShell_profile.ps1 Используемый мной сценарий создает много переменных при запуске. Я задал всю область переменных «Script», но переменные, используемые в скрипте, никогда не выходят за рамки.Сценарии профилей Powershell dot-sourced?

Я хотел бы, чтобы переменные выходили за пределы области действия, как только скрипт выполняется, и управление передается мне.

Если я сравниваю количество глобальных, локальных и скриптовых переменных, которые у меня есть, я получаю одинаковое число.

Пример:

# Profile script does what it does. 

Get-Variable -Scope Global | Measure-Object 
Get-Variable -Scope Local | Measure-Object 
Get-Variable -Scope Script | Measure-Object 

Output: 
60 
60 
60 

В настоящее время я захватывая снимок переменных в начале моего профиля сценария, а затем удаление любых новых переменных в конце.

Пример:

$snapshotBefore = Get-Variable 
$profileVar1 = 'some value' 
$profileVar2 = 'some other value' 
$snapshotAfter = Get-Variable 

# Compare before and after, and create list of new variables. 

Remove-Variable $variablesToRemove 
+0

Я не уверен в вашей цели. Зачем устанавливать области видимости переменных в 'script'? –

+0

@Bill_Stewart: Цель состоит в том, чтобы использовать временные переменные внутри профиля, которые не должны задерживаться после завершения загрузки профиля. – mklement0

+1

Ах. Да, профили PowerShell являются точками. –

ответ

2

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

К сожалению, нет никакой возможности модификатора, который позволяет создавать временную область для переменных, которые вы только хотите, чтобы существовать в то время как профиль нагрузка - даже сфера local эффективно глобальный профильный сценарий; аналогично, использование области private также не является вариантом, поскольку область действия этого профиля - из-за того, что точка-источник - - это глобальный охват.

Вообще говоря, вы можете использовать & (оператор вызова) с блоком сценария для создания переменных внутри этого блока, которые контекстные к этому блоку, но это, как правило, расходится с созданием доступных глобально определений в профиле, по крайней мере, по умолчанию.
Аналогичным образом, вызов другого сценария без использования точек доступа, как и в вашем собственном ответе, по умолчанию не будет определять его определения по всему миру.
You может, однако, создавать глобальные элементы из , не -dot-источников блоков скрипта/сценария, указав глобальный масштаб явно; например: & { $global:foo = 'Going global' }, или & { function global:bar { 'global func' } }.

Это говорит, Обоснование профилей дота-сорсинг, вероятно, что это легче сделать все определения глобального по умолчанию, что делает определение типичных элементов профиля - псевдонимы, функции привода отображений, загрузка модулей - проще (нет необходимости указывать явную область).
В отличие от этого, глобальные переменные менее типичны, и для определения типичных элементов, перечисленных выше, обычно вам не нужны переменные типа скрипта (и, следовательно, глобальные) в вашем профиле.


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

простой обходной путь - используйте префикс имени экзотической переменной, такой как __ внутри сценария профиля, чтобы уменьшить риск их обращения по ссылке (например, $__profileVar1 = ...).
Другими словами: переменные все еще существуют
глобально, но их экзотические имена обычно не вызывают проблем.

Однако вашего подход, даже если это требует немного дополнительной работы, звучит как прочные обходной, вот как это выглядит в полном объеме (с использованием PSv3 + синтаксис):

# Save a snapshot of current variables. 
# * If there are variables that you DO want to exist globally, 
# define them ABOVE this command. 
# * Also, load MODULE and dot-source OTHER SCRIPTS ABOVE this command, 
# because they may create variables that *should* be available globally. 
$varsBefore = (Get-Variable).Name 

# ... define and use temporary variables 

# Remove all variables that were created since the 
# snapshot was taken, including $varsBefore. 
Remove-Variable (Compare-Object $varsBefore (Get-Variable).Name).InputObject 

Обратите внимание, что Я полагаюсь на поведение Compare-Object по умолчанию только для сообщения разницы между объектами и, если вы еще не пробовали удалить любые переменные, только переменные добавлены. сообщили.


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

Вот фрагменты из различных разделов справки (по состоянию на PSv5), которые обеспечивают ключи (курсив мой):

От Get-Help about_Profiles:

профиль

под управлением Windows PowerShell скрипт, который запускается при Windows PowerShell начинается. Вы можете использовать профиль в качестве сценария входа в систему, чтобы настроить среду . Вы можете добавлять команды, псевдонимы, функции, переменные, оснастки, модули и диски Windows PowerShell. Вы также можете добавить в свой профиль другие элементы, относящиеся к сеансу, чтобы они были доступны на каждом этапе без необходимости их импорта или воссоздания.

От Get-Help about_Variables:

По умолчанию переменные доступны только в области, в которой они созданы.

Например, переменная, которую вы создаете в функции, - это , доступная только внутри функции. Переменная, которую вы создаете в скрипте, доступна только в скрипте (, если только вы не используете сценарий, который добавляет его в текущую область действия).

От Get-Help about_Operators:

. Оператор Dot sourcing Запускает скрипт в текущей области действия, чтобы любые функции, псевдонимы и переменные, созданные сценарием, добавлены в текущий .

От Get-Help about_Scopes

Но вы можете добавить скрипт или функцию в текущей области с помощью дот источника обозначения. Затем, когда сценарий запускается в текущей области, любые функции, псевдонимы и переменные, которые создает скрипт, доступны в текущей области.

Чтобы добавить функцию в текущую область действия, введите точку (.) И пробел до путь и имя функции в вызове функции.

+0

Благодарим вас за ответ и за исправление ответа, чтобы лучше ответить на вопрос. Вы проделали хорошую работу. Позвольте мне указать на один вопрос, который я нашел в своем предыдущем обходном пути (используя моментальные снимки и Compare-Object). Когда я загрузил модуль и создал глобальную переменную. Эта переменная позже будет удалена этой операцией. Вот почему я искал «лучший способ» сделать это, и надеялся, что правильная область обзора решит его. Еще раз спасибо! –

+0

также мне было любопытно, если бы у вас был источник для вашего первого абзаца ** «Профили PowerShell разработаны с точки зрения дизайна, потому что это позволяет глобально доступным определениям, содержащимся в них (псевдонимы, функции ...)» * *. –

+0

Спасибо за загрузку модулей с указателем - я обновил ответ с оговоркой. Вы все еще можете использовать эту технику, вам просто нужно аккуратно поместить команду смены моментального снимка после загрузки модулей и поиска других источников. Мне также интересно, что вы на самом деле делаете в своем профиле, если он работает для вас, чтобы просто вызвать другой скрипт с '&', который не может создать элементы _global_. – mklement0

0

Таким образом, это звучит как Powershell dot-sources профиля. Я не мог найти ресурс, который конкретно говорит об этом, или другие форумы, которые задали этот вопрос.

Я нашел ответ и хотел его опубликовать здесь.

Я изменил свой профиль, чтобы вызвать файл сценария. Скрипт теперь имеет свою область видимости, и пока переменные не становятся глобальными, они будут выходить за пределы области действия после завершения загрузки профиля.

Так что теперь мой профиль одна линия:

& (Split-Path $Path $profile -Parent | Join-Path "Microsoft.PowerShell_profile_v2.ps1") 

Microsoft.PowerShell_profile_v2.ps1 теперь может содержать правильную сферу:

$Global:myGlobalVar = "A variable that will be available during the current session" 
$Script:myVar = "A variable that will disappear after script finishes." 
$myVar2 = "Another variable that will disappear after script finishes." 

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

Мне все равно было бы интересно, почему Microsoft решила назвать профиль таким образом. Если кто-то знает и хотел бы поделиться. Мне бы хотелось увидеть ответ здесь.

+1

mklement0 уже предоставил ответ на ваш вопрос. Профили распределены по точкам, поэтому определения доступны во всем мире. –

+0

Я начинаю видеть, откуда вы родом: вы фокусируетесь на глобальных _variables_, которые, однако, не являются типичным элементом для размещения в профиле; определение псевдонимов, функций и сопоставлений дисков, а также загрузка модулей/оснасток является более типичным. Таким образом, более удобно, чтобы эти элементы были глобальными _ по умолчанию_ - через dot-sourcing - чем указать область времени. И наоборот, возникает вопрос: почему у вас есть необходимость определять переменные уровня скрипта в вашем профиле? Чтобы создать типичные элементы, указанные выше, вам не нужны переменные уровня скрипта. – mklement0

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