#powershell
#powershell
Вопрос:
Интересно, возможно ли удалить все переменные, используемые в текущем сеансе скрипта?
Try {
Write-Host "Scripting start...."
}
Catch {
Write-Warning -Message "[PROCESS] Something wrong happened"
Write-Warning -Message $Error[0].Exception.Message
}
Finally {
Remove-Variable *
[System.GC]::Collect()
}
Если нет, что я могу сделать в Finally
блоке?
Ответ №1:
Лучше всего называть вашу пользовательскую переменную некоторой энтропией, чтобы их было легко найти и удалить. Удаление ‘*’ удаляет все, независимо от того, когда / как это было создано, включая все переменные PS по умолчанию.
Не делайте этого.
При каждом запуске сеанса собирайте значения по умолчанию и автоматические значения в переменной, перед завершением сеанса сравнивайте эту коллекцию переменных с тем, что вы создали, и удаляйте только то, что вы создали.
Итак, в моем случае я бы использовал, скажем…
$panVariableName
… затем
Remove-Variable -Name 'pan*' -Force
Или, если вы не хотите делать это таким образом. При запуске сеанса сделайте это…
$AutomaticVariables = Get-Variable
… затем вы можете сравнить любые переменные, которые вы создаете, независимо от того, как вы их называете, чтобы получить свою коллекцию для удаления. Вот функция, которую я сохраняю в своем профиле модуля для таких случаев использования для очистки относительно этого подхода.
Итак, в моем профиле модуля это находится вверху…
$AutomaticVariables = Get-Variable
Затем, когда я буду готов, вызывается эта функция.
Function Clear-ResourceEnvironment
{
[CmdletBinding(SupportsShouldProcess)]
[Alias('cre')]
Param
(
[switch]$AdminCredStore
)
[System.GC]::Collect()
[GC]::Collect()
[GC]::WaitForPendingFinalizers()
Get-PSSession |
Remove-PSSession -ErrorAction SilentlyContinue
If ($AdminCredStore)
{Remove-Item -Path "$env:USERPROFILEDocumentsAdminCredSet.xml" -Force}
Else
{
Write-Warning -Message "`n`t`tYou decided not to delete the custom Admin credential store.
This store is only valid for this host and user $env:USERNAME"
}
Write-Warning -Message "`n`t`tRemoving the displayed session specific variable ojects"
Compare-Object -ReferenceObject (Get-Variable) -DifferenceObject $AutomaticVariables -Property Name -PassThru |
Where -Property Name -ne 'AutomaticVariables' |
Remove-Variable -Verbose -Force -Scope 'global' -ErrorAction SilentlyContinue
Remove-Variable -Name AdminCredStore -Verbose -Force
}
Ответ №2:
Я полагаю, вы можете использовать:
Clear-Variable * -Scope Global
или
Remove-Variable * -Scope Global
В качестве альтернативы, решит ли вашу проблему определение области действия процесса? Вы можете создать scriptblock
и вызвать его с помощью «оператора вызова» ( amp;
). Это позволило бы запустить процесс в ограниченной среде, отдельной от глобальной. Это выглядело бы примерно так:
$scriptBlock = {
Try {
Write-Host "Scripting start...."
}
Catch {
Write-Warning -Message "[PROCESS] Something wrong happened"
Write-Warning -Message $Error[0].Exception.Message
}
Finally {
[System.GC]::Collect()
}
}
amp;$scriptBlock
Вам не нужно было бы удалять-Variable, потому что после выполнения все, что происходило в области видимости в терминах переменных, уже исчезло.
Комментарии:
1. Привет @Andrew, спасибо за быстрый ответ. Итак, если я запускаю скрипт локально, будет ли применима оболочка $ ScriptBlock?
2. Да, должно быть жизнеспособным. Не совсем уверен, какие переменные вы очищаете, но должно сработать. На самом деле я не совсем уверен, создает ли это новую область для переменных $ Error. Возможно, вам придется протестировать это, если это одна из переменных, которые вы хотите очистить.
3. Спасибо, Эндрю, что я хотел бы очистить, так это все переменные, которые были созданы в рамках текущего выполнения скрипта.
4. Потрясающе, так что, если это есть в этом try / catch, тогда вы можете удалить их из оператора вызова с ограниченной областью действия (amp;). В противном случае другие параметры должны работать, если они вызваны в конце.