The Old Way
By definition, creating a PowerShell binary cmdlet library means the resulting file is a dll
- not an exe
- and therefore cannot be executed directly. Instead, it must be imported into and subsequently executed by PowerShell. Debugging a cmdlet library basically involves the same process: Instead of running the application directly, you tell Visual Studio to run PowerShell.exe
, import your dll
, and then you can commence debugging.
The New Way
For months I’ve been watching the development of the new PowerShell Standard Library nuget package because I wanted to start creating cross-platform cmdlet libraries. Six preview versions have been released since August of 2017, but the first RC just came out 10 days ago. Somewhere in there I gave one of the previews a shot and ran into some unexpected problems. At the time, I wasn’t particularly interested in wading through an early adopter jungle, so I set it aside until the package was closer to the finish line. Now that an RC is out, I decided to give it another shot. One again, I ran into an issue, but this time I realllllly wanted to figure it out.
You can read my StackOverflow question for more details, but in a nutshell I set up my PowerShell Core solution just like I would a PowerShell “Classic” solution, as described above, with a few obvious substitutions. Instead of targeting the .NET Framework 4.7, I targeted .NET Standard 2.0. Instead of using the PowerShell.5.ReferenceAssemblies package, I used the PowerShell Standard Library package. Instead of running the library with powershell.exe
, I used pwsh.exe
. In every other respect, the setup was the same. However, when I ran it, I got a FileNotFoundException
on a nuget package reference.
Before I get to my solution, let me just say that I still don’t fully understand why this was happening. Yes, I consistently got a FileNotFoundException
when referencing this SimpleInjector package. And yes, I did find a workaround for that problem. But I’m unable to explain why the same exception didn’t occur when referencing this json.net package. Referencing json.net worked perfectly fine. I know the problem isn’t specific to SimpleInjector because I was able to reproduce it with dummy “hello world” packages I created locally. Perhaps the explanation will become obvious over time as I work more with .NET Core and .NET Standard. For now, it remains a mystery.
Anyway, the solution is simple. First, create a post-build event that includes this statement: dotnet publish --no-build
. Second, in the cmdlet project’s “Debug” properties, change the “Application arguments” such that the published dll is loaded into your PowerShell context. Using the example project I used in my Stackoverflow question, I changed this:
-NoExit -NoLogo -NoProfile -Command "Import-Module .\MyNetStandardProject.dll"
To this:
-NoExit -NoLogo -NoProfile -Command "Import-Module .\publish\MyNetStandardProject.dll"
Again, the only difference here is that I’m loading the published version of my dll. And with that, the FileNotFoundException
disappeared.