Major Update: for Powershell v7 and .NET Core - see below
Another Update: about using VS Code (rather than Visual Studio) - see further below
The other alternative is to make a full-on PowerShell module. Here's the quickie way to do that:
- Create a new Class Library Solution
- NuGet in
Microsoft.PowerShell.5.ReferenceAssemblies
NOTE:
The Microsoft.PowerShell.5.ReferenceAssemblies NuGet package is only compatible with the .NET Framework (up to v4.8) and not with .NET Core. This can be rectified by targeting .NET Standard (see "Major Update" below)
- Create a simple POCO class (just as a demo) like:
My Greeting class:
public class GreetingClass
{
public string Greeting { get; set; }
public string ToWhom { get; set; }
}
- Then create a Cmdlet class that inherits from
System.Management.Automation.Cmdlet and comes with a few PowerShell-specific attributes:
Here's mine:
[Cmdlet(VerbsCommon.New, "Greeting")]
[OutputType(typeof(GreetingClass))]
public class NewGreeting : Cmdlet
{
[Parameter(Mandatory = true)]
public string Greeting { get; set; }
[Parameter]
[Alias("Who")]
public string ToWhom { get; set; } = "World";
protected override void ProcessRecord()
{
base.ProcessRecord();
WriteVerbose("Creating and returning the Greeting Object");
var greeting = new GreetingClass {Greeting = Greeting, ToWhom = ToWhom};
WriteObject(greeting);
}
}
- In order to debug it, open the
Debug tab project properties and set:
- Start external program:
C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe
- Command line arguments:
-noprofile -noexit -command "import-module .\yourProjectName.dll
Now press F5. A PowerShell console will come up. Since you imported your module, the New-Greeting cmdlet is loaded. So this all works:
PS C:\> New-Greeting -Greeting "hello there" -ToWhom World
resulting in:
Greeting ToWhom
-------- ------
hello there World
But, your cmdlet is a full PowerShell cmdlet so it can get in on the pipeline. This:
PS C:\> New-Greeting -Greeting "What's new" -ToWhom Pussycat | Format-List
Will result in:
Greeting : What's new
ToWhom : Pussycat
Since you start up a PowerShell session when you press F5 and load your module, you can set breakpoints in your code, single-step, etc. within the debugger.
You get all the normal PowerShell goodness. You can use -Who as an alias for -ToWhom. The -Greeting parameter is described as Mandatory, so if you forget it, the console will prompt you.
You can also expose methods on your POCO class. For example, if you add this method to the GreetingClass:
public void SayHello()
{
Console.WriteLine($"{Greeting} {ToWhom}");
}
You can do this within PowerShell:
PS C:\> $greet = New-Greeting -Greeting Hello -Who World
PS C:\> $greet.SayHello()
and get this as a result:
Hello World
I learned a lot of this from: https://www.red-gate.com/simple-talk/dotnet/net-development/using-c-to-create-powershell-cmdlets-the-basics/
You get basic Get-Help help auto-magically from PowerShell, but if you follow along the Red-Gate demos (from the link above), you will learn how to get rich Get-Help help from standard C# XML Comments (from the XmlDoc2CmdletDoc NuGet package).
The XML Comments to Get-Help capabilities of XmlDoc2CmdletDoc are concisely described on the GitHub ReadMe page for XmlDoc2CmdletDoc: https://github.com/red-gate/XmlDoc2CmdletDoc
Major Update
I got this working using a .NET Standard assembly (i.e., .NET Core compatible) and the new Core-based PowerShell. (PowerShell v7). For the most part, everything above is still mostly valid.
- Using Visual Studio 2022
- Create a Class Library - C# (not .NET Framework) project
- Set the Target Framework to
.NET Standard 2.0
- NuGet in
Microsoft.PowerShell.5.1.ReferenceAssemblies
Getting it to debug is more difficult (because of the wacky new Debug setup for .NET Core applications):
- Right-click the project in the Solution Explorer and choose Properties
- On the Debug tab, choose the Open debug launch profiles UI link
- In the Launch Profiles window that pops up:
- Click the Create a new profile icon (the top-left-est icon in the window)
- Choose it to be Executable
- Set the Executable name to be
C:\Program Files\PowerShell\7\pwsh.exe (or wherever you have PowerShell 7 installed)
- Use the same Command Line Arguments as above (
-noprofile -noexit -command "import-module .\yourProjectName.dll)
- Once you have that set up, rename the profile (the right-most icon) to be exactly the same as the default profile that's already there.
That should do it. The same .NET Standard assembly will now work with both the traditional Windows PowerShell and the new-fangled PowerShell 7 (I'm using version 7.2.8).
Another Update: Using VS Code
To use this with VS Code:
- Open a command prompt
- Create the project in a new folder:
dotnet new classlib -f netstandard2.0 -n [YourProjectName]
- Change to the newly created directory
- NuGet in the
Microsoft.PowerShell.5.1.ReferenceAssemblies package using:
dotnet add package Microsoft.PowerShell.5.1.ReferenceAssemblies
- Rename the sample CS file that got created to “Greeting.cs”
- Open the folder in VS Code
- Set things up so that it compiles a C# project in the normal fashion
- Add the following as
launch.json:
{
"version": "0.2.0",
"configurations": [
{
"name": "PowerShell cmdlets: pwsh",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
"program": "C:\\Program Files\\PowerShell\\7\\pwsh.exe",
"args": [
"-noprofile",
"-noexit",
"-command",
"import-module .\\bin\\Debug\\netstandard2.0\\PowerShellVsCode.dll"
],
"cwd": "${workspaceFolder}",
"stopAtEntry": false,
"console": "externalTerminal"
}
]
}
If you want to use the XmlDoc2CmdletDoc NuGet package, you'll need to NuGet it in:
dotnet add package XmlDoc2CmdletDoc
And you will need to add the following line to the "args:" under "tasks:" in tasks.json:
"/property:GenerateDocumentationFile=true",
If I messed something up in these instructions, let me know in a comment.
publicmethods should be accessible. What isn't working with the code you posted?System.Management.Automation.Cmdlet, and add some attributes. The class's public properties become cmdlet parameters. You can get fullGet-Helpsupport from mostly standard C# XML comments. Take a look at: red-gate.com/simple-talk/dotnet/net-development/…