diff --git a/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs b/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs new file mode 100644 index 0000000..bb2cadd --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/ADCommandParametersTests.cs @@ -0,0 +1,48 @@ +using System.Management.Automation.Runspaces; +using ActiveDirectoryQuerier.ActiveDirectory; +using ActiveDirectoryQuerier.PowerShell; + +namespace ActiveDirectoryQuerier.Tests; + +// ReSharper disable once InconsistentNaming +public class ADCommandParametersTests +{ + [Fact] + public void AvailableParameters_AvailableParametersNotPopulated_NoValidCommandProvided() + { + // Arrange + ADCommandParameters adCommandParameters = new(); + + // Assert + Assert.Contains("No valid command provided", adCommandParameters.AvailableParameters); + } + + [Fact] + public async Task LoadAvailableParametersAsync_PopulatesAvailableParameters_IsNotEmpty() + { + // Arrange + ADCommandParameters adCommandParameters = new(); + Command command = new("Get-Process"); + + // Act + await adCommandParameters.LoadAvailableParametersAsync(command); + + // Assert + Assert.NotEmpty(adCommandParameters.AvailableParameters); + } + + [Fact] + public async Task LoadAvailableParametersAsync_CheckAvailableParameters_ContainsNameAndId() + { + // Arrange + ADCommandParameters adCommandParameters = new(); + Command command = new("Get-Process"); + + // Act + await adCommandParameters.LoadAvailableParametersAsync(command); + + // Assert + Assert.Contains("-Name", adCommandParameters.AvailableParameters); + Assert.Contains("-Id", adCommandParameters.AvailableParameters); + } +} diff --git a/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs b/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs new file mode 100644 index 0000000..a5afd55 --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/ADCommandsFetcherTests.cs @@ -0,0 +1,33 @@ +using System.Collections.ObjectModel; +using System.Management.Automation.Runspaces; +using ActiveDirectoryQuerier.ActiveDirectory; +using ActiveDirectoryQuerier.PowerShell; + +namespace ActiveDirectoryQuerier.Tests; + +// ReSharper disable once InconsistentNaming +public class ADCommandsFetcherTests +{ + [Fact] + public async Task GetADCommands_ReturnsCommandList_IsNotEmpty() + { + // Act + ObservableCollection adCommands = await ADCommandsFetcher.GetADCommands(); + + // Assert + Assert.NotEmpty(adCommands); + } + + [Theory] + [InlineData("Get-ADUser")] + [InlineData("Get-ADGroup")] + [InlineData("Get-ADComputer")] + public async Task GetADCommands_ReturnsCommandList_ContainsCommand(string commandName) + { + // Act + ObservableCollection adCommands = await ADCommandsFetcher.GetADCommands(); + + // Assert + Assert.Contains(adCommands, command => command.CommandText == commandName); + } +} diff --git a/ActiveDirectoryQuerier.Tests/ActiveDirectoryCommandsTests.cs b/ActiveDirectoryQuerier.Tests/ActiveDirectoryCommandsTests.cs deleted file mode 100644 index 267c130..0000000 --- a/ActiveDirectoryQuerier.Tests/ActiveDirectoryCommandsTests.cs +++ /dev/null @@ -1,31 +0,0 @@ -using System.Collections.ObjectModel; -using System.Management.Automation.Runspaces; -using ActiveDirectoryQuerier.PowerShell; - -namespace ActiveDirectoryQuerier.Tests; - -public class ActiveDirectoryCommandsTests -{ - [Fact] - public async Task GetActiveDirectoryCommands_ReturnsCommandList_IsNotEmpty() - { - // Act - ObservableCollection commandList = await ActiveDirectoryCommands.GetActiveDirectoryCommands(); - - // Assert - Assert.NotEmpty(commandList); - } - - [Theory] - [InlineData("Get-ADUser")] - [InlineData("Get-ADGroup")] - [InlineData("Get-ADComputer")] - public async Task GetActiveDirectoryCommands_ReturnsCommandList_ContainsCommand(string commandName) - { - // Act - ObservableCollection commandList = await ActiveDirectoryCommands.GetActiveDirectoryCommands(); - - // Assert - Assert.Contains(commandList, cmd => cmd.CommandText == commandName); - } -} diff --git a/ActiveDirectoryQuerier.Tests/AppConsoleTests.cs b/ActiveDirectoryQuerier.Tests/AppConsoleTests.cs new file mode 100644 index 0000000..22f00fa --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/AppConsoleTests.cs @@ -0,0 +1,83 @@ +using System.Management.Automation.Runspaces; +using ActiveDirectoryQuerier.PowerShell; + +namespace ActiveDirectoryQuerier.Tests; + +public class AppConsoleTests : IDisposable +{ + // TODO: Make sure this is how I should perform cleanups... + public void Dispose() + { + if (File.Exists("output.txt")) + { + File.Delete("output.txt"); + } + + if (File.Exists("output.csv")) + { + File.Delete("output.csv"); + } + + GC.SuppressFinalize(this); + } + + private static async Task<(AppConsole, PSOutput)> ExecuteCommandAsync(Command command) + { + PSExecutor psExecutor = new(); + AppConsole appConsole = new(); + PSOutput result = await psExecutor.ExecuteAsync(command); + + appConsole.Append(result.HadErrors ? result.StdErr : result.StdOut); + + return (appConsole, result); + } + + [Fact] + public async Task ClearConsole_ClearsConsole_SuccessfullyCleared() + { + // Arrange + Command command = new("Get-Process"); + command.Parameters.Add("Name", "explorer"); + var (appConsole, _) = await ExecuteCommandAsync(command); + + // Act + appConsole.Clear(); + + // Assert + Assert.Empty(appConsole.ConsoleOutput); + } + + [Fact] + public void Append_AppendsStringToConsole_SuccessfullyAppended() + { + // Arrange + AppConsole appConsole = new(); + const string output = "Output"; + + // Act + appConsole.Append(output); + + // Assert + Assert.Equal(output, appConsole.ConsoleOutput); + } + + [Fact] + public async Task ExportToText_ExportToText_SuccessfullyExported() + { + // Arrange + Command command = new("Get-Process"); + command.Parameters.Add("Name", "explorer"); + var (appConsole, returnValues) = await ExecuteCommandAsync(command); + + // Act + appConsole.ExportToText(); + string fileContents = await File.ReadAllTextAsync("output.txt"); + + // Assert + Assert.True(File.Exists("output.txt")); + + Assert.Equal(returnValues.HadErrors ? string.Join(Environment.NewLine, returnValues.StdErr) + : string.Join(Environment.NewLine, returnValues.StdOut), + fileContents); + } +} diff --git a/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs b/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs new file mode 100644 index 0000000..a98c571 --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/ComboBoxParameterViewModelTests.cs @@ -0,0 +1,76 @@ +using System.Collections.ObjectModel; +using System.Management.Automation.Runspaces; +using ActiveDirectoryQuerier.ActiveDirectory; +using ActiveDirectoryQuerier.PowerShell; +using ActiveDirectoryQuerier.ViewModels; + +namespace ActiveDirectoryQuerier.Tests; + +public class ComboBoxParameterViewModelTests +{ + [Fact] + public async Task ComboBoxParameterViewModel_WhenConstructed_PossibleParametersIsNotNullOrEmpty() + { + // Arrange + Command command = new("Get-ADUser"); + ADCommandParameters adCommandParameters = new(); + ComboBoxParameterViewModel comboBoxParameterViewModel; + + // Act + await adCommandParameters.LoadAvailableParametersAsync(command); + comboBoxParameterViewModel = new(adCommandParameters.AvailableParameters); + + // Assert + Assert.NotNull(comboBoxParameterViewModel.AvailableParameters); + Assert.NotEmpty(comboBoxParameterViewModel.AvailableParameters); + } + + [Fact] + public async Task ComboBoxParameterViewModel_WhenConstructed_PossibleParametersContainsExpectedParameters() + { + // Arrange + Command command = new("Get-ADUser"); + ADCommandParameters adCommandParameters = new(); + ComboBoxParameterViewModel comboBoxParameterViewModel; + + // Act + await adCommandParameters.LoadAvailableParametersAsync(command); + comboBoxParameterViewModel = new(adCommandParameters.AvailableParameters); + + // Assert + Assert.Contains(comboBoxParameterViewModel.AvailableParameters, param => param == "-Filter"); + Assert.Contains(comboBoxParameterViewModel.AvailableParameters, param => param == "-Identity"); + Assert.Contains(comboBoxParameterViewModel.AvailableParameters, param => param == "-LDAPFilter"); + Assert.Contains(comboBoxParameterViewModel.AvailableParameters, param => param == "-SearchBase"); + Assert.Contains(comboBoxParameterViewModel.AvailableParameters, param => param == "-SearchScope"); + } + + [Fact] + public async Task ComboBoxParameterViewModel_WhenSelectedParameterChosen_SelectedParameterIsSet() + { + // Arrange + string selectedParameter; + Command command = new("Get-ADUser"); + ADCommandParameters adCommandParameters = new(); + ComboBoxParameterViewModel comboBoxParameterViewModel; + + // Act + await adCommandParameters.LoadAvailableParametersAsync(command); + comboBoxParameterViewModel = new(adCommandParameters.AvailableParameters); + selectedParameter = comboBoxParameterViewModel.AvailableParameters[0]; + comboBoxParameterViewModel.SelectedParameter = selectedParameter; + + // Assert + Assert.Equal(selectedParameter, comboBoxParameterViewModel.SelectedParameter); + } + + [Fact] + public void ComboBoxParameterViewModel_WhenConstructedWithNullPossibleParameters_ThrowsArgumentNullException() + { + // Arrange + ObservableCollection possibleParameters = null!; + + // Assert + Assert.Throws(() => new ComboBoxParameterViewModel(possibleParameters)); + } +} diff --git a/ActiveDirectoryQuerier.Tests/CommandParametersTests.cs b/ActiveDirectoryQuerier.Tests/CommandParametersTests.cs deleted file mode 100644 index aa749a2..0000000 --- a/ActiveDirectoryQuerier.Tests/CommandParametersTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System.Management.Automation.Runspaces; -using ActiveDirectoryQuerier.PowerShell; - -namespace ActiveDirectoryQuerier.Tests; - -public class CommandParametersTests -{ - [Fact] - public void PossibleParameters_LoadCommandParametersAsyncNotPopulated_ThrowInvalidOperationException() - { - // Arrange - CommandParameters commandParameters = new(); - - // Assert - Assert.Throws(() => commandParameters.PossibleParameters); - } - - [Fact] - public async Task LoadCommandParametersAsync_PopulatesPossibleParameters_IsNotEmpty() - { - // Arrange - CommandParameters commandParameters = new(); - Command command = new("Get-Process"); - - // Act - await commandParameters.LoadCommandParametersAsync(command); - - // Assert - Assert.NotEmpty(commandParameters.PossibleParameters); - } - - [Fact] - public async Task LoadCommandParametersAsync_CheckPossibleParameter_ContentIsCorrect() - { - // Arrange - CommandParameters commandParameters = new(); - Command command = new("Get-Process"); - - // Act - await commandParameters.LoadCommandParametersAsync(command); - - // Assert - Assert.Contains("-Name", commandParameters.PossibleParameters); - Assert.Contains("-Id", commandParameters.PossibleParameters); - } -} diff --git a/ActiveDirectoryQuerier.Tests/PowerShellExecutorTests.cs b/ActiveDirectoryQuerier.Tests/PSExecutorTests.cs similarity index 57% rename from ActiveDirectoryQuerier.Tests/PowerShellExecutorTests.cs rename to ActiveDirectoryQuerier.Tests/PSExecutorTests.cs index 24c8828..ae5f78b 100644 --- a/ActiveDirectoryQuerier.Tests/PowerShellExecutorTests.cs +++ b/ActiveDirectoryQuerier.Tests/PSExecutorTests.cs @@ -3,20 +3,23 @@ namespace ActiveDirectoryQuerier.Tests; -public class PowerShellExecutorTests +// ReSharper disable once InconsistentNaming +public class PSExecutorTests { [Theory] [InlineData("Get-Command", "Module", "ActiveDirectory")] [InlineData("Get-Process", "Name", "explorer")] - public void Execute_WhenGivenValidCommand_ReturnsExpectedOutput(string cmd, string paramName, string paramValue) + public void Execute_WhenGivenValidCommand_ReturnsExpectedOutput(string command, + string parameter, + string parameterValue) { // Arrange - Command command = new(cmd); - command.Parameters.Add(paramName, paramValue); - PowerShellExecutor powerShellExecutor = new(); + Command psCommand = new(command); + psCommand.Parameters.Add(parameter, parameterValue); + PSExecutor psExecutor = new(); // Act - ReturnValues result = powerShellExecutor.Execute(command); + PSOutput result = psExecutor.Execute(psCommand); // Assert Assert.False(result.HadErrors); @@ -32,11 +35,11 @@ public void Execute_CheckIfOutputChanged_ReturnsDifferentOutput() command.Parameters.Add("Module", "ActiveDirectory"); Command command2 = new("Get-Process"); command.Parameters.Add("Name", "explorer"); - PowerShellExecutor powerShellExecutor = new(); + PSExecutor psExecutor = new(); // Act - ReturnValues result = powerShellExecutor.Execute(command); - ReturnValues result2 = powerShellExecutor.Execute(command2); + PSOutput result = psExecutor.Execute(command); + PSOutput result2 = psExecutor.Execute(command2); // Assert Assert.NotEqual(result, result2); @@ -45,17 +48,17 @@ public void Execute_CheckIfOutputChanged_ReturnsDifferentOutput() [Theory] [InlineData("Get-Command", "Module", "ActiveDirectory")] [InlineData("Get-Process", "Name", "explorer")] - public async Task ExecuteAsync_WhenGivenValidCommand_ReturnsExpectedOutput(string cmd, - string paramName, - string paramValue) + public async Task ExecuteAsync_WhenGivenValidCommand_ReturnsExpectedOutput(string command, + string parameter, + string parameterValue) { // Arrange - Command command = new(cmd); - command.Parameters.Add(paramName, paramValue); - PowerShellExecutor powerShellExecutor = new(); + Command psCommand = new(command); + psCommand.Parameters.Add(parameter, parameterValue); + PSExecutor psExecutor = new(); // Act - ReturnValues result = await powerShellExecutor.ExecuteAsync(command); + PSOutput result = await psExecutor.ExecuteAsync(psCommand); // Assert Assert.False(result.HadErrors); @@ -66,15 +69,17 @@ public async Task ExecuteAsync_WhenGivenValidCommand_ReturnsExpectedOutput(strin [Theory] [InlineData("Get-ADUser", "InvalidParameter", "*")] [InlineData("InvalidCommand", "Filter", "*")] - public void Execute_WhenGivenInvalidCommand_ReturnsExpectedOutput(string cmd, string paramName, string paramValue) + public void Execute_WhenGivenInvalidCommand_ReturnsExpectedOutput(string command, + string parameter, + string parameterValue) { // Arrange - Command command = new(cmd); - command.Parameters.Add(paramName, paramValue); - PowerShellExecutor powerShellExecutor = new(); + Command psCommand = new(command); + psCommand.Parameters.Add(parameter, parameterValue); + PSExecutor psExecutor = new(); // Act - ReturnValues result = powerShellExecutor.Execute(command); + PSOutput result = psExecutor.Execute(psCommand); // Assert Assert.True(result.HadErrors); @@ -85,17 +90,17 @@ public void Execute_WhenGivenInvalidCommand_ReturnsExpectedOutput(string cmd, st [Theory] [InlineData("Get-ADUser", "InvalidParameter", "*")] [InlineData("InvalidCommand", "Filter", "*")] - public async Task ExecuteAsync_WhenGivenInvalidCommand_ReturnsExpectedOutput(string cmd, - string paramName, - string paramValue) + public async Task ExecuteAsync_WhenGivenInvalidCommand_ReturnsExpectedOutput(string command, + string parameter, + string parameterValue) { // Arrange - Command command = new(cmd); - command.Parameters.Add(paramName, paramValue); - PowerShellExecutor powerShellExecutor = new(); + Command psCommand = new(command); + psCommand.Parameters.Add(parameter, parameterValue); + PSExecutor psExecutor = new(); // Act - ReturnValues result = await powerShellExecutor.ExecuteAsync(command); + PSOutput result = await psExecutor.ExecuteAsync(psCommand); // Assert Assert.True(result.HadErrors); diff --git a/ActiveDirectoryQuerier.Tests/PSOutputTest.cs b/ActiveDirectoryQuerier.Tests/PSOutputTest.cs new file mode 100644 index 0000000..dccddf1 --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/PSOutputTest.cs @@ -0,0 +1,39 @@ +using ActiveDirectoryQuerier.PowerShell; + +namespace ActiveDirectoryQuerier.Tests; + +// ReSharper disable once InconsistentNaming +public class PSOutputTest +{ + [Fact] + public void HadErrors_StdErrHasEntries_ReturnsTrue() + { + // Arrange + PSOutput psOutput = new(); + psOutput.StdErr.Add("Error"); + + // Act + bool result = psOutput.HadErrors; + + // Assert + Assert.True(result); + Assert.NotEmpty(psOutput.StdErr); + Assert.Empty(psOutput.StdOut); + } + + [Fact] + public void NoErrors_StdOutHasEntries_ReturnsFalse() + { + // Arrange + PSOutput psOutput = new(); + psOutput.StdOut.Add("Output"); + + // Act + var result = psOutput.HadErrors; + + // Assert + Assert.False(result); + Assert.Empty(psOutput.StdErr); + Assert.NotEmpty(psOutput.StdOut); + } +} diff --git a/ActiveDirectoryQuerier.Tests/RelayCommandTests.cs b/ActiveDirectoryQuerier.Tests/RelayCommandTests.cs index b44ba75..bb4439c 100644 --- a/ActiveDirectoryQuerier.Tests/RelayCommandTests.cs +++ b/ActiveDirectoryQuerier.Tests/RelayCommandTests.cs @@ -1,4 +1,6 @@ -namespace ActiveDirectoryQuerier.Tests; +using ActiveDirectoryQuerier.ViewModels; + +namespace ActiveDirectoryQuerier.Tests; public class RelayCommandTests { diff --git a/ActiveDirectoryQuerier.Tests/ReturnValuesTest.cs b/ActiveDirectoryQuerier.Tests/ReturnValuesTest.cs deleted file mode 100644 index 7e75175..0000000 --- a/ActiveDirectoryQuerier.Tests/ReturnValuesTest.cs +++ /dev/null @@ -1,38 +0,0 @@ -using ActiveDirectoryQuerier.PowerShell; - -namespace ActiveDirectoryQuerier.Tests; - -public class ReturnValuesTest -{ - [Fact] - public void HadErrors_StdErrHasEntries_ReturnsTrue() - { - // Arrange - var returnValues = new ReturnValues(); - returnValues.StdErr.Add("Error"); - - // Act - var result = returnValues.HadErrors; - - // Assert - Assert.True(result); - Assert.NotEmpty(returnValues.StdErr); - Assert.Empty(returnValues.StdOut); - } - - [Fact] - public void NoErrors_StdOutHasEntries_ReturnsFalse() - { - // Arrange - var returnValues = new ReturnValues(); - returnValues.StdOut.Add("Output"); - - // Act - var result = returnValues.HadErrors; - - // Assert - Assert.False(result); - Assert.Empty(returnValues.StdErr); - Assert.NotEmpty(returnValues.StdOut); - } -} diff --git a/ActiveDirectoryQuerier.Tests/TextBoxViewModelTests.cs b/ActiveDirectoryQuerier.Tests/TextBoxViewModelTests.cs new file mode 100644 index 0000000..87aa8f4 --- /dev/null +++ b/ActiveDirectoryQuerier.Tests/TextBoxViewModelTests.cs @@ -0,0 +1,31 @@ +using ActiveDirectoryQuerier.ViewModels; + +namespace ActiveDirectoryQuerier.Tests; + +public class TextBoxViewModelTests +{ + [Fact] + public void TextBoxViewModel_WhenConstructed_SelectedParameterValueIsNotNullOrEmpty() + { + // Arrange + TextBoxViewModel textBoxViewModel = new() {// Act + SelectedParameterValue = "*" + }; + + // Assert + Assert.NotNull(textBoxViewModel.SelectedParameterValue); + Assert.NotEmpty(textBoxViewModel.SelectedParameterValue); + } + + [Fact] + public void TextBoxViewModel_WhenSetToNull_NoExceptionIsThrown() + { + // Arrange + TextBoxViewModel textBoxViewModel = new() {// Act + SelectedParameterValue = null! + }; + + // Assert + Assert.Null(textBoxViewModel.SelectedParameterValue); + } +} diff --git a/ActiveDirectoryQuerier/ActiveDirectory/ADCommandParameters.cs b/ActiveDirectoryQuerier/ActiveDirectory/ADCommandParameters.cs new file mode 100644 index 0000000..2b5b107 --- /dev/null +++ b/ActiveDirectoryQuerier/ActiveDirectory/ADCommandParameters.cs @@ -0,0 +1,82 @@ +using System.Collections.ObjectModel; +using System.Diagnostics; +using System.Management.Automation; +using System.Management.Automation.Runspaces; + +namespace ActiveDirectoryQuerier.ActiveDirectory; + +// ReSharper disable once InconsistentNaming +public class ADCommandParameters +{ + private readonly ObservableCollection _availableParameters = new(); + + /// + /// + /// This property should not be accessed before LoadAvailableParametersAsync or LoadAvailableParameters has been + /// called. If it is accessed before either method has been called, no parameters will be available. + /// + public ObservableCollection AvailableParameters + { + get { + if (_availableParameters.Count == 0) + { + Debug.WriteLine("Warning: LoadAvailableParametersAsync should be called before accessing " + + "AvailableParameters, to ensure asynchronous loading of parameters."); + LoadAvailableParameters(null); + } + + return _availableParameters; + } + } + + public async Task LoadAvailableParametersAsync(Command? psCommand) + { + await LoadAvailableParametersCore(psCommand, true); + } + + public void LoadAvailableParameters(Command? psCommand) + { + LoadAvailableParametersCore(psCommand, false).Wait(); + } + + private async Task LoadAvailableParametersCore(Command? psCommand, bool isAsync) + { + // psCommand can be null if the user attempts to select an ActiveDirectory command that doesn't exist. + // More specifically, if the entered command doesn't exist in the ADCommands property defined in + // MainWindowViewModel.cs, psCommand will be null, causing an exception to be thrown, crashing the + // program. + if (psCommand is null) + { + Trace.WriteLine("Error: command is null"); + _availableParameters.Add("No valid command provided"); + return; + } + + if (_availableParameters.Count == 0) + { + using var powerShell = System.Management.Automation.PowerShell.Create(); + string commandString = + $"Get-Command {psCommand.CommandText} | Select -ExpandProperty Parameters | ForEach-Object {{ $_.Keys }}"; + + powerShell.Commands.Clear(); + powerShell.AddScript(commandString); + + if (isAsync) + { + PSDataCollection result = await powerShell.InvokeAsync(); + foreach (PSObject adCommandParameter in result) + { + _availableParameters.Add($"-{adCommandParameter}"); + } + } + else + { + Collection result = powerShell.Invoke(); + foreach (PSObject adCommandParameter in result) + { + _availableParameters.Add($"-{adCommandParameter}"); + } + } + } + } +} diff --git a/ActiveDirectoryQuerier/ActiveDirectory/ADCommandsFetcher.cs b/ActiveDirectoryQuerier/ActiveDirectory/ADCommandsFetcher.cs new file mode 100644 index 0000000..6ab5746 --- /dev/null +++ b/ActiveDirectoryQuerier/ActiveDirectory/ADCommandsFetcher.cs @@ -0,0 +1,38 @@ +using System.Collections.ObjectModel; +using System.Management.Automation; +using System.Management.Automation.Runspaces; +using System.Windows; +using ActiveDirectoryQuerier.PowerShell; + +namespace ActiveDirectoryQuerier.ActiveDirectory; + +// ReSharper disable once InconsistentNaming +public static class ADCommandsFetcher +{ + // ReSharper disable once InconsistentNaming + public static async Task> GetADCommands() + { + Command psCommand = new("Get-Command"); + psCommand.Parameters.Add("Module", "ActiveDirectory"); + PSExecutor psExecutor = new(); + ObservableCollection adCommands = new(); + PSOutput psOutput = await psExecutor.ExecuteAsync(psCommand); + + // This is more of an internal error catch, as even through this command shouldn't fail, it's possible that it + // could. If this is the case, we want to know about it. + if (psOutput.HadErrors) + { + string errorMessage = "Internal Error: An error occurred while retrieving the Active Directory commands: " + + $"({string.Join(" ", psOutput.StdErr)})"; + MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error); + throw new InvalidPowerShellStateException(errorMessage); + } + + foreach (string command in psOutput.StdOut) + { + adCommands.Add(new Command(command)); + } + + return adCommands; + } +} diff --git a/ActiveDirectoryQuerier/ActiveDirectoryQuerier.csproj b/ActiveDirectoryQuerier/ActiveDirectoryQuerier.csproj index 1efb6dd..403bbb6 100644 --- a/ActiveDirectoryQuerier/ActiveDirectoryQuerier.csproj +++ b/ActiveDirectoryQuerier/ActiveDirectoryQuerier.csproj @@ -9,9 +9,9 @@ Active Directory Querier - 0.5.0 + 0.6.0 Hunter T., Pieter, Joseph - https://github.com/StrangeRanger/FAFB-PowerShell-Tool + https://github.com/StrangeRanger/Active-Directory-Querier false diff --git a/ActiveDirectoryQuerier/AppConsole.cs b/ActiveDirectoryQuerier/AppConsole.cs new file mode 100644 index 0000000..0c0caba --- /dev/null +++ b/ActiveDirectoryQuerier/AppConsole.cs @@ -0,0 +1,53 @@ +using System.ComponentModel; +using System.IO; + +namespace ActiveDirectoryQuerier; + +public sealed class AppConsole : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + private string _consoleOutput = string.Empty; + + /// + /// + /// Do not set this property directly. Use the Append method instead. It's public for data binding purposes. + /// + /// TODO: Find a way to make the set of this property private, while still allowing data binding. + public string ConsoleOutput + { + get => _consoleOutput; + [EditorBrowsable(EditorBrowsableState.Never)] + set { + if (_consoleOutput != value) + { + _consoleOutput = value; + OnPropertyChanged(nameof(ConsoleOutput)); + } + } + } + + public void Clear() + { + ConsoleOutput = string.Empty; + } + + public void Append(List outputText) + { + ConsoleOutput += string.Join(Environment.NewLine, outputText); + } + + public void Append(string outputText) + { + ConsoleOutput += outputText; + } + + public void ExportToText(string filePath = "output.txt") + { + File.WriteAllText(filePath, ConsoleOutput); + } + + private void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} diff --git a/ActiveDirectoryQuerier/ComboBoxParameterViewModel.cs b/ActiveDirectoryQuerier/ComboBoxParameterViewModel.cs deleted file mode 100644 index b9c800e..0000000 --- a/ActiveDirectoryQuerier/ComboBoxParameterViewModel.cs +++ /dev/null @@ -1,68 +0,0 @@ -using System.Collections.ObjectModel; -using System.ComponentModel; - -namespace ActiveDirectoryQuerier; - -/// -/// ViewModel for a ComboBox that displays possible parameters for a PowerShell command. -/// It is used when adding a new parameter slot to a command in the UI. -/// -public sealed class ComboBoxParameterViewModel : INotifyPropertyChanged -{ - public event PropertyChangedEventHandler? PropertyChanged; - private ObservableCollection _possibleParameterList = new(); - private string _selectedParameter = string.Empty; - - /// - /// Initializes a new instance of the ComboBoxParameterViewModel class. - /// - /// Initial list of possible parameters for the ComboBox. - public ComboBoxParameterViewModel(ObservableCollection possibleParameterList) - { - PossibleParameterList = possibleParameterList ?? throw new ArgumentNullException(nameof(possibleParameterList)); - } - - /// - /// Sets a unique selected value for each combo box. - /// - public string SelectedParameter - { - get => _selectedParameter; - set { - if (_selectedParameter != value) - { - _selectedParameter = value; - OnPropertyChanged(nameof(SelectedParameter)); - } - } - } - - /// - /// Gets or sets the list of possible parameters that can be selected for a command. - /// - public ObservableCollection PossibleParameterList - { - get => _possibleParameterList; - set { - if (value is null) - { - throw new ArgumentNullException(nameof(value)); - } - - if (_possibleParameterList != value) - { - _possibleParameterList = value; - OnPropertyChanged(nameof(PossibleParameterList)); - } - } - } - - /// - /// Invokes the PropertyChanged event for the specified property name. - /// - /// Name of the property that has changed. - private void OnPropertyChanged(string propertyName) - { - PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); - } -} diff --git a/ActiveDirectoryQuerier/MainWindow.xaml b/ActiveDirectoryQuerier/MainWindow.xaml index 7a62e8f..07c52f0 100644 --- a/ActiveDirectoryQuerier/MainWindow.xaml +++ b/ActiveDirectoryQuerier/MainWindow.xaml @@ -1,4 +1,4 @@ - - + + + + - - + - - - + + + + + + + + - + - - - + + + - - - + + - + - - - - + + + - @@ -60,10 +61,8 @@ - - @@ -71,15 +70,32 @@ - - + + - - - + + + + + + Query Name + + + Query Description + - + @@ -90,32 +106,38 @@ - - - - - + + - - + + - - - + + + - - + + + + + + + Command + - + Parameter + + ItemsSource="{Binding AvailableParameters}" + SelectedItem="{Binding SelectedParameter}" /> - - + + + Value + + Text="{Binding SelectedParameterValue, UpdateSourceTrigger=PropertyChanged}" /> - - - - - - - - - - - - - - -