I'm developing a test project in ASP.NET MVC, where Im using System.Management.Automation to execute some PowerShell cmdlets.
Some of the cmdlets are from the Azure Powershell module.
The code is working fine when I run it from Visual Studio. But when I Published the website to IIS the some cmdlets and these scripts don't work.
Example, see the comments before:
var shell = PowerShell.Create();
var script1 = "Get-AzureSubscription | Out-String"; // cant execute the cmdlet
var script2 = "C:\\inetpub\\wwwroot\\App1\\Scripts\\test.ps1"; //Cant execute the script.
var script3 = "Get-Date"; //Work fine
try
{
shell.Commands.AddScript(script); // here insert the script.
Collection<PSObject> results = shell.Invoke();
//Search for errors, if some error is found redirect to an Error page.
if (shell.Streams.Error.Count > 0)
{
foreach (ErrorRecord err in shell.Streams.Error)
{
string error = err.ToString();
TempData["pserror"] = error;
return RedirectToAction("Powershellerror");
}
}
else
if (results.Count > 0)
{
foreach (var psObject in results)
{
string result2 = psObject.ToString();
TempData["psoutput"] = result2;
return RedirectToAction("PowershellOutput");
}
}
Both, script1 and script2 give this error:
The term 'C:\inetpub\wwwroot\App1\Scripts\test.ps1' 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.
and
The term 'Get-AzureSubscription' 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.
What could be??? Something is missing in the IIS setup?
You probably need to import the Azure module, try as suggested here:
https://stackoverflow.com/a/6267517/1183475
var ps = PowerShell.Create(myRS);
ps.Commands.AddCommand("Import-Module").AddArgument(#"g:\...\PowerDbg.psm1")
ps.Invoke()
I don't have the Azure PS tools installed on this machine, but the path should be:
"C:\Program Files (x86)\Microsoft SDKs\Windows Azure\PowerShell\Azure\Azure.psd1
Related
I want to execute the power shell logic using c#(web application) but i'm getting the issue
The term 'git' 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 added the git path in environmental variables and able to execute the same powershell logic from powershell window without any issues.
My powershell script:
function CheckoutTheCode($checkoutRepoUrl, $checkoutDirectory, $checkoutBranch)
{
[hashtable]$Return = #{}
try
{
# Cloning
git clone --single-branch -b $checkoutBranch $checkoutRepoUrl $checkoutDirectory
$Return.Status = $true
$Return.Message = "Success"
}
catch
{
$Return.Message = $Error[0].Exception
$Return.Status = $false
}
Return $Return
}
$checkoutDirectory = "local directory for checkout"
$checkoutRepoUrl = "bit bucket repo url"
$checkoutBranch = "branch version"
CheckoutTheCode $checkoutRepoUrl $checkoutDirectory $checkoutBranch
My c# code:
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddScript("PowerShell script");
Collection<PSObject> PSOutput = PowerShellInstance.Invoke();
}
In My case the issue is I have added the system environment variable after the c# web application is opened in visual studio.
When i have closed the visual studio and opened again, it's working fine.
I am trying to run PowerShell scripts using C# using this link as a reference.
So far I have got:
try
{
using (PowerShell PowerShellInstance = PowerShell.Create())
{
PowerShellInstance.AddCommand(scriptPath);
var PSOutput = PowerShellInstance.Invoke();
if (PowerShellInstance.Streams.Error.Count > 0)
{
foreach (var line in PowerShellInstance.Streams.Error)
{
Console.WriteLine(line);
}
return false;
}
else
{
return true;
}
}
}
catch (Exception ex)
{
return false;
}
Which keeps throwing an exception:
"AuthorizationManager check failed."
Inner Exception: A command that prompts the user failed because the
host program or the command
type does not support user interaction. The host was attempting to
request confirmation with the following message: Run only scripts that
you trust. While scripts from the internet can be useful, this script
can potentially harm your computer. If you trust this script, use the
Unblock-File cmdlet to allow the script to run without this warning
message. Do you want to run C:\PowerShellScripts\MyScript.ps1?
So looking at the Exception I can see it's asking me to confirm the script but there is no window for the user to interact, hence the exception.
So I started looking at how to stop the confirmation text and found Powershell New-Item: How to Accept Confirmation Automatically
But even adding:
PowerShellInstance.AddScript("$ConfirmPreference = \"None\"");
PowerShellInstance.Invoke();
Before executing my script didn't work. So is there a way of setting $ConfirmPreference = "None" for my PowerShell instance using C#?
While the accepted answer solved this specific problem, the correct way of setting $ConfirmImpact preference variable is via session state:
var sessionState = InitialSessionState.CreateDefault();
sessionState.Variables.Add(new SessionStateVariableEntry("ConfirmPreference", ConfirmImpact.None, ""));
using (PowerShell shell = PowerShell.Create(sessionState))
{
// execute commands, etc
}
(This is for visitors who came here from Google search results)
I think it has something to do with the Execution Policy. You can query the execution policy with the Cmdlet Get-ExecutionPolicy. You can:
change the Execution Policy to (for example): "Unrestricted" by
using Set-ExecutionPolicy Unrestricted or
run your script by running powershell.exe -ExecutionPolicy Bypass C:\PowerShellScripts\MyScript.ps1 or
unblock the script by using the Cmdlet Unblock-File C:\PowerShellScripts\MyScript.ps1
Hi I'm trying to execute the Get-ClusterGroup cmdlet from C# 4.0. I've used the following code
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new string[] { "failoverclusters"});
Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss);
myRunSpace.Open();
Pipeline pipeLine = myRunSpace.CreatePipeline();
Command myCommand = new Command("Get-ClusterGroup");
pipeLine.Commands.Add(myCommand);
Console.WriteLine("Invoking Command");
Collection commandResult = pipeLine.Invoke();
foreach (PSObject resultObject in commandResult)
{
Console.WriteLine(resultObject.ToString());
}
myRunSpace.Close();
But getting the following error
The term 'Get-ClusterGroup' 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.
It will be great if someone can show me the where I'm missing the logic or where is the problem in my code
Get-ClusterGroup is a Powershell Commandlet, not an .exe file. You can invoke Powershell commands from .NET using the System.Management.Automation.PowerShell class, as described on MSDN here: http://msdn.microsoft.com/en-us/library/system.management.automation.powershell(v=vs.85).aspx
I'm trying to call the Add-AppxPackage cmdlet from C#. I found the MSDN article on running PowerShell from C# code. I have referenced the System.Management.Automation assembly and have tried the following code snippets, all of which result in the same exception when trying to call powerShell.Invoke():
System.Management.Automation.CommandNotFoundException was unhandled
The term 'Add-AppxPackage' 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.
Snippet 1:
var powerShell = PowerShell.Create();
powerShell.AddCommand(string.Format("Add-AppxPackage '{0}'", appxFilePath));
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
I understand why this doesn't work, since I shouldn't be providing parameters in the AddCommand() function.
Snippet 2:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddParameter("Path", appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
Snippet 3:
var powerShell = PowerShell.Create();
powerShell.AddCommand("Add-AppxPackage");
powerShell.AddArgument(appxFilePath);
foreach (PSObject result in powerShell.Invoke())
{
Console.WriteLine(result);
}
My C# project targets .Net 4.5, and if I do powerShell.AddCommand("Get-Host") it works and the Version it returns back is 4.0. Add-AppxPackage was added in v3.0 of PowerShell, so the command should definitely exist, and it works fine if I manually run this command from the Windows PowerShell command prompt.
Any ideas what I am doing wrong here? Any suggestions are appreciated.
-- Update --
I found this post and this one, and realized there is a AddScript() function, so I tried this:
Snippet 4:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format("Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
foreach (PSObject result in results)
{
Console.WriteLine(result);
}
And it does not throw an exception, but it also doesn't install the metro app, and the "results" returned from powerShell.Invoke() are empty, so I'm still at a loss...
-- Update 2 --
So I decided that I would try just creating a new PowerShell process to run my command, so I tried this:
Process.Start(new ProcessStartInfo("PowerShell", string.Format("-Command Add-AppxPackage '{0}'; $key = $Host.UI.RawUI.ReadKey('NoEcho,IncludeKeyUp')", appxFilePath)));
but it still throws the same error that Add-AppxPackage is not a recognized cmdlet.
ANSWER
If you follow the long comment thread on robert.westerlund's answer, you will see that for some reason when running/launched from Visual Studio, PowerShell was not including all of the PSModulePaths that it does when running straight from a PowerShell command prompt, so many modules are not present. The solution was to find the absolute path of the module that I needed (the appx module in my case) using:
(Get-Module appx -ListAvailable).Path
And then import that module before trying to call one of its cmdlets. So this is the C# code that worked for me:
var powerShell = PowerShell.Create();
powerShell.AddScript(string.Format(#"Import-Module 'C:\WINDOWS\system32\WindowsPowerShell\v1.0\Modules\Appx\Appx.psd1'; Add-AppxPackage '{0}'", appxFilePath));
var results = powerShell.Invoke();
UPDATED ANSWER
You can see from this other post I opened, that the problem was with a bug in a Visual Studio extension (in my case StudioShell) causing not all of the PSModulePaths to be loaded. After uninstalling that extension all of the modules were loaded correctly and I no longer needed to manually import the module.
In PowerShell there is a difference between terminating errors (which stops the execution) and non-terminating errors (which are just written to the error stream).
If you want to create a non-terminating error in a function of your own, just use the Write-Error cmdlet. If you want to create a terminating error, use the Throw keyword. You can read more about these concepts if you run Get-Help Write-Error, Get-Help about_Throw and Get-Help about_Try_Catch_Finally.
Using the Add-AppxPackage with a non existing package is a non terminating error and will thus be written to the error stream, but no execution halting exception will be thrown. The following code tries to add a non existing package and then writes the error to the console.
var powerShell = PowerShell.Create();
powerShell.AddScript("Add-AppxPackage NonExistingPackageName");
// Terminating errors will be thrown as exceptions when calling the Invoke method.
// If we want to handle terminating errors, we should place the Invoke call inside a try-catch block.
var results = powerShell.Invoke();
// To check if a non terminating error has occurred, test the HadErrors property
if (powerShell.HadErrors)
{
// The documentation for the Error property states that "The command invoked by the PowerShell
// object writes information to this stream whenever a nonterminating error occurs."
foreach (var error in powerShell.Streams.Error)
{
Console.WriteLine("Error: " + error);
}
}
else
{
foreach(var package in results)
{
Console.WriteLine(package);
}
}
I am invoking a get-msoluser cmdlet of office365 and i use the following cmdlet in powershell
Get-MsolUser -UserPrincipalName user#organization.onmicrosoft.com | ForEach-Object{ $_.licenses}
The output is a collection of licenses and i wanted the same script to be run in c#. so i have written the code as follows
private void displayLicenses(){
Command cmd = new Command("Get-MsolUser");
cmd.Parameters.Add("UserPrincipalName","user#organization.onmicrosoft.com");
Command cmd2 = new Command("ForEach-Object");
cmd2.Parameters.Add("$_.licenses.AccountSku");
Pipeline pipe = Office365Runspace.CreatePipeline();
pipe.Commands.Add(cmd);
pipe.Commands.Add(cmd2);
Console.WriteLine("Before invoking the pipe");
ICollection<PSObject> result = pipe.Invoke();
CheckForErrors(pipe);
Console.WriteLine("Executed command {0} + {1} with no error", cmd.CommandText, cmd2.CommandText);
foreach(PSObject obj in result){
foreach(PSPropertyInfo propInfo in obj.Properties){
Console.WriteLine(propInfo.Name+": "+propInfo.Value+" "+propInfo.MemberType);
}
}
}
But i still get an error on executing this function saying
Unhandled Exception:
System.Management.Automation.CommandNotFoundException: The term
'ForEach-Object' is not recognized as the name of a cmdlet, function,
scrip t file, or operable program. Check the spelling of the name, or
if a path was in cluded, verify that the path is correct and try
again.
I checked that my project has a reference to System.management.Automation.dll file that contains the ForEach-Object cmdlet.
I found the dll using this cmd in powershell
(Get-Command ForEach-Object).dll
Thanks,
Satya
I figured out the problem causing for the issue. It is due to the misconfigured runspace i created.
InitialSessionState initalState = InitialSessionState.Create();
initalState.ImportPSModule(new String[] { "msonline" });
//initalState.LanguageMode = PSLanguageMode.FullLanguage;
Office365Runspace = RunspaceFactory.CreateRunspace(initalState);
Office365Runspace.Open();
i was creating the initalstate with empty one,When i changed it to default one it worked fine.On creating the default one it includes all the modules that were obtained by default.
InitialSessionState initalState = InitialSessionState.CreateDefault();
it worked fine.
Thanks,
Satya
It sounds like your're trying to run that in the remote session at the Exchange server. Those are NoLanguage constrained sessions, meaning that you can only run the Exchange cmdlets in those sessions. If you want to use PowerShell core language cmdlets (like foreach-object), you have to do that in a local session and either use Import-PSSession to import the Exchange functions into your local session (implicit remoting) , or use Invoke-Command and point it at the remote session on the Exchange server.