-
Notifications
You must be signed in to change notification settings - Fork 25
Guidance on writing new PS cmdlets in .net #94
Comments
@a-teece More and more you're going to run into problems building for WinPS, so these should be your targets for compatability: netstandard2.0 - WinPS5.1 and above. May need to make separate net472 and netcore builds depending on what your cmdlets use, very common for instance if you want to use SecureString for instance. It's a tradeoff, if you don't need to do 5.1 compatibility your life will be infinitely easier, you can still add the 5.1 PowerShellStandard and set PrivateAssets to true and it will exclude those DLLs from your module so it's smaller and lighter. |
@JustinGrote I am lucky in that I only need to target PS7+ and can pretty much dictate the version as we currently only use our own cmdlets internally. However I wondered if (given my need to just target PS7+) I should be using a different NuGet package. I believe the Cmdlets in the PowerShell repository don't reference this package so where do they get their Cmdlet base class from and should I be using the same? Having written that and searched a little more I can see they get their base from System.Management.Automation.... So do you think that if targeting PS7+ only this PSStandard package can be skipped and System.Management.Automation used instead. However System.Management.Automation has a LOT more dependencies that this NuGet package so it certainly bloats a small library of cmdlets I really feel some official documentation / guidance on this would help people to write cmdlets. |
@iSazonov I have seen that yes. My scenario is "Implementing a PowerShell binary module" and I do "seek to compile against references to PowerShell without publishing it in their build". In "PowerShell NuGet packages at a glance" it doesn't say which NuGet package to use for this, but the PowerShellStandard.Library is the smallest. The SDK package talks about rehosting PowerShell which I don't need to do, and even System.Management.Automation talks about "minimal hosted implementations". Again as I am not hosting PowerShell these didn't seem appropriate either. For PowerShellStandard.Library it says "PowerShell Standard is intended for writing PowerShell modules, or other code only intended to be run after loading it into a PowerShell process. " which is exactly what I need. That is my scenario, writing cmdlets. The fact that I don't need or care about targeting multiple PowerShell versions isn't really covered. So if I only need to target PS 7 or above (any specific version is fine), I want to compile against .net 5 or 6, I have no need to host PowerShell but I want to produce a small package which NuGet Package can I use. It feels like none. All have drawbacks: |
@a-teece I can say in my experience you can depend against PowershellStandard.Library 7-preview1 fine and mark "PrivateAssets" as true and it will "exclude" most redundancies for a .net6 or .net5 targeted module. For a recent module I did (FSharp) I had to exclude a lot more, here's a good starting place. <?xml version="1.0" encoding="utf-8"?>
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<OutputType>Library</OutputType>
<SatelliteResourceLanguages>en</SatelliteResourceLanguages>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblySearchPaths>$(MSBuildSDKsPath)\..\FSharp;$(AssemblySearchPaths);</AssemblySearchPaths>
</PropertyGroup>
<ItemGroup>
<Compile Include="Library.fs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="fsharp.compiler.service" Version="41.0.1"/>
<Content Include="FSharp.psd1" CopyToPublishDirectory="Always" />
</ItemGroup>
<ItemGroup>
<!-- These are provided by Powershell 7 and dont need to be included in the package -->
<PackageReference Include="System.Management.Automation" Version="7.0.0-preview.1" PrivateAssets="All"/>
<PackageReference Include="System.Configuration.ConfigurationManager" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Drawing.Common" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Resources.Extensions" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Security.Cryptography.Pkcs" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Security.Cryptography.ProtectedData" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Security.Cryptography.Xml" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Security.Permissions" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.Windows.Extensions" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="Microsoft.Win32.SystemEvents" Version="6.0.0" ExcludeAssets="all"/>
<PackageReference Include="System.CodeDom" Version="6.0.0" ExcludeAssets="all"/>
</ItemGroup>
</Project> |
@JustinGrote Thanks for the tip. Basically keep using it, change the target framework and then mark this as private so it doesn't actually ship. Appreciate your input and hints. Be great if something more formal could be done by the team..... |
@a-teece You can see examples in https://github.com/PowerShell/modules |
@SteveL-MSFT @JamesWTruher I think @a-teece has a reasonable ask, seems like the README should be updated to:
For item 2 I feel like there should be a new "meta" nuget package that has all the PWSH assemblies that ship with pwsh, so that it can all be excluded via Private/ExcludeAssets in one go. What is the deal with 7.0.0-preview? What in the API surface has to change to remain 5.1 compatible or is the 5.1.0 PowershellStandard still fine? |
Is this project abandoned and if so what is the new approach to writing PowerShell cmdlets in .net, specifically .net 5.0 and above?
The last release was over a year ago and is marked as a preview!
The text was updated successfully, but these errors were encountered: