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.