Skip to content
This repository has been archived by the owner on Dec 21, 2024. It is now read-only.

Commit

Permalink
CSV formatting is now done at the powershell level
Browse files Browse the repository at this point in the history
  • Loading branch information
StrangeRanger committed Mar 22, 2024
1 parent 44ad702 commit b0d523e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 58 deletions.
21 changes: 21 additions & 0 deletions ActiveDirectoryQuerier.Tests/PSExecutorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -107,4 +107,25 @@ public async Task ExecuteAsync_WhenGivenInvalidCommand_ReturnsExpectedOutput(str
Assert.NotEmpty(result.StdErr);
Assert.Empty(result.StdOut);
}

[Theory]
[InlineData("Get-Command", "Module", "ActiveDirectory")]
[InlineData("Get-Process", "Name", "explorer")]
public async Task ExecuteAsync_ExecuteToCsv_ReturnsExpectedOutput(string command,
string parameter,
string parameterValue)
{
// Arrange
Command psCommand = new(command);
psCommand.Parameters.Add(parameter, parameterValue);
PSExecutor psExecutor = new();

// Act
PSOutput result = await psExecutor.ExecuteAsync(psCommand, OutputFormat.Csv);

// Assert
Assert.False(result.HadErrors);
Assert.Empty(result.StdErr);
Assert.NotEmpty(result.StdOut);
}
}
7 changes: 7 additions & 0 deletions ActiveDirectoryQuerier/PowerShell/OutputFormat.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace ActiveDirectoryQuerier.PowerShell;

public enum OutputFormat
{
Text,
Csv
}
15 changes: 10 additions & 5 deletions ActiveDirectoryQuerier/PowerShell/PSExecutor.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ public PSExecutor()
_powerShell.Commands.Clear();
}

private void AssembleFullCommand(Command psCommand)
private void AssembleFullCommand(Command psCommand, OutputFormat outputFormat)
{
ArgumentNullException.ThrowIfNull(psCommand);

Expand All @@ -31,14 +31,19 @@ private void AssembleFullCommand(Command psCommand)
{
_powerShell.Commands.AddParameter(parameter.Name, parameter.Value);
}

if (outputFormat == OutputFormat.Csv)
{
_powerShell.Commands.AddCommand("ConvertTo-Csv").AddParameter("NoTypeInformation");
}
}

public PSOutput Execute(Command psCommand)
public PSOutput Execute(Command psCommand, OutputFormat outputFormat = OutputFormat.Text)
{
try
{
_powerShell.Commands.Clear();
AssembleFullCommand(psCommand);
AssembleFullCommand(psCommand, outputFormat);

Collection<PSObject> results = _powerShell.Invoke();

Expand All @@ -50,12 +55,12 @@ public PSOutput Execute(Command psCommand)
}
}

public async Task<PSOutput> ExecuteAsync(Command command)
public async Task<PSOutput> ExecuteAsync(Command command, OutputFormat outputFormat = OutputFormat.Text)
{
try
{
_powerShell.Commands.Clear();
AssembleFullCommand(command);
AssembleFullCommand(command, outputFormat);

PSDataCollection<PSObject> results = await _powerShell.InvokeAsync();

Expand Down
99 changes: 46 additions & 53 deletions ActiveDirectoryQuerier/QueryExecutor.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System.Diagnostics;
using System.IO;
using System.Management.Automation.Runspaces;
using System.Reflection;
using System.Text;
using System.Windows;
using System.Windows.Controls;
Expand Down Expand Up @@ -34,17 +35,20 @@ public async Task ExecuteQueryAsync(ConsoleViewModel consoleOutput, Command? com
try
{
PSOutput result;
OutputFormat outputFormat = CalculateOutputFormat();

if (command is not null)
{
result = await psExecutor.ExecuteAsync(command);
result = await psExecutor.ExecuteAsync(command, outputFormat);
}
else
{
mainWindowViewModel.UpdateCommandWithSelectedParameters();
// Null forgiveness operator is used because if command is not null, this line will never be reached.
// If it is null, that must mean that SelectedCommandInQueryBuilder is not null, else the return
// statement above would have been executed.
result = await psExecutor.ExecuteAsync(mainWindowViewModel.SelectedCommandInQueryBuilder!);
result =
await psExecutor.ExecuteAsync(mainWindowViewModel.SelectedCommandInQueryBuilder!, outputFormat);
}

if (result.HadErrors)
Expand All @@ -60,39 +64,37 @@ public async Task ExecuteQueryAsync(ConsoleViewModel consoleOutput, Command? com
consoleOutput.Append($"Error executing command: {exception.Message}");
}
}

public async Task OutputExecutionResultsToTextFileAsync(object? queryButton)
public void ExportConsoleOutputToFile(object _)
{
if (queryButton is not null)
{
var buttonQuery = (Query)((Button)queryButton).Tag;
await ExecuteQueryAsync(consoleOutputInQueryBuilder, buttonQuery.Command);
}
else
if (consoleOutputInQueryBuilder.ConsoleOutput.Length == 0)
{
await ExecuteQueryAsync(consoleOutputInQueryBuilder);
MessageBox.Show("The console is empty.", "Information", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}

// Filepath
// Write the text to a file & prompt user for the location
SaveFileDialog saveFileDialog = new() { // Set properties of the OpenFileDialog
FileName = "Document", // Default file name
Filter = "All files(*.*) | *.*"
};
SaveFileDialog saveFileDialog = new() { DefaultExt = ".txt", Filter = "Text documents (.txt)|*.txt" };

// Display
bool? result = saveFileDialog.ShowDialog();

// Get file and write text
if (result == true)
{
// Open document
string filePath = saveFileDialog.FileName;
await File.WriteAllTextAsync(filePath, consoleOutputInQueryBuilder.ConsoleOutput);
string filename = saveFileDialog.FileName;
consoleOutputInQueryBuilder.ExportToTextFile(filename);
}
}

public async Task OutputExecutionResultsToTextFileAsync(object? queryButton)
{
await OutputExecutionResultsToFileAsync(queryButton, ".txt", "Text documents (.txt)|*.txt");
}

public async Task OutputExecutionResultsToCsvFileAsync(object? queryButton)
{
await OutputExecutionResultsToFileAsync(queryButton, ".csv", "CSV files (*.csv)|*.csv");
}

private async Task OutputExecutionResultsToFileAsync(object? queryButton, string fileExtension, string filter)
{
if (queryButton is not null)
{
Expand All @@ -104,49 +106,40 @@ public async Task OutputExecutionResultsToCsvFileAsync(object? queryButton)
await ExecuteQueryAsync(consoleOutputInQueryBuilder);
}

StringBuilder csv = new();
string[] output = consoleOutputInQueryBuilder.ConsoleOutput.Split(' ', '\n');

for (int i = 0; i < output.Length - 2; i++)
{
var first = output[i];
var second = output[i + 1];
// format the strings and add them to a string
var newLine = $"{first},{second}";
csv.AppendLine(newLine);
}

// Write the text to a file & prompt user for the location
SaveFileDialog saveFileDialog = new() { FileName = "Document", Filter = "All files(*.*) | *.*" };
SaveFileDialog saveFileDialog = new() { DefaultExt = fileExtension, Filter = filter };

// Display
bool? result = saveFileDialog.ShowDialog();

// Get file and write text
if (result == true)
{
// Open document
string filePath = saveFileDialog.FileName;
await File.WriteAllTextAsync(filePath, csv.ToString());
await File.WriteAllTextAsync(filePath, consoleOutputInQueryBuilder.ConsoleOutput);
}
}

public void ExportConsoleOutputToFile(object _)
private OutputFormat CalculateOutputFormat()
{
if (consoleOutputInQueryBuilder.ConsoleOutput.Length == 0)
{
MessageBox.Show("The console is empty.", "Information", MessageBoxButton.OK, MessageBoxImage.Information);
return;
}

SaveFileDialog saveFileDialog = new() { DefaultExt = ".txt", Filter = "Text documents (.txt)|*.txt" };
StackTrace stackTrace = new();
StackFrame[] stackFrames = stackTrace.GetFrames();

bool? result = saveFileDialog.ShowDialog();
try
{
if (stackFrames.Length > 2)
{
// Null forgiveness operator is used because the method this statement would not be reached if the
// length of the stackFrames array is less than 3.
MethodBase callingMethod = stackFrames[2].GetMethod()!;
if (callingMethod.Name == "OutputExecutionResultsToCsvFileAsync")
{
return OutputFormat.Csv;
}
}

if (result == true)
return OutputFormat.Text;
}
catch (Exception)
{
string filename = saveFileDialog.FileName;
consoleOutputInQueryBuilder.ExportToTextFile(filename);
return OutputFormat.Text;
}
}
}

0 comments on commit b0d523e

Please sign in to comment.