I'm trying to use PowerShell from C#. I want to import the Az.Compute module to use cmdlets, but it's not working.
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;
Console.WriteLine(iss.ExecutionPolicy);
//iss.ImportPSModule(new string[] { "Az.Compute" });
iss.ImportPSModulesFromPath(#"C:\Program Files\WindowsPowerShell\Modules\Az.Compute");
Runspace runspace = RunspaceFactory.CreateRunspace(iss);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
Collection<PSObject> servers = ps
.AddCommand("Get-AzVM")
.Invoke();
First I needed to bypass the execution policy to be able to import module. I'm using ImportPSModule method from the InitialSessionSate class. When I'm running this code I get an exception at Get-AzVM: System.Management.Automation.CommandNotFoundException: 'The 'Get-AzVM' command was found in the module 'Az.Compute', but the module could not be loaded. For more information, run 'Import-Module Az.Compute'.'
If I run Get-InstalledModule in the developer powershell the module is there. I'v tried by importing the module from path, but still get the exception when trying to use cmdlets from the module.
The above error is due to the Az.Compute module was not loaded properly.
You can try the below workarounds to let the Get-AzVM cmdlet work and also the module to get loaded correctly:
Install-Module -Name Az -AllowClobber -Scope CurrentUser after running this cmdlet, restart the Powershell and then run again this import-module az.compute cmd.
Also you can check the logs of PowerShellCore/Operational from Event viewer, if any errors are found then update the packages to the latest versions.
Related
We have a windows service which runs as the local system account. It calls a PowerShell script and retrieves the output for further processing. It works like a charm under windows server 2016 but now needs to be moved to a windows server 2012 R2. On this machine, it does not recognize the azure specific cmdlets.
I tried to install the specific cmdlets via -Scope AllUsers. We also logged into the PowerShell directly as local system-user; it does recognize the cmdlets (e.g. Add-AzureRMAccount) correctly.
C#:
PowerShell psInstance = PowerShell.Create();
psInstance.AddScript(scriptBase + "getVMs.ps1");
var azureVMList = psInstance.Invoke();
getVMs.ps1:
$finalPassword = ConvertTo-SecureString -String $password -AsPlainText -Force
$psCred = New-Object System.Management.Automation.PSCredential -ArgumentList $accountName, $finalPassword
$trash = Add-AzureRmAccount -Credential $psCred -TenantId $tenantID -ServicePrincipal`
We don't understand why the cmdlets are working fine under the same circumstances on server 2016 and if we run them directly as the user.
Any hint is appreciated
I suggest a workaround here, in your c# code, directly import the module which contains the cmdlet.
1.you can use this command to get the module file(I'm using az module, feel free to change to azureRm module):
(Get-Module -Name az.accounts).Path
then you can see the module file path, in my side, it's "C:\Program Files\WindowsPowerShell\Modules\Az.Accounts\1.5.2\Az.Accounts".
2.in your c# code:
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {"the full path of Az.Accounts.psd1, if it does not work, try full path of Az.Accounts.psm1"} );
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.AddScript(scriptBase + "getVMs.ps1");
var azureVMList = psInstance.Invoke();
Has any one met this issue before? I plan to use C# to call AzureAD cmdlets. But I tried many ways to import the module, like:
InitialSessionState initialState = InitialSessionState.CreateDefault();
initialState.ExecutionPolicy = Microsoft.PowerShell.ExecutionPolicy.Bypass;
initialState.AuthorizationManager = new System.Management.Automation.AuthorizationManager("O365");
initialState.LanguageMode = System.Management.Automation.PSLanguageMode.FullLanguage;
initialState.ImportPSModule(new string[] {"AzureAD" });
Runspace runspace = RunspaceFactory.CreateRunspace(initialState);
Or
pipeline.Commands.AddScript("Import-Module -Name AzureAD -Force; Get-Module");
var modules = pipeline.Invoke();
Or
pipeline.Commands.AddScript("Import-Module");
pipeline.Commands[0].Parameters.Add("Name", "AzureAD");
var modules = pipeline.Invoke()
No one can import the module. Even I use the full path "C:\Program Files\WindowsPowerShell\Modules\AzureAD\2.0.0.131\AzureAD.psd1". I have used cmdlet "Install-Module AzureAD -Force" to install the AzureAD module in my server. There is no error when I call the import-module in C#, but when I trying to use AzureAD cmdlet like 'Connect-AzureAD' I will get the error message:
The 'Connect-AzureAD' command was found in the module 'AzureAD', but the module could not be loaded.
I have tried both the 2 System.Management.Automation.dll, the issue is the same. I tried powershell 4.0, 5.0.
Any one has any ideas, please? Thanks very much.
By the way, the 1st version Azure AD module MSOnline works fine.
I enabled the -Verbose log in the import-module AzureAD cmdlet, then I checked the VERBOSE output in PowerShell.Streams.Verbose, I found there are just one record:
Loading module from path 'C:\Program Files (x86)\WindowsPowerShell\Modules\AzureAD\2.0.0.131\AzureAD.psd1'.
But it should have tens of verbose output as it does in powershell command prompt:
Thanks
-Justin
I also can repro it on my side. I resolved it by uncheck Prefer 32-bit the platform target, more detail please refer to the screenshot.
As I install the AzureADPreview module, C# code I used for test:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Import-Module AzureADPreview -Force;");
pipeline.Commands.AddScript("Connect-AzureAD");
var result = pipeline.Invoke();
I'm trying to run a powershell script within my C# web application.
When i run the following in powershell, it works fine.
Import-Module 'C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1'
Get-NAVTenant -ServerInstance DynamicsHost
But when i'm running it using my web application, it tells me
The term 'Get-NAVTenant -ServerInstance DynamicsHost' 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.
Here is my c# code:
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { "C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-NAVTenant -ServerInstance DynamicsHost");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.ToString());
}
Can someone point me in the right direction??
UPDATE:
Using runspace.SessionStateProxy.PSVariable.GetValue("Error") i could see the following error:
Cannot bind argument to parameter 'Name' because it is null.
Cannot bind argument to parameter 'Path' because it is null.
Cannot find path 'HKLM:\SOFTWARE\Microsoft\Microsoft Dynamics NAV\80\Service' because it does not exist.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
A command that prompts the user failed because the host program or the command type does not support user interaction. Try a host program that supports user interaction, such as the Windows PowerShell Console or Windows PowerShell ISE, and remove prompt-related commands from command types that do not support user interaction, such as Windows PowerShell workflows.
The error message suggests that your entire command string is interpreted as the name of a (non-existent) cmdlet. According to the documentation the AddCommand() method expects the name of a cmdlet, while parameters should be added via AddParameter().
Try changing this:
ps.Commands.AddCommand("Get-NAVTenant -ServerInstance DynamicsHost");
into this:
ps.Commands.AddCommand("Get-NAVTenant");
ps.Commands.AddParameter("-ServerInstance", "DynamicsHost");
or this:
ps.AddCommand("Get-NAVTenant");
ps.AddParameter("-ServerInstance", "DynamicsHost");
I can verify the following code works, posted from above: the following code will return the DatabaseServer name of the specified Dynamics NAV service tier
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] { "C:\\Program Files\\Microsoft Dynamics NAV\\80\\Service\\NavAdminTool.ps1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Get-NAVTenant");
ps.Commands.AddParameter("-ServerInstance", "objectupgrade");
foreach (PSObject result in ps.Invoke())
{
Console.WriteLine(result.Properties["DatabaseServer"].Value);
}
Console.Read();
Console.ReadKey();
A better and a much quicker method is to use the Microsoft.Dynamics.Nav.Management snap-in directly. Significant performance improvement can be seen by using this method. Please see following code found here: Why does PowerShell class not load a snapin
var config = RunspaceConfiguration.Create();
PSSnapInException warning;
config.AddPSSnapIn("Microsoft.Dynamics.Nav.Management", out warning);
using (Runspace runspace = RunspaceFactory.CreateRunspace(config))
{
runspace.Open();
using (var ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddCommand("Get-NAVTenant");
ps.AddParameter("ServerInstance", "ObjectUpgrade");
Collection<PSObject> results = ps.Invoke();
foreach (PSObject obj in results)
{
Console.WriteLine(obj.Properties["DatabaseServer"].Value);
}
Console.Read();
Console.ReadKey();
}
}
It turned out to be that the developer web server could't handle the request. Switching to IIS as developer server solved the problem. Now both of watto's examples works.
I am trying to use a custom snapin for powershell in my C# program. (The C# program is a modified version this)
I'm using the standard approach to setup the runspace:
Runspace runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript(scriptText);
Collection<PSObject> results = pipeline.Invoke();
runspace.Close();
If I run this as is and scriptText contains the command "Get-PSSnapin" my snapin is missing. If I run "Get-PSSnapin -Registered" then I can see my snapin. If I use Add-PSSnapin, then it returns nothing and followup commands that I issue (which are implemented in the snapin will return):
...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
So, I amended my code to add the cmdlet to the runconfig:
RunspaceConfiguration runConfig = RunspaceConfiguration.Create();
PSSnapInException psEx = null;
runConfig.AddPSSnapIn("mySnapin", out psEx);
Runspace runspace = RunspaceFactory.CreateRunspace(runConfig);
Now, when I run it, I get:
error in script : Cannot invoke this function because the current host
does not implement it.
I tried both the x86 and 64 version. The snapin gets installed in the x86 programs so I did this by compiling for x86. If I do the 64 version, I get:
"Error in script : The Windows PowerShell snap-in 'mySnapin' is not
installed on this machine".
Confirming that this is specific to x86.
I also tried loading this as a module (desperation), but it doesn't work that way either. When I run:
get-command <command in mySnapin> | select Module, PsSnapin
The output doesn't have a module, just the snapin, hence it was silly to begin with.
I should note that this is installed by another program and I have no control over where it is install. I thought that might be a factor, but since it shows up with -Register I think it is finding without issue.
Edit:
I also tried import-module <path to dll>. This doesn't output anything and subsequent calls to functions in my snapin yield:
error in script : Cannot invoke this function because the current
host does not implement it.
Then again in C# since I wasn't clear on whether the import will be preserved across calls.
pipeline.Commands.Add("Import-Module");
var command = pipeline.Commands[0];
command.Parameters.Add("Name", #"<path to my snapin .dll>");
Any help getting this rolling would be greatly appreciated. Thank you!
I'm trying to install new features on a Windows Server 2012 system through PowerShell and C#. I am getting this error back when trying to call the Install-WindowsFeature cmdlet:
The term 'Install-WindowsFeature' is not recognized as the name of a
cmdlet, function, script file, or operable program...
I can call other cmdlets though C# and even some of the other new ones. I did a Get-Command and Install-WindowsFeature, Remove-WindowsFeature, and Get-WindowsFeatures are not listed...but about 980 others are.
Why wouldn't I be able to call this cmdlet from my C# program, but when I go to PowerShell it calls it just fine?
runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Install-WindowsFeature");
Collection<PSObject> output = pipeline.Invoke();
Try this command instead of Install-WindowsFeature in your code:
Invoke-Expression "Powershell -Command {Import-Module ServerManager ; Install-WindowsFeature XXXX}"
Try compiling in x64. In Visual Studio go to menu Project → Properties → Build - Platform Target = x64.