What is an appropriate debugging workflow for Powershell Core modules? - powershell

My company has a .NET Powershell module, written in C# to allow advanced users to automate tasks in our product. Currently it targets Powershell 5 using .NET 4.6.1. We would like to allow customers using other operating systems to use it as well, and as it has no OS-specific code, porting it was straightforward.
However, I cannot find documentation on a debugging workflow that should be followed. In standard .NET Powershell, this was quite simple and required a one-time setup procedure:
Configure the debug executable to be the Powershell path
Set debug arguments to be a short script that loads the module and if appropriate, executes the function that is being tested.
Hit F5
However, this doesn't work for Powershell Core. Because the project depends on NuGet packages, the module registration fails with a dependency error. I was able to figure out another workflow but it's a bit more obtuse:
Navigate to the project directory
Execute dotnet publish -f netstandard2.0 -c debug
Execute Import-Module ./bin/Debug/netstandard2.0/publish/MyModule.dll
Execute $pid to find the PID
Attach to the PID via Attach to Process in Visual Studio
This works and I have debugged a few issues with this method, but it's not the most pleasant or efficient way to do it. I believe that there must be a better way that is just not well documented.

I originally came up with a script based approach that you can see in this post's history, but what I didn't know at the time was the CopyLocalLockFileAssemblies property which makes the debug directory look like how it used to look when working on .NET Framework. You just need to add this to your .csproj in a <PropertyGroup>:
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
Then, the debugging setup is just the same as any other .NET module loaded into a third party application:
Right click on your Powershell module project and click properties
Select Debug
Set Launch to Executable
Executable: C:\Program Files\PowerShell\6\pwsh.exe
Arguments: -NoExit -Command "Import-Module C:\dev\my-module\bin\Debug\netstandard2.0\my-module.dll"
Set your module as the startup project
Hit F5 to begin debugging.

Related

How to publish a Console Application that uses 3rd party references?

My problem might seem specific, but in fact it is probably very general: How to publish a Console Application that uses 3rd party references?
I am using Visual Studio 2015 to make a Console Application called Gdx2PostgreSql programmed in Visual Basic. The application is reading data in a Gdx-file (output from a GAMS program, www.gams.com) and writing the data to a PostgreSql database. The interface to PostgreSql is handled by NpgSql, www.npgsql.org. NpgSql is referenced as
\\dtu-storage\hela\Documents\Visual Studio 2015\Projects\GDX to PostgreSQL 2\packages\Npgsql.3.1.7\lib\net451\Npgsql.dll
The program functions correctly when it is executed in Debug mode inside Visual Studio.
I have to be able to run the program from the command prompt in a CMD window. Moreover, I have to be able to run the program by spawning from a GAMS program using the GAMS syntax
Execute 'Gdx2PostgreSql "FileName.gdx" "CaseName"';
I have published the program and run the setup file installing the program. But when I run it in a CMD window I get the error:
'Gdx2PostgreSql' is not recognized as an internal or external command, operable program or batch file.
I get the same error message when spawning from my GAMS program.
Being rather desperate I have tried renaming the file setup.exe in the Publish-folder to Gdx2PostgreSql.exe. When I use this file I get:
Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Npgsql, Version=3.1.7.0, Culture=neutral, PublicKeyToken=5d8b90d52f46fda7' or one of its dependencies. The system cannot find the file specified.
That is, NpgSql is not known to the program.
As I see it, I need to have one EXE-file that holds all what is needed - especially because my program should be able to run on other PCs, too.
Can anyone help me make my program Gdx2PostgreSql function?
Finally, I should mention that I have made other programs reading Gdx-files and using NggSql to write to PostgreSql. These programs function correctly, but they are Windows Forms Applications – and not Console Applications.
Console applications aren't really any different from winforms applications - you have to distribute the EXE along with any DLLs it depends on - in the same directory. As mentioned in the comment, after building your program you should be able to find everything you need under bin/Debug (or Release).
Regarding why your Gdx2PostgreSql isn't being found, that's likely a problem of path - try running your program with an absolute path, or cd'ing into bin/Debug (or Release) before executing it.

Creating application installers with PowerShell

Hi I'm wondering if it's possible to create application installers for MSI's. What I want it to do is when I run an MSI I want to be able to run it in it's own process so I can reference it via it's process ID so I can send various keys to it so it installs the way I want it too.
I can code in both C and Java but for the Sys Admins would be good if I could code it in Powershell for them. Also I've seen other installers that can detect when the next instance of the install screen appears so it immediately send the new command keys, well appears that way.
Any advice is welcomed.
MSI's traditionally allow for admins to provide an answer file or arguments using msiexec.
See this q/a on SuperUser or this SO Q/A for more info.
You can then use PowerShell to call the exe's by using the 3rd party Windows Installer PowerShell Module
.
[The Windows Installer PowerShell Module] Exposes Windows Installer functionality to PowerShell, providing means to query installed product and patch information and to query views on packages.
for example:
install-msiproduct .\example.msi -destination (join-path $env:ProgramFiles Example)
See this page for additional examples.
If you need to send keystrokes to the msi gui; you could look in to the Windows Automation Snapin for PowerShell. I have never used this personally.

Nuget Command-line install is not launching Install/Init scripts

I was trying to use Nuget as a software deployment system (repository, versioning and delivery) - idea from Octopus. Previously I was packaging ASP.NET sites into a self-extracting RAR archives with a .CMD startup scripts embeded. Now I'm trying to use Nuget creating puckages during automated build. The issue is that the package installation scripts (tools\Install.ps1 or tools\Init.ps1) do not execute if the package is being installed using command line:
nuget.exe install <package_id> -OutputDirectory <install_folder> -source <local_repo>
Same scripts are able to execute when package installed from Visual Studio Package Manager or Console.
I do not see why this shouldn't be possible given omnipresence of PowerShell.
Am I missing something or this is behaviour by design? Will appreciate you help.
Yes, we did consider MSDeploy but we already have install scripts that do the same thing and give more control and we need some strong package management and repository for build artifacts (something that Java folks do with Maven).
As of today, the powershell scripts are not invoked from doing installations from command line.
One reason for this is that, in general, most of the install/init actions are tied to dte and the visual studio project and doesn't add much value to be able to run it from outside VS.
We have a backlog item for enabling support for exe based scripts too in addition to powershell.

Run part of a build script on a windows box and the rest on linux

My build script runs on linux and invokes things like gcc, shell scripts, etc.
Part of the solution is written in mono and could be compiled easily on linux.
But I want to obfuscate the code. Not manually, but as part of the build process.
Therefore I need to invoke Dotfuscator and Dotfuscator so far only runs on windows.
Is there a good solutions to invoke command line based workers/build scripts remotely from linux on a windows machine? I don't just want to run a command remotely, but also pass files along.
Like a windows service that is accessed using simple curl-uploads of a tar file, creates a temp folder for each concurrently connected client (or blocks concurrent calls) and unpacks the file, invokes something on these files and packages the result again as tar file to give it back to the caller? And clears the temp file even in case of failures?
Maybe someone knows a good solution that saves me from writing this myself!
It should not be so uncommon that a build process spans multiple platforms, yet common build server answers I found mainly talk about only one build script.
Also think about running e.g. the nsis setup builder from a linux driven build script, if part of your solution has a tiny windows component

Do PowerShell scripts run under Mono?

Do PowerShell scripts run under Mono?
I would like to run them on a Mac.
There is an open source version of PowerShell called Pash designed for Mono. It is not complete, but may be able to do what you need:
http://pash.sourceforge.net/ (this project has not been active for quite some time)
Checkout the re-start at: Pash-Project on GitHub.
Powershell has now been open-sourced and is available here.
As of right now it is V6.0 alpha. I've been running it on OS X for a lot of file operations and it has been working very well.
Note that you may need to install .Net Core to get Powershell to behave properly. Also note that system.management.automation.runspaces works right out of the box (for runspacepools).
The powershell.exe stub is actually a native win32 program, not a managed assembly. It may be possible in the future to host the System.Management.Automation assembly in Mono, but I'm fairly sure it doesn't work at the moment.