Register Powershell SnapIn to specific version of Powershell - powershell

I am trying to run an Exchange Management Shell script via managed code.
Our PowerShell version is version 4.
I am trying to use the runspaceConfiguration.AddPSSnapin() method to add the exchange SnapIn Microsoft.Exchange.Management.Powershell.E2010, however this line fails, giving :
no snapins have been registered for Powershell version 4.
A quick Get-PSSnapIn -registered shows the SnapIn is installed but registered to PS version 1.
In regEdit, I have found the registry key for the snapIn for PowerShell v1, used the export function to script the key, changed the target version to 4 and ran the export command, which has created the new key '4' under PowerShell as expected, with the snapin details copied across. However I still get the 'no snapins have been registered for Powershell version 4.', even though the key is there in the registry.
Is there something else I should be doing to register the snapin to PowerShell version 4?
Thank you for your time.

You are correct in that this is a 32/64 bit build issue. After I set the target build to x64 in VS and redeployed, all magically seemed to work fine.
The error message regarding Powershell versions is a massive Red Herring in this case.

Related

Install-Module not available - not recognized as a name of a cmdlet

I'm trying to take advantage of the PowerShell Gallery which requires Install-Module. For some reason I cannot get this to work on any computer I have access to:
Install-Module: The term 'Install-Module' is not recognized as a name of a cmdlet, function, script file, or executable program.
I tried this on a Windows 8.1, Windows 10 and even installed PowerShell 7.1 on the Windows 10 computer. I see that a lot of people have this issue, but other than installing WMF (which seems to already be included with Win10) I don't see any useful suggestions.
I don't have a lot of experience with PowerShell, and definitely not managing it, so I'm curious if anybody has an idea as to why this is not working.
Edit 1:
I seem to have the PowerShellGet module in the following directories:
C:\Program Files\WindowsPowerShell\Modules
C:\Program Files\PowerShell\7\Modules
and the $env:PSModulePath variables contains C:\Program Files\PowerShell\Modules;c:\program files\powershell\7\Modules;C:\Program Files\WindowsPowerShell\Modules;C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules
Edit 2:
This may be related to the __PSLockDownPolicy environment variable, that was set to 4 on all of the affected computers. I was able to figure this out by attempting to manually load the PowerShellGet module, which yielded an error that hinted at this.
After removing that environment variable, it seems to work.
As you've discovered yourself, it was the presence of machine-level environment variable __PSLockDownPolicy that prevented Install-Module from running (see below for general prerequisites).
This undocumented environment variable, effective on Windows only, is for security reasons only respected if defined at the machine level via the registry (rather than as a per-user or process-specific variable) and can be used to restrict what is allowed in a PowerShell session.
Values 4 through 7 result in PowerShell operating in constrained language mode, where only a handful of pre-approved .NET types may be used, which as a result prevents the PowerShellGet module that contains the Install-Module from loading - see the conceptual about_Language Modes help topic.
You can check what language mode is in effect in a given session by executing $ExecutionContext.SessionState.LanguageMode; in constrained mode, the result is ConstrainedLanguage; FullLanguage indicates that no language restrictions are in place.
Looking at PowerShell's source code, the fact that this variable is checked inside a method named GetDebugLockdownPolicy() suggests that it isn't officially supported.
For more information, see this archived blog post.
The simplest way to remove this restriction is to delete the environment variable, by running the following from an elevated PowerShell prompt:
Remove-ItemProperty 'HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager\Environment' __PSLockdownPolicy
One mystery remains:
As you state, importing the PowerShellGet module explicitly, with Import-Module PowerShellGet showed you that the real problem was not that the Install-Module command didn't exist, but that its enclosing module failed to load.
Doing so revealed that yet another module was the problem, namely the PackageManagement module that PowerShellGet depends on; Import-Module PackageManagement finally reveals: Cannot set property. Property setting is supported only on core types in this language mode, which implies that the (constrained) language mode was the problem.
The mystery is the error message reported in your question: Install-Module: The term 'Install-Module' is not recognized as a name of a cmdlet, function, script file, or executable program.
I see a different error message, both in Windows PowerShell 5.1 and PowerShell (Core) 7.1.2, when the constrained language mode is in effect, i.e. when $ExecutionContext.SessionState.LanguageMode reports ConstrainedLanguage:
Install-Module: The 'Install-Module' command was found in the module 'PowerShellGet', but the module could not be loaded. For more information, run 'Import-Module PowerShellGet'.
This error message makes it more obvious what the problem is, and would probably have led to a faster diagnosis.
The following contains general information that is unrelated to the above:
Installing / troubleshooting of the PowerShellGet module that provides the Install-Module command:
Install-Module is a (function-based) cmdlet that comes with Windows PowerShell 5.0 and 5.1 as well as all versions of PowerShell (Core) (v6+), as part of the PowerShellGet module.
If your computers do meet these criteria, the implication is that your PowerShell installation has been corrupted in one or both of the following ways:
The PowerShell get module was removed (or renamed) from its default location
(C:\Program Files\WindowsPowerShell\Modules\PowerShellGet in Windows PowerShell,
C:\Program Files\Powershell\7\Modules\PowerShellGet in PowerShell (Core) 7.x, on Windows).
Either reinstall PowerShell or try the manual installation instructions linked to below.
The $env:PSModulePath environment variable is missing an entry for the parent directory of the respective default location (that is,
C:\Program Files\WindowsPowerShell\Modules /
C:\Program Files\PowerShell\7\Modules). Without this entry, PowerShell cannot find the PowerShellGet module (by name only).
Manually update the machine-level definition of environment variable PSModulePath via sysdm.cpl, tab Advanced, button Environment Variables... to include the applicable directory.
If your computers do not meet these criteria, you have two choices:
If you can, upgrade the Windows PowerShell version to v5.1 or switch to PowerShell (Core).
Alternatively - if your Windows PowerShell version is 3 or 4 - install PowerShellGet manually, as per the official instructions.
Note: You may have to have access to at least one computer that already has a functioning copy of PowerShellGet to source the manual installation from.

Update powershell to the latest revision

I have two different revision of PowerShell in different machines. The local one have the following one:
Major
Minor
Build
Revision
5
1
17763
1007
And the virtual machine has the following one:
Major
Minor
Build
Revision
5
1
17763
771
As you can see that it has the same: Major, Minor, and Build values except the Revision values. I am not sure if it is behind the failure of the command:
Register-PSRepository -Name $RepoKeyName -SourceLocation $RepoKeyValue
-PublishLocation $RepoKeyValue -InstallationPolicy Trusted -Verbose
The above snippet works fine on the local machine but not on the virtual machine and it fails in the virtual machine with the following error:
parameter 'SourceLocation' is an invalid Web Uri. Please ensure that it meets the Web Uri requirements.
And this is why I want to update the PowerShell in the virtual machine to the latest revision value. How to do it?
If you have Microsoft's winget app (Windows package manager), you can run the following command to update to the most recent version of PowerShell:
winget install Microsoft.PowerShell
If you're running Windows 11 or have updated App Installer in Windows 10.
Update PowerShell using Windows Package Manager (winget)
winget upgrade Microsoft.PowerShell
You also can install PowerShell by using below command via winget
winget install Microsoft.PowerShell
Learn more:
winget in Microsoft Docs
winget in GitHub repository
Run the following command from command prompt wait till gets downloaded, and it will prompt to installation wizard follow the instructions to install it.
Invoke-Expression "& { $(irm https://aka.ms/install-powershell.ps1) } -UseMSI"
You can never update Windows PowerShell installations on demand - except, in the past, if you upgraded to a new major version, but v5.1 is the last version that will ever be released, given that Windows PowerShell is in maintenance-only will see no new development, unlike its successor, the cross-platform PowerShell (Core) 7+ edition.[1]
Note:
While switching to the PowerShell (Core) edition[1] - where all future development effort will go - is advisable in general, doing so is not something to be done casually and requires a deliberate decision:
PowerShell (Core) is mostly, but not fully backward-compatible with Windows PowerShell, and certain cmdlets are unavailable, except via a compatibility feature that has its limitations both in terms of performance and type fidelity.
PowerShell (Core) is installed alongside Windows PowerShell and has different CLI (pwsh.exe rather than powershell.exe) and different SDKs (see this answer); also, targeting PowerShell (Core) via PowerShell remoting requires explicit configuration - see this answer.
Windows PowerShell-specific considerations:
Revisions of v5.1 are delivered as part of Windows updates.
However, you can selectively update the PowerShellGet module, in which the problem-causing Register-PSRepository command is defined:
While you normally would just run Update-Module PowerShellGet, a different approach is required the first time, when switching from the bundled PowerShellGet module to the latest version from the PowerShell Gallery:
Open an elevated session (Run as Administrator).
Execute the following (add -Verbose to get detailed information):
Install-Module PowerShellGet -Force
The -Force is to enable installation even though a module by that name is already installed; you may still see a prompt about downloading the NuGet package provider.
Note that the old PowerShellGet version will linger in a different location, but the new one will take precedence over it.
After this initial switch to the gallery-installed version, you'll be able to use
Update-Module PowerShellGet for future versions.
You can use the Get-Command cmdlet to discover a given command's module of origin; e.g.:
PS> (Get-Command Register-PSRepository).Module
ModuleType Version PreRelease Name ExportedCommands
---------- ------- ---------- ---- ----------------
Script 2.1.4 PowerShellGet {Find-Command, Find-DscResource, Find-Module, Find-RoleCapability…}
[1] PowerShell (Core) 7+ versions can be updated on demand - however, as of v7.2.x, PowerShell (Core) doesn't come with Windows and initially requires manual installation. However, you can now install and update it via the Microsoft Store application or, programmatically, using winget.exe (which comes with the App Installer Microsoft Store application, which recent versions of Windows ship with):
Initial installation:
winget install Microsoft.PowerShell
Later upgrade:
winget upgrade Microsoft.PowerShell
Note: Use Microsoft.PowerShell.Preview to install / upgrade the latest preview version instead.
Solution1:
Go to this link:
https://github.com/PowerShell/PowerShell/releases/
Find Assets and click on Assets word.
Download and install .msi link.
Solution2:
Go to this link for download Windows Package Manager:
https://github.com/microsoft/winget-cli/releases
Find Assets and click on Assets word.
Download : Microsoft.DesktopAppInstaller_8wekyb3d8bbwe.msixbundle
Execute the downloaded file and click on update.
Open your command prompt or powershell and execute this command on it:
winget install Microsoft.PowerShell
If you have Mircrosoft.PowerShell execute this command:
winget upgrade Microsoft.PowerShell
For figure out your powershell version: execute host command in your powershell.

Service Fabric/Jenkins integration issue

I am trying to automate deployment to Azure Service Fabric with Jenkins and ServiceFabric PowerShell extension. Jenkins ServiceFabric plugin is not a good option in my case due to lack of control and flexibility over deployment process.
I've faced following issue - Jenkins can't recognize SF PowerShell cmdlets
Connect-ServiceFabricCluster : The term 'Connect-ServiceFabricCluster'
is not recognized as the name of a cmdlet, function, script file, or
operable program. Check the spelling of the name, or if a path was
included, verify that the path is correct and try again
ServiceFabric setup is correct because tt works like a charm when I run the script locally from PowerShell.
So, I've tried to run Jenkins locally instead of service mode as suggested in different posts over the internet, but this haven't resolved the issue.
The other things i've tried:
run the script with self-elevation to admin
run x86/x64 powershell modes
run the script via calling PowerShell exe from cmd runner instead
powershell plugin
forcing "unrestricted" mode
double-dot before script name
I'm still receiving the same result.
So, I tried ServiceFabric Python Cli as an alternative, but faced the other issue - it returns "Bad SSL handshake" on "sfctl cluster select" with certificate, which worked with PS ServiceFabric cmdlets locally
Any ideas?
This is similar to Azure/service-fabric-issues issue 491 which was about a mismatch between the Azure Service Fabric SDK and the Service Fabric runtime.
For instance:
The 2.7 SDK will work against a version 6.0 cluster, but the task will not work on with the 2.8 SDK installed on the agent.
Plus:
Service Fabric PowerShell cmdlets requires PowerShell 3.0 or higher.
Service Fabric uses Windows PowerShell scripts for creating a local development cluster and for deploying applications from Visual Studio. By default, Windows blocks these scripts from running.
To enable them, you must modify your PowerShell execution policy. Open PowerShell as an administrator and enter the following command:
Set-ExecutionPolicy -ExecutionPolicy Unrestricted -Force -Scope CurrentUser
So: if that script is working locally, but not through a Jenkins job on a Jenkins agent, look for differences between the local execution environment (where it is working) and the Jenkins one (where it fails).
The user might not be the same and/or the runtime version might not be compatible with the SDK version.
Do you have Jeknis PowerShell Plugin installed in your system ??
if so can you add your commands into the Power Shell dialog box and see if it works :)

Issues with Save-AzureRmProfile

I have created virtual machine in Azure and selected Windows Server 2012 R2.
I have installed windows PowerShell using the Web platform installer. When I try to run the following command:
Save-AzureRmProfile -Path C:\MyPath\myfile.json
It throws the error:
The term 'Save-AzureRmProfile' is not recognized as the name of a
cmdlet, function, script file, or operable program. Check the
spelling of the name, or if a path was included, verify that the path
is correct and try again.
I have tried to follow this link here by adding environments variables but no help. Has anyone solved this issue?
Save-AzureRmProfile works on version 3.7. You could use the following cmdlet to check Azure PowerShell version.
Get-Module -ListAvailable -Name Azure -Refresh
You could download 3.7 version msi installer from this link.
You have to Install the Azure PowerShell cmdlets. I suggest you to install it using the latest MSI from this site.
It looks like the Save-AzureRmProfile cmdlet has been replaced by Save-AzureRmContext. I found that information here.
The name of the cmdlet was changed in 4.0, you can see all the changes in 4.0 here: https://github.com/Azure/azure-powershell/blob/preview/documentation/release-notes/migration-guide.4.0.0.md
Unfortunately, the name of the cmdlet was changed without an alias for backward compatibility in version 3.8, per this issue: . This is actually a bug we will be pushing out a version 3.9 which is identical to 3.8, except that the two profile cmdlets (Save-AzureRmProfile, Select-AzureRmProfile) remove this breaking change
Save-AzureRmContext and Import-AzureRmContext can be used for same purpose on Version 4.0
Usage is same!

TFS post build powershell script not seeing commands from imported module

We have a TFS build process using a custom template. The build works fine with the crm solution files successfully being created. We are then attempting to run a powershell script on the post build. This script imports a module. But the commands in the module are not being exposed. Whenever we attempt to invoke a command, we get an error. Along the lines of
The term 'Get-XrmSolution' is not recognized as the name of a cmdlet,
function, script file, or operable program.
It doesn't matter which command we use in that module, we get the same kind of error.
To troubleshoot, we have logged onto the build server under the identity of the build account and can successfully run the script we are attempting to run.
Putting some more output into the script to troubleshoot...
Get-Module lists Xrm.Framework.CI.PowerShell. - Good.
Get-Command -Module "Xrm.Framework.CI.PowerShell" returns nothing. From the console, a number of commands are listed.
Is there something we need to do with the running of powershell post build scripts to enable the contents of an imported module to be seen?
Watch out for the bitness of PowerShell invoked by MSBuild and likewise, the bitness of MSBuild launched by Visual Studio. Certain modules only run in either 32-bit or 64-bit PowerShell and not both. You want to make sure the correct version of PowerShell is getting launched.
IIRC you have to explicitly import the module with no assumption of being loaded on user profile, nor on the script path.
Suppose Module1.psm1 is in the same folder as your script, use something like
Import-Module (Join-Path (Split-Path -Parent $MyInvocation.MyCommand.Definition) 'Module1.psm1')
I had the same problem.
The module was loaded in the 'C:\Program Files\WindowsPowerShell\Modules' folder (64 bits).
It all seemed fine when I logged on as the user, but it failed during TFS build.
Solution: I had to uninstall the module in PowerShell 64 bit and re-install in PowerShell 32 bit.
The module was then installed in 'C:\Program Files (x86)\WindowsPowerShell\Modules' folder.