I need to perform a validation using PowerShell and based on the result, execute an action in the WPF Application. 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.
Here's an example.
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:
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? 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. To update exists
from PowerShell you would have to pass it by reference to your PowerShell script. 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#. You can modify your variable state in C# based on that result.
Here is a slightly modified version of your code that I ran in LinqPad with the output:
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. 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!";
}
}
}
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.