Skip to content
This repository has been archived by the owner on Apr 18, 2020. It is now read-only.
/ FileWriter Public archive

A simple app demonstrating implementing embedded PowerShell scripts in a Web API / Angular app

Notifications You must be signed in to change notification settings

JaimeStill/FileWriter

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 

Repository files navigation

File Writer - PowerShell SDK with Web API and Angular

This repository is a simple demonstration of how to use a PowerShell script embedded in a .NET Core class library, exposing the functionality of the script to a Web API / Angular web app. This application has been kept very simple to emphasize how data flows and executes between each technology.

write-file
click to open

For much more advanced implementations of this features, see my Portfolio and Mapper repositories.

The portion of my Portfolio repository that uses this feature makes use of an embedded ffmpeg executable to convert .mp4 files to .gif.

The Mapper repository uses PowerShell to automate the generation of GeoJSON (as demonstrated by Mike Bostock in his Command-Line Cartography article series) so that maps can be rendered using D3.

Scripting

Back to Top

All of the PowerShell-related features are contained in the src/FileWriter.Scripting library. It uses the Microsoft.PowerShell.SDK to execute an embedded .ps1 script in a PowerShell Core runspace on the machine that is hosting the .NET Core app.

FileWriter.Scripting/Scripts/Write-Text.ps1

write-text.ps1

This simple script takes a path and a value parameter to create a text file at the specified path with the specified value.

In order to access the PowerShell script, it needs to be included in the class library as an EmbeddedResource.

FileWriter.Scripting/FileWriter.Scripting.csproj

filewriter.scripting.csproj

Before getting into the functionality of the .Scripting library, there are three classes that need to be created to support three important aspects of this app:

  • WriterInput.cs - Represents the input that will be provided to the script
  • ConsoleOutput.cs - Represents the output the script will respond with
  • OutputPath.cs - Allows the base path that files are written to to be configurable

FileWriter.Scripting/WriterInput.cs

writer-input.cs

FileWriter.Scripting/ConsoleOutput.cs

console-output.cs

FileWriter.Scripting/OutputPath.cs

output-path.cs

Now, all of the infrastructure needed to define the PowerShell interactions is in place. The logic for these interactions is contained in ScriptExtensions.cs.

First up, if a script ends in an error state, we want to be able to extract that data in an consistent, readable manner. This is done by the GetCategoryInfo(this ErrorRecord error) extension method:

GetCategoryInfo

After the invocation of a command is complete, we need to be able to extract the details of the command execution from the powershell stream, which is handled by GetPowershellOutput(this PowerShell ps):

GetPowershellOutput

Creating a PowerShell runspace, invoking a command, and returning the output is a task that can be isolated, so it is defined by the ExecuteCommand(this Command command) extension method:

ExecuteCommand

Before a command can be created, a script must be read as text from an embedded resource. GetTextFromEmbeddedResource(this string resource) handles this:

GetTextFromEmbeddedResource

Now an extension method, GenerateScript(this WriterInput input), can be written to generate a command that loads the script, and map values provided by a WriterInput object as parameters to the script:

GenerateScript

The final extension method, WriteText(this WriterInput input) pulls everything together. The command is generated, executed, and the resulting output is returned:

WriteText

API

Back to Top

In the previous section, I mentioned that the base path that files are written to should be configurable, and showed an OutputPath class defined. Using the dependency injection mechanism in .NET Core, this can be achieved.

An AppDirectory variable is defined in FileWriter.Web/appsettings.json:

appsettings

An instance of OutputPath is then registered as a Singleton in the ConfigureServices(IServiceCollection services) method of FileWriter.Web/Startup.cs:

ConfigureServices

Now, an API can be written that allows for the following features:

  • GetOutputFiles() - Enumerates all of the files at the output path
  • WriteText([FromBody]WriterInput input) - Executes the WriteText() extension method from the FileWriter.Scripting library, and returns the output
  • RemoveOutputFile([FromBody]KeyValuePair<string, string> path) - Deletes the specified file from the output path

FileWriter.Web/Controllers/AppController.cs

AppController.cs

Client

Back to Top

All that's left now is to create a simple Angular interface. There are 3 pieces to this:

  • Models - provide interfaces for mapping the shape of the data that will interact with the API
  • Service - provides state management and functions for interacting with the API
  • Route - the UI that will allow for this interaction

In a production application, this would all be a lot more complicated, but I've kept it simple for the purposes of this demonstration.

The remainder of the application is pretty self-explanatory. For the most part, I'll allow the remaining code to speak for itself.

FileWriter.Web/ClientApp/src/app/models/console-output.ts

console-output.ts

FileWriter.Web/ClientApp/src/app/models/writer-input.ts

writer-input.ts

The AppService primarily consists of two parts:

  • A private files: BehaviorSubject<string[]> exposed as a read-only Observable for state management
  • Functions that connect the Client to the API

FileWriter.Web/ClientApp/src/app/services/app.service.ts

app.service.ts

FileWriter.Web/ClientApp/src/app/routes/home/home.component.ts

home.component.ts

FileWriter.Web/ClientApp/src/app/routes/home/home.component.html

home.component.html

About

A simple app demonstrating implementing embedded PowerShell scripts in a Web API / Angular app

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages