Как я могу получить и установить переменные в текущем пространстве выполнения? (модули на основе командлетов)

Я пытаюсь написать модуль 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#, которые я пропустил.

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
0
1 112
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Предполагая, что ваш командлет 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 не является модификатором видимости или области видимости, а скорее гарантирует, что никто не сможет перезаписать значение переменной.

Это здорово. Спасибо. У меня есть пара вопросов, если можно. 1) Означает ли параметр Private, что будущие командлеты не смогут перезаписать это значение? 2) Смогу ли я аналогично вызывать значения переменных из будущих командлетов, т.е. SessionState.PSVariable.Get(do stuff)

Ash 19.06.2019 14:57

Любой командлет в том же пространстве выполнения/сеансе сможет прочитать переменную таким образом, да (обновленный ответ)! Private параметры не защитят от SessionState.PSVariable.Set(someOtherPSVariableInstance) вызова из другого командлета

Mathias R. Jessen 19.06.2019 15:46

Спасибо! Замечательно. Я попробовал то, что вы предложили, и оставил пример ниже на основе вашего ответа.

Ash 19.06.2019 15:49

Большое спасибо Матиасу выше за его руководство по этому вопросу. Вот минимальный пример для всех, кто ищет это.

Подключить командлет

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

Другие вопросы по теме