2010-11-17 12 views
6

Я по существу хочу создать переменную, которая будет выполняться каждый раз. Для простейшего примера:Возможно ли создать собственную «автоматическую переменную»?

$myvar = `write-host foo`; 

Тогда каждый раз, когда я ссылаться $ MyVar, он будет выводить Foo:

dir $myvar 

Directory of foo: 

Точка того, что write-host foo часть будет повторно выполняться каждый раз, когда я ссылаться на $ MyVar

+1

Почему бы не использовать метод? http://www.computerperformance.co.uk/powershell/powershell_functions.htm – asawyer

+0

В вашем примере dir $ myvar не будет работать, потому что write-host не будет выводиться для dir. Вы хотите написать-вывод, но вам это действительно не нужно, вам просто нужно '$ myvar = 'foo'' – Jaykul

ответ

5

Это можно сделать в управляемом коде (C#/VB), создав собственный собственный производный класс PSVariable, но не напрямую в чистом сценарии, извините. Я говорю «чистый сценарий», потому что в powershell v2 вы можете встроить C# с добавлением. Тем не менее, вы можете взломать его в сценарии, полагаясь на неявные вызовы ToString, но это не будет надежным в любой ситуации. Пример:

# empty custom object 
$o = new-object psobject 

# override ToString with a PSScriptMethod member 
$o.psobject.members.add((new-object ` 
    System.Management.Automation.PSScriptMethod "ToString", { 
     "ticks: $([datetime]::now.ticks)" })) 

ps> $o 
ticks: 634256043148813794 

ps> $o 
ticks: 634256043165574752 

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

function Ticks { [datetime]::now.ticks } 

# use as a parameter - note the use of (and) 
ps> write-host (ticks) 
634256043148813794 

# use in a string - note the use of $(and) 
ps> write-host "ticks $(ticks)" 
ticks 634256043165574752 

Надеется, что это помогает

-Oisin

+1

Мне нравится, что вы думали об использовании переопределения ToString для этого. Если вы пойдете так, убедитесь, что вы создали переменную ReadOnly, Constant, AllScope, чтобы она не могла быть перезаписана, и помните, что это только при преобразовании ее в строку. В противном случае это нечто другое. x0n: Ты больной, больной гений :) – Jaykul

+0

Это по какой-то причине не работает так же, как автоматическая переменная, но действительно близко. Например: «dir c: \; dir $$» будут делать то же самое. Но с вашим методом выше «dir c: \; dir $ o» нет. Это требует, чтобы я делал «dir c: \; dir ($ o)», который вызывает раздражение: P – esac

+0

для записи: $$ похож на $ o в моем примере (который я только что добавил ниже), он не вычисляется по требованию , он устанавливается после запуска каждой команды. Я хотел сказать об этой альтернативе вчера, но я отвлекся. – Jaykul

2

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

$MySecretOldPromptStorage = ${Function:Prompt} 
function prompt { $o = $([datetime]::now.ticks); &$MySecretOldPromptStorage } 

конечно, это приводит к его запустить каждый раз, а не по требованию

2

Не так сложно завершить то, что @ x0n упоминает. Мы можем вставлять кусок C# в наш код и получить реальную автоматическую переменную:

# define a class of my variable, override the Value property 
Add-Type @' 
using System; 
using System.Management.Automation; 
public class MyVariable : PSVariable 
{ 
    public MyVariable(string name) : base(name) {} 
    public override object Value 
    { 
     get { return DateTime.Now.Ticks; } 
     set { } 
    } 
} 
'@ 

# install the variable 
$ExecutionContext.SessionState.PSVariable.Set((New-Object MyVariable Ticks)) 

# test 
$Ticks 
sleep 1 
$Ticks 
sleep 1 
$Ticks 

О PSVariable:

http://msdn.microsoft.com/en-us/library/system.management.automation.psvariable