简体   繁体   English

WPF和PowerShell-将变量从PS传递到C#或修改值

[英]WPF & PowerShell - Passing Variables from PS to C# or modifying value

I need to perform a validation using PowerShell and based on the result, execute an action in the WPF Application. 我需要使用PowerShell执行验证,并根据结果在WPF应用程序中执行操作。 I know I can modify TextBlocks from PowerShell but when I try to modify the value of a WPF variable from within PowerShell nothing happens. 我知道我可以从PowerShell修改TextBlocks,但是当我尝试从PowerShell修改WPF变量的值时,没有任何反应。

Here's an example. 这是一个例子。

MainWindow.xaml: MainWindow.xaml:

    <Window x:Class="Test.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:Test"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <TextBlock x:Name="textBlock" HorizontalAlignment="Left" Margin="74,76,0,0" TextWrapping="Wrap" Text="false" VerticalAlignment="Top" Height="177" Width="371"/>
    </Grid>
</Window>

MainWindow.xaml.cs: MainWindow.xaml.cs:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text.RegularExpressions;
using System.IO;

namespace Test
{
    public partial class MainWindow : Window
    {
        private bool exists = false;

        public MainWindow()
        {
            InitializeComponent();

            // Setup PowerShell Environment
            Runspace runSpace = RunspaceFactory.CreateRunspace();
            runSpace.ThreadOptions = PSThreadOptions.UseCurrentThread;
            runSpace.Open();
            runSpace.SessionStateProxy.SetVariable("exists", exists);
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runSpace;
            string check = "$exists = true";
            ps.AddScript(check);
            // Execute
            ps.Invoke();
            runSpace.Close();

            if (exists == true)
            {
                textBlock.Text = "It is true!";
            }
        }
    }
}

How can I modify the C# / WPF variable from within PowerShell after doing some validation? 经过一些验证后,如何在PowerShell中修改C#/ WPF变量? Is that even possible? 那有可能吗?

I don't want to have to create random textblocks / labels / textboxes for temporary variables. 我不想为临时变量创建随机文本块/标签/文本框。

First of all, exists is a value type. 首先, exists一个值类型。 To update exists from PowerShell you would have to pass it by reference to your PowerShell script. 要从PowerShell更新exists ,您必须通过引用PowerShell脚本来传递它。 I may be wrong but it seems unlikely that that is possibly. 我可能是错的,但似乎不太可能。 Even if it were possible I still would not recommend it. 即使有可能,我仍然不建议这样做。 Manipulating state like that just seems gross. 这样的状态看起来简直是毛骨悚然。 I think a better approach is to pass the data that you want to validate to your PowerShell script and return the result of the validation back to C#. 我认为更好的方法是将要验证的数据传递到PowerShell脚本,然后将验证结果返回给C#。 You can modify your variable state in C# based on that result. 您可以根据该结果在C#中修改变量状态。

Here is a slightly modified version of your code that I ran in LinqPad with the output: 这是我在LinqPad中使用输出运行的代码的略微修改版本:

var exists = true;
Runspace runSpace = RunspaceFactory.CreateRunspace();
runSpace.ThreadOptions = PSThreadOptions.UseCurrentThread;
runSpace.Open();

PowerShell ps = PowerShell.Create();
ps.Runspace = runSpace;
string validation = @"
    # Perform some validation.

    # For the purposes of this demonstration I am going to pretend
    # that validation failed and set 'result' to false.
    $result = $false

    # Return 'result'
    $result
";
ps.AddScript(validation);

// Write the state of `exists` to the console before invoking PowerShell.
Console.WriteLine("exists: " + exists.ToString());

// Execute
var result = ps.Invoke();

// Update exists based on the result of the validation.
exists = bool.Parse(result[0].ToString());

// Or you can use 'GetVariable' to get the result back from PowerShell:
// exists = bool.Parse(runSpace.SessionStateProxy.GetVariable("result").ToString());

// Write the state to the console after invoking PowerShell.
Console.WriteLine("exists: " + exists.ToString());

And here is the result written to the console: 这是写入控制台的结果:

exists: True 存在:真实
exists: False 存在:错误

Using Mike's suggestion I managed to get the variable from PS withouth even having to map it. 根据迈克的建议,我什至不必映射就可以从PS中获取变量。 Like so: 像这样:

using System;
using System.Windows;
using System.Windows.Controls;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Text.RegularExpressions;
using System.IO;

namespace Test
{
    public partial class MainWindow : Window
    {
        public bool itExists = false;

        public MainWindow()
        {
            InitializeComponent();

            // Setup PowerShell Environment
            Runspace runSpace = RunspaceFactory.CreateRunspace();
            runSpace.ThreadOptions = PSThreadOptions.UseCurrentThread;
            runSpace.Open();
            PowerShell ps = PowerShell.Create();
            ps.Runspace = runSpace;
            string check = "$itExists = $TRUE";
            ps.AddScript(check);
            // Execute
            ps.Invoke();

            var result = runSpace.SessionStateProxy.PSVariable.GetValue("itExists").ToString();

            runSpace.Close();

            itExists = result.Equals("True");

            if (itExists)
            {
                textBlock.Text = "It is true!";
            }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM