PowerShell Binary Module - Could not load Automation module in PS 5.1 - powershell

I'm working on a PS Binary module and I developed it using PS 7.1. I tried importing the dll into PS 5.1 and I got the following error:
ipmo : Could not load file or assembly 'System.Management.Automation, Version=6.0.4.0, Culture=neutral,
PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.
My .csproj file is as follows:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Library</OutputType>
<TargetFramework>netstandard2.0</TargetFramework>
<AssemblyName>assemblyName</AssemblyName>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PowerShellStandard.Library" Version="5.1.0-preview-06">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="System.Management.Automation" Version="6.0.4" />
</ItemGroup>
</Project>
This project is created by using the PowerShell Module Template via dotnet cli: dotnet new psmodule.

You did it backwards. If you want a module to be compatible with both Windows PowerShell and PowerShell Core, you need to develop it against PowerShell 5.1, then use the Portability Analyzer to determine how portable your module is.
System.Management.Automation houses most, if not all, of the PowerShell specific constructs. If you build against PowerShell Core, PowerShell 5.1 is NOT going to have the same version of that assembly loaded into memory. Hence, it cannot find the assembly version it is looking for.
Here is some more information you may find useful on the subject.
Edit:
If your module is not compatible both ways, you can develop it for PowerShell 5.1 anyways and use the WindowsCompatibility module from PowerShell Core which should implicitly make use of constructs only available in Windows PowerShell. There are some caveats, the module must not use "live" objects (like CIM, remote connections, etc.) and the module will effectively remain "Windows-only" since you can't run PowerShell 5.1 on Linux or MacOS.

Related

Why doesn't Uninstall-Package launch the Chocolatey uninstall script?

So I've been trying out OneGet for a while and wanted to create packages. The biggest problem I've run into is that OneGet does not seem to actually execute the uninstall script provided into the package.
This is the .nuspec file and the script files I've been testing with:
<?xml version="1.0" encoding="utf-8"?>
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>notepadplusplus</id>
<version>6.8.5</version>
<title>Notepad++</title>
<authors>Notepad ppl</authors>
<owners>King Kong</owners>
<projectUrl>https://notepad-plus-plus.org/</projectUrl>
<iconUrl>http://i1-win.softpedia-static.com/screenshots/icon-60/Notepad-plus-plus.png</iconUrl>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>Notepad++ is a free (as in "free speech" and also as in "free beer") source code editor and Notepad replacement that supports several languages. Running in the MS Windows environment, its use is governed by GPL License.</description>
<summary>Notepad++</summary>
<tags>notepad notepad++ texteditor text editor</tags>
</metadata>
<files>
<file src="tools\chocolateyInstall.ps1" target="tools\chocolateyInstall.ps1" />
<file src="tools\chocolateyUninstall.ps1" target="tools\chocolateyUninstall.ps1" />
</files>
</package>
chocolateyinstall.ps1:
Install-ChocolateyPackage 'notepadplusplus' 'exe' '/S' 'https://notepad-plus-plus.org/repository/6.x/6.8.5/npp.6.8.5.Installer.exe'
chocolateyuninstall.ps1:
Get-WmiObject -Class Win32_Product | Select-Object -Property Name > C:\foo.txt
I use the uninstall script just to test if the script is even run but it's not. When I do the same to the install script I can clearly see that it hit the script and actually create the text file.
So my question is does the oneget module in Windows 10 not use the script files at all? Since Doing an Uninstall-package seems to execute the uninstall file if the name provided is the exact same as in the registry. For example doing the command Uninstall-package notepad++ will uninstall notepad++ even though it was installed with the name notepadplusplus.
The current OneGet Chocolatey provider is a non-fully featured prototype from March 2014 (yes, 2014), written by Microsoft. The official provider is not done. Look for that to be finished sometime in 2017.
The Chocolatey team uses a prioritization schedule that allows for quickly reprioritizing when demands shift, so it is hard to provide better estimated dates on this. If anyone is interested in picking this up to finish, please comment below.
We'll make an official announcement in the mailing list and in the newsletter when it is ready.
Until it is announced, I would expect it to be an early preview and pretty much consider everything about it broken (including security fixes that have been added since 2014). It's based currently on Chocolatey from nearly two years ago and not even fully functional to the features available then.
HTH

Bug in Wix? Is ps:SnapIn writing to the wrong registry key with PowerShell 3.0?

We have a PowerShell snapin that requires version 3.0 of PowerShell to function. So we used the following file element in a WiX (3.8) file:
<File Id="MySnapin.dll"
Name="MySnapin.dll"
Assembly=".net"
KeyPath="yes"
Vital="no"
Checksum="yes"
DiskId="1"
Source="$(var.FilesPath)\Bin\MySnapin.dll"
AssemblyApplication="MySnapin.dll">
<ps:SnapIn Id="MySnapin"
Description="This is a PowerShell snap-in"
Vendor="My Company Inc."
RequiredPowerShellVersion="3.0">
<ps:FormatsFile FileId="MySnapin.format.ps1xml" />
</ps:SnapIn>
</File>
However, when installing this the snapin cannot be found in powershell (Get-PSSnapIn -Registered). When examining the registry it turns out that the snapin has been registered in HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\3\PowerShellSnapIns\MySnapin. But when running installutil.exe on the DLL, the registration ends up in HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Microsoft\PowerShell\1\PowerShellSnapIns\MySnapin, and powershell finds it properly. Is this a bug in WiX Toolset, or am I doing something wrong here?
Where are the registrations really supposed to go?
Yea this sounds like a bug, so you might want to report it to the WiX maintainers, but there is better way.
The recommended way to add cmdlets and functions is through PowerShell Modules. Snap-ins are the older way to extend PowerShell and while still supported are not recommended. If you do not need to support adding your cmdlets to older versions of PowerShell use a module.
Modules are somewhat easier to deploy than snap-ins. Basically you can put them anywhere, however if you want users to be able to load them by name they need to exist on the PSModulePath environment variable. Your installer would add your files and update the PSModulePath variable to include a Modules folder from your install folder. Then users will simply be able to call Import-Module MyModule to load them. Also, see the documentation on PSModulePath.
This blog post contains a detailed walkthrough of how to write a WiX installer to do this. It also has instructions on how to check that the required PowerShell version is installed. Basically, you are going to check the under both those registry keys you mentioned for the PowerShellEngine\PowerShellVersion value.

Register all dll in a directory in GAC Silently in powershell

I have to register all .dll files in a directory to GAC silently without any screen popup.
How can i do this using powershell.
Please help :)
I am the author of PowerShell GAC. With PowerShell GAC you don't need gacutil and you can install all dlls in a folder to the GAC with the following command.
# Can only be run from an elevated prompt
Add-GacAssembly C:\Folder\*.dll
Use gacutil.exe.
& gacutil.exe -i <strongly named DLL>
Note - the DLL must meet the requirements of being installable into the GAC.
The .Net Framework already contains methods to register components in the GAC. No need to add SDKs and third party plugins.
[System.Reflection.Assembly]::Load("System.EnterpriseServices, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a")
$publisher = New-Object System.EnterpriseServices.Internal.Publish
# For installation
$publisher.GacInstall("C:\Components\MyComponent.dll")
# For removal
$publisher.GacRemove("C:\Components\MyComponent.dll")

How to make nant build 32 bit assemblies

I have a Visual Studio project that was originally configured to build using the Release|Any CPU build configuration.
I need to change this so all the assemblies are built using Release|x86.
I can change this in Visual Studio but how do I specify the equivalent in my nant build script?
EDIT: I am building my assemblies using the csc task.
My experience might be outdated (did this 3 years ago), but the NAnt <csc> documentation still supports it: this is not possible in a simple way.
We've solved this by running corflags on the output assembly after build to set the 32BIT flag. You can do this from NAnt, with the <exec> task. CorFlags is installed as part of the SDK, so you should have it already.
I am using nant 0.92 version. I have solved the problem using platform attribute of csc/vbc compiler tag.
<csc target="library" output="xxxx.dll" platform="x86" verbose="true" debug="true">
<vbctarget="library" output="xxxx.dll" platform="x86" verbose="true" debug="true">

NUnit in TFS 2008 and .NET 4.0

Is there a way to set /framework:net-4.0 in nunit-console.exe.config like in GUI? Or any other way to run NUnit tests with MSBuild Community Tasks?
I thought that this solution was applicable to NUnit GUI only, appearently it is applicable to any .NET application. So to answer my own question, all you have to do is
add <startup>
<supportedRuntime version="v4.0"/>
</startup> to nunit-console.exe.config and you don't have to specify it as a command argument.