Я недавно начал подбирать C #, поскольку в компании требовались некоторые исполняемые файлы, которые будут запускать предопределенные наборы команд PowerShell. Я знаю ...
Это не тот модуль, который я использую, но ниже я написал упрощенный пример проблемы, с которой я сталкиваюсь при использовании модуля activedirectory.
Вот xaml.
<Window x:Class="ADTool.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:ADTool"
mc:Ignorable="d"
Title="AD Administration" Height="270" Width="500" ResizeMode="CanMinimize">
<Grid Background="Crimson" Width="494" Height="241">
<TextBlock Margin="20,90,0,0" TextWrapping="Wrap" FontWeight="Bold" FontSize="20" Height="25" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120" TextAlignment="Right"><Run FontFamily="Calibri" Text="AD Group" Foreground="Azure"/></TextBlock>
<ComboBox Name ="ADGroup" Height="25" Margin="150,90,0,0" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" FontSize="12" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="324" DropDownClosed="ADGroup_DropDownClosed"/>
<TextBlock Margin="20,135,0,0" TextWrapping="Wrap" FontWeight="Bold" FontSize="20" Height="25" VerticalAlignment="Top" HorizontalAlignment="Left" Width="120" TextAlignment="Right"><Run FontFamily="Calibri" Text="ADGroupMember" Foreground="Azure"/></TextBlock>
<ComboBox Name ="ADGroupMember" Height="25" Margin="150,135,0,0" VerticalAlignment="Top" BorderBrush="Black" BorderThickness="1" FontSize="12" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" HorizontalAlignment="Left" Width="324"/>
<Button Name="BtnAdd" Content="Add" Margin="32,180,0,0" BorderBrush="Black" FontWeight="Bold" Background="LightGray" Foreground="Black" BorderThickness="1" HorizontalAlignment="Left" Width="100" Height="25" VerticalAlignment="Top"/>
<Button Name="BtnRemove" Content="Remove" Margin="142,180,0,0" BorderBrush="Black" FontWeight="Bold" Background="LightGray" Foreground="Black" BorderThickness="1" HorizontalAlignment="Left" Width="100" Height="25" VerticalAlignment="Top"/>
<Button Name="BtnShow" Content="Show" Margin="252,180,0,0" BorderBrush="Black" FontWeight="Bold" Background="LightGray" Foreground="Black" BorderThickness="1" HorizontalAlignment="Left" Width="100" Height="25" VerticalAlignment="Top"/>
<Button Name="BtnQuit" Content="Quit" Margin="362,180,0,0" BorderBrush="Black" FontWeight="Bold" Background="LightGray" Foreground="Black" BorderThickness="1" HorizontalAlignment="Left" Width="100" Height="25" VerticalAlignment="Top"/>
</Grid>
</Window>
А вот и C #.
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;
using System.Security;
using System.Windows;
namespace ADTool
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
// Initiate new PowerShell session and import modules
string[] psModule = { "activedirectory" };
var powerShell = NewPowerShellSession(psModule);
// Add list of AD Groups
var groups = ListADGroup(powerShell);
ADGroup.ItemsSource = groups;
}
// New PowerShell Session, optionally with module(s)
private PowerShell NewPowerShellSession(String[] PSModule = null)
{
// Define our PowerShell Session
PowerShell powerShell = PowerShell.Create();
// Add a runspace to import the module if required.
if (PSModule != null)
{
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(PSModule);
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
powerShell.Runspace = runspace;
}
return powerShell;
}
// PowerShell function
private Collection<PSObject> RunPSASync(PowerShell ps, String PSCommand, IDictionary<String, Object> Parameters, String Property)
{
// Sleep two seconds before proceeding.
ps.AddCommand("Start-Sleep").AddParameter("Seconds", 2).AddStatement();
// Run our command adding the parameters one by one and then pipe in to Out-String.
ps.AddCommand(PSCommand);
if (Parameters != null)
{
foreach (var key in Parameters.Keys)
{
ps.AddParameter(key, Parameters[key]);
}
}
// List a selected property
if (Property != null)
{
ps.AddCommand("Select-Object").AddParameter("ExpandProperty", Property);
}
// Invoke our command asynchronously and return the objects.
IAsyncResult async = ps.BeginInvoke();
var returnCollection = new Collection<PSObject>();
foreach (PSObject obj in ps.EndInvoke(async))
{
returnCollection.Add(obj);
}
return returnCollection;
}
// PowerShell function with pipeline
private Collection<PSObject> RunPSASyncPipe(PowerShell ps, String PSCommand, IDictionary<String, Object> Parameters, String PSCommand2, IDictionary<String, Object> Parameters2, String Property)
{
// Sleep two seconds before proceeding.
ps.AddCommand("Start-Sleep").AddParameter("Seconds", 2).AddStatement();
// Run our command adding the parameters one by one and then pipe in to Out-String.
ps.AddCommand(PSCommand);
if (Parameters != null)
{
foreach (var key in Parameters.Keys)
{
ps.AddParameter(key, Parameters[key]);
}
}
// Add the second command in the pipeline
ps.AddCommand(PSCommand2);
if (Parameters2 != null)
{
foreach (var key in Parameters2.Keys)
{
ps.AddParameter(key, Parameters2[key]);
}
}
// List a selected property
if (Property != null)
{
ps.AddCommand("Select-Object").AddParameter("ExpandProperty", Property);
}
// Invoke our command asynchronously and return the objects.
IAsyncResult async = ps.BeginInvoke();
var returnCollection = new Collection<PSObject>();
foreach (PSObject obj in ps.EndInvoke(async))
{
returnCollection.Add(obj);
}
return returnCollection;
}
// List all AD Groups in a specific OU
private IEnumerable<PSObject> ListADGroup(PowerShell ps)
{
// Define Searchbase
IDictionary<String, Object> parameters = new Dictionary<String, Object>();
parameters.Add("Filter", "*");
parameters.Add("SearchBase", "OU=SomeOtherOU,OU=topOU,DC=blah,DC=com");
var adGroups = RunPSASync(ps, "Get-ADGroup", parameters, "Name");
return adGroups;
}
// Action when ADGroup combobox gets closed
private void ADGroup_DropDownClosed(PowerShell ps)
{
// Collect the currently selected Edge device
string adGroupName = ADGroup.SelectedItem.ToString();
IDictionary<String, Object> groupParameters = new Dictionary<String, Object>();
groupParameters.Add("Filter", "*");
groupParameters.Add("SearchBase", "OU=SomeOtherOU,OU=topOU,DC=blah,DC=com");
IDictionary<String, Object> memberParameters = new Dictionary<String, Object>();
memberParameters.Add("Name", adGroupName);
var adMembers = RunPSASyncPipe(ps, "Get-ADGroup", groupParameters, "Get-ADGroupMember", memberParameters, "name");
ADGroupMember.ItemsSource = adMembers;
}
}
}
А вот как бы я это сделал, если бы мне было разрешено предоставлять людям файл .ps1.
$xaml = "C:\Scripts\somefile.xml"
$wpf = [System.Xml.XmlDocument](Get-Content $xaml)
$reader = (New-Object System.Xml.XmlNodeReader $wpf)
$app = [System.Windows.Markup.XamlReader]::Load($reader)
# Create variables for the named nodes.
$wpf.SelectNodes("//*[@Name]") | ForEach-Object {
New-Variable -Name $_.Name -Value $app.FindName($_.Name) -Scope Global -Force
}
$ADGroup.Add_DropDownClosed({
# do stuff...
})
Я подозреваю, что мне не хватает чего-то, чтобы активировать действие DropDownClosed, и я пытался добавить его в XAML, но это не сработало. Я искал другие варианты, но если бы кто-нибудь мог пощадить новичка в C #, то я был бы очень признателен. Я знаком с .NET, но, похоже, он работает не так, как я ожидаю в PowerShell.
(Прошу прощения за любые ошибки в моем C # тоже)