Я пытаюсь написать модуль PowerShell на основе командлета для нашего приложения. После командлета начального подключения я хочу где-то хранить значения, пока у пользователя открыто текущее окно PowerShell. Одним из значений является ключ аутентификации, который я создаю из учетных данных пользователя, а затем он требуется для будущих вызовов без предоставления учетных данных для каждого действия.
Я думал, что это может быть легко получить и установить их в пользовательском объекте из С#, но я изо всех сил пытаюсь заставить его применяться к текущему пространству выполнения. Признаюсь, я тоже новичок в C#.
Вот пример моей самой успешной попытки в минимальной форме, т.е. это будет оценено как истина, однако это не то же самое пространство выполнения. Если я вызову $item в PowerShell, он, очевидно, не знает, о чем я говорю.
using System.Management.Automation.Runspaces;
namespace Test
{
public class VariableTest
{
public bool CreateVariable()
{
var runSpace = RunspaceFactory.CreateRunspace();
runSpace.Open();
runSpace.SessionStateProxy.SetVariable("item", "FooBar");
var a = runSpace.SessionStateProxy.PSVariable.GetValue("item");
if (a.ToString() == "FooBar")
{
return true;
}
else
{
return false;
}
}
}
}
Если бы я писал этот модуль в PowerShell, я бы, наверное, просто сохранил их в глобальной переменной. Может ли кто-нибудь помочь с получением и установкой этих значений, чтобы я мог вызывать элемент в консоли PowerShell? Или это ужасно неправильно, и что-то уже существует для учета постоянных переменных модуля в C#, которые я пропустил.
Предполагая, что ваш командлет Connect-*
наследует PSCmdlet
, вы можете получить доступ к переменным через this.SessionState.PSVariable
:
[Cmdlet("Connect", "SomeSystem")]
public class ConnectCmd : PSCmdlet
{
protected override void EndProcessing()
{
SessionState.PSVariable.Set(new PSVariable("varName", valueGoesHere, ScopedItemOptions.Private));
}
}
Теперь любой командлет, работающий в том же пространстве выполнения, может получить и прочитать переменную:
[Cmdlet("Get", "Stuff")]
public class GetCmd : PSCmdlet
{
protected override void EndProcessing()
{
WriteObject(SessionState.PSVariable.Get("varName").Value);
}
}
Обратите внимание, что параметр Private
не является модификатором видимости или области видимости, а скорее гарантирует, что никто не сможет перезаписать значение переменной.
Любой командлет в том же пространстве выполнения/сеансе сможет прочитать переменную таким образом, да (обновленный ответ)! Private
параметры не защитят от SessionState.PSVariable.Set(someOtherPSVariableInstance)
вызова из другого командлета
Спасибо! Замечательно. Я попробовал то, что вы предложили, и оставил пример ниже на основе вашего ответа.
Большое спасибо Матиасу выше за его руководство по этому вопросу. Вот минимальный пример для всех, кто ищет это.
Подключить командлет
using System.Management.Automation;
namespace Test
{
[Cmdlet(VerbsCommunications.Connect, "TestSystem")]
public class VariableTest : PSCmdlet
{
private string _item;
public string Item
{
get { return _item; }
set { _item = value; }
}
protected override void BeginProcessing()
{
base.BeginProcessing();
}
protected override void ProcessRecord()
{
Item = "FooBar";
}
protected override void EndProcessing()
{
SessionState.PSVariable.Set(new PSVariable(nameof(Item), Item, ScopedItemOptions.Private));
}
}
}
Другой командлет
using System.Management.Automation;
namespace Test
{
[Cmdlet(VerbsCommunications.Read, "TestVariable")]
public class ReadVariable : PSCmdlet
{
protected override void BeginProcessing()
{
base.BeginProcessing();
}
protected override void ProcessRecord()
{
var test = SessionState.PSVariable.Get("Item");
WriteObject(test.Value.ToString());
}
}
}
Результат
PS C:\> Connect-TestSystem
PS C:\> Read-TestVariable
FooBar
Это здорово. Спасибо. У меня есть пара вопросов, если можно. 1) Означает ли параметр Private, что будущие командлеты не смогут перезаписать это значение? 2) Смогу ли я аналогично вызывать значения переменных из будущих командлетов, т.е.
SessionState.PSVariable.Get(do stuff)