Powershell Command Will not run in C# - c#

I am writing a c# Windows Form app to migrate Exchange 2010 mailboxes to a file location on the server in .pst format. I used an example from the Powershell SDK (Runspace05) to access the exchange cmdlets (Get-Mailbox) and populate a combo-box with the users mailboxes with no problem.
The parts i'm having trouble with is getting the New-MailboxExportRequest cmdlet (the cmdlet that performs the export) to run and the ability to return it's objects and show them in a listbox control. What am I missing? Thanks in advance for your help.
The Code:
InitialSessionState iss = InitialSessionState.CreateDefault();
PSSnapInException warning;
iss.ImportPSSnapIn("Microsoft.Exchange.Management.PowerShell.E2010", out warning);
using (Runspace myrunspace = RunspaceFactory.CreateRunspace(iss))
{
myrunspace.Open();
using (PowerShell powershell = PowerShell.Create())
{
var mailbox = cmbEmailUserName.Text;
var pstFile = txtFileSaveLocation.Text;
const int badLimit = 100; //can be increased in necessary
powershell.AddCommand("Microsoft.Exchange.Management.PowerShell.E2010\\New-MailboxExportRequest");
powershell.AddParameter("Mailbox", mailbox);
powershell.AddParameter("FilePath", pstFile);
powershell.Runspace = myrunspace;
Collection<PSObject> results = powershell.Invoke();
foreach (PSObject thisResult in results)
{
lstBoxStatus.Items.Add(thisResult);
}
myrunspace.Close();
}
}

You want to access the properties of the PSObject, not the object itself.
Try this:
foreach (PSObject thisResult in results)
{
foreach (PSPropertyInfo thisResultInfo in thisResult.Properties)
{
lstBoxStatus.Items.Add("Name: {0} Value: {1} Type: {2}", thisResultInfo.Name, thisResultInfo.Value, thisResultInfo.MemberType);
}
}

Related

C# Powershell not returning any Get-ChildItem results

When I run powershell from my MVC application, i get no results from the Get-ChildItem –Path IIS:\AppPools command.
If i run it directly in powershell it works fine. I have set the site to run on administrator account, thinking that maybe it cant "see" the pools, but no luck.
This is just a test too, accessing the pools, as what i was origionally struggling with was turning off an application pool, as it "could not be found". with Get-WebAppPoolState -name $service
public static string test()
{
using (var powershell = PowerShell.Create())
{
using (Runspace runspace = RunspaceFactory.CreateRunspace())
{
using (RunspaceInvoke invoker = new RunspaceInvoke())
{
invoker.Invoke("Set-ExecutionPolicy Unrestricted");
invoker.Invoke("Import-Module WebAdministration");
runspace.Open();
powershell.Runspace = runspace;
powershell.AddScript(#"Import-Module WebAdministration
Get-ChildItem –Path IIS:\AppPools");
var results = powershell.Invoke();
var result = "";
result += ResultsToString(results); // results is a blank list
result += String.Join(",", powershell.Streams.Error.ToList().Select(x => x.Exception.Message));
return result;
}
}
}
}
Any ideas where the issue lies? code, permissions?

How to get a list of AppV virtual processes using C#

I am trying to get a list of all Virtual Processes started by Microsoft AppV using C#.
I tried using Powershell in C# but I get this error:
System.Management.Automation.CommandNotFoundException: 'The 'Get-AppvVirtualProcess' command was found in the module 'AppvClient', but the module could not be loaded. For more information, run 'Import-Module AppvClient'.'
The weird thing is that if I use the Powershell command line, it works just fine and lists the virtual processes.
So in C# I did a:
ps.Commands.AddCommand("Get-Command");
and it shows Get-AppvVirtualProcess listed as a command:
The result:
Function Get-AppvVirtualProcess 1.0.0.0 A
I tried loading the module in C# manually using:
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {#"C:\Program Files\Microsoft Application Virtualization\Client\AppvClient\AppvClient.psd1" });
and
ps.Commands.AddCommand("Import-Module").AddArgument("AppvClient");
But it still gives me the same error mentioned above.
The code in C# looks like this:
public static void powershellCommand()
{
Collection<PSObject> result;
using (Runspace myRunSpace = RunspaceFactory.CreateRunspace())
{
InitialSessionState initial = InitialSessionState.CreateDefault();
initial.ImportPSModule(new string[] {#"C:\Program Files\Microsoft Application Virtualization\Client\AppvClient\AppvClient.psd1" });
Runspace runspace = RunspaceFactory.CreateRunspace(initial);
runspace.Open();
PowerShell ps = PowerShell.Create();
ps.Runspace = runspace;
ps.Commands.AddCommand("Import-Module").AddArgument("AppvClient");
ps.Commands.AddCommand("Get-AppvVirtualProcess");
result = ps.Invoke();
var builder = new StringBuilder();
foreach (PSObject psObject in result)
{
builder.Append(psObject.ToString() + "\n");
builder.ToString();
}
Console.WriteLine("Virtual Process: {0}", builder.ToString());
}
}
Instead of Runspace, I tried this as well but I get the same error:
public static void p()
{
using (var powershell = PowerShell.Create())
{
powershell.AddCommand("Get-AppvVirtualProcess");
powershell.Invoke();
}
}
You could try to iterate through all the running process, and find those that loaded either AppVEntSubsystems32.dll or AppVEntSubsystems64.dll.
You can read more about this here: https://blogs.msdn.microsoft.com/gladiator/2014/09/04/app-v-5-on-application-launch/

WPF host for Powershell, output formatting

Description of Issue:
I've created a host for Powershell 2.0. The host uses WPF and C#.
The problem is, much output to my WPF host is not formatted the same way as what is displayed when using Powershell ISE.
When I run the script ls alias: in Powershell ISE, the results are in a table form, with CommandType, Name, and Definition column headers. When I run the same script in my WPF host, the results are simply a list of the names of aliases. A similar issue happens with many other scripts, commandlets, and aliases.
Question:
How do I get the same formatting functionality that seems to be built into Powershell ISE? Is this an issue with the Powershell side of things, or do I need to include extra code on the WPF side of things?
Code Sample:
Here is the class I've built to handle Powershell input and output, from within WPF (framework courtesy of example at code.msdn.microsoft.com, although my class is not asynchronous):
internal class PSInterfacer
{
private Runspace runspace { get; set; }
public PSInterfacer()
{
runspace = RunspaceFactory.CreateRunspace();
runspace.Open();
}
public string RunScript(string script)
{
string tempOut = "";
// create powershell instance
using (PowerShell ps = PowerShell.Create())
{
// add existing runspace
ps.Runspace = runspace;
// add script
ps.AddScript(script);
// pipe errors to the same output as normal results
ps.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error,
PipelineResultTypes.Output);
// put output in list
List<PSObject> psOutputs = ps.Invoke().ToList();
// display output elements, seperated by newlines
foreach (PSObject psObject in psOutputs)
{
if (psObject != null)
{
tempOut += psObject.BaseObject;
}
if (psObject != psOutputs.Last())
{
tempOut += Environment.NewLine;
}
}
return tempOut;
}
}
}
After working for a few days, found this solution. Basically, use the .AddCommand method (in the Powershell class) to pipe to "Out-String." That formats everything properly.
Replace RunScript method with this:
public string RunScript(string script)
{
string tempOut = "";
try
{
using (PowerShell ps = PowerShell.Create())
{
ps.Runspace = runspace;
ps.AddScript(script);
ps.AddCommand("Out-String");
ps.Commands.Commands[0].MergeMyResults(PipelineResultTypes.Error, PipelineResultTypes.Output);
List<PSObject> psOutputs = ps.Invoke().ToList();
foreach (PSObject psObject in psOutputs)
{
if (psObject != null)
{
tempOut += psObject.BaseObject;
}
}
}
}
catch(Exception ex)
{
tempOut = string.Format("Error when invoking powershell commands:\n{0}", ex.Message);
tempOut += "\nThis function did not complete.";
}
return tempOut;
}

Powershell outputs on a C# .NET Environment

I was trying to invoke powershell commands in a c# .net environment and manipulate the outputs, for example: I would like to iterate through each parent and child nodes and get their Innertext value and map them into my classes, but all I get is the whole xml content: below is my code so far:
Runspace rs = RunspaceFactory.CreateRunspace();
rs.Open();
Pipeline pipe = rs.CreatePipeline();
//create powershell
using (PowerShell powershell = PowerShell.Create())
{
//Add the commnads to the PowerShell object.
powershell.AddCommand("Get-Content").AddArgument("C:\\XMLFileSettings.xml");
try
{
foreach (PSObject result in powershell.Invoke())
{
Console.WriteLine("{0}", result.ToString());
}
}
finally
{
}
}

Calling Get-MsolUser returns no results

I'm working on the some proof of concept code for a system that will manage a large number of Office365 accounts, however, I seem to be struggling at the first hurdle with a rather daft problem.
I'm using the RunspaceFactory to fire my Powershell commands at Office 365 and whilst the code appears to be running without any errors I never get a list of users back.
Firstly here's my code....
Runspace runSpace = RunspaceFactory.CreateRunspace();
runSpace.Open();
Pipeline pipeline = runSpace.CreatePipeline();
Command msolConnect = new Command("Connect-MsolService");
System.Security.SecureString securePassword = new System.Security.SecureString();
foreach (char pwdLetter in password)
{
securePassword.AppendChar(pwdLetter);
}
PSCredential credential = new PSCredential(username, securePassword);
msolConnect.Parameters.Add("Credential", credential);
pipeline.Commands.Add(msolConnect);
Command msolGetUser = new Command("Get-MsolUser");
msolGetUser.Parameters.Add("SearchString", "hayley");
pipeline.Commands.Add(msolGetUser);
Collection<PSObject> connectOutput = pipeline.Invoke();
foreach (PSObject psObject in connectOutput)
{
Console.WriteLine(psObject.Members["DisplayName"].Value.ToString());
}
The pipline.HadErrors is false and the connectOutput is always empty. It appears that code is succesfully running but without returning any results.
I have tried;
the same command in Windows Powershell and I get back a list of expected results.
mis-spelling SearchString (just to check that the command was running and the parameter was being passed) and an error is generated as I would expect I have also
using ImportPSModule(new[] { "MsOnline" }) to ensure the MSOnline module is available
other commands (e.g. Get-MsolGroup) and get back an empty list
I know find myself scratching my head on a Friday afternoon hoping that someone else may be able to help me...
Thanks in advance,
Darren
First you need to install SharePoint Online Management Shell from the following link: https://www.microsoft.com/en-us/download/details.aspx?id=35588. But you may also need to install Microsoft Online Services Sign-In Assistant version 7.0 or greater version from the following link: https://www.microsoft.com/en-my/download/details.aspx?id=39267 and then need to install Windows Azure Active Directory Module.
After that you can follow the following code:
InitialSessionState iss = InitialSessionState.CreateDefault();
iss.ImportPSModule(new[] { "MSOnline" });
using (Runspace myRunSpace = RunspaceFactory.CreateRunspace(iss))
{
Pipeline pipeline = myRunSpace.CreatePipeline();
myRunSpace.Open();
// Execute the Get-CsTrustedApplication cmdlet.
using (System.Management.Automation.PowerShell powershell = System.Management.Automation.PowerShell.Create())
{
powershell.Runspace = myRunSpace;
Command connect = new Command("Connect-MsolService");
System.Security.SecureString secureString = new System.Security.SecureString();
string myPassword = "Password";
foreach (char c in myPassword)
secureString.AppendChar(c);
connect.Parameters.Add("Credential", new PSCredential("admin#domain.microsoftonline.com", secureString));
powershell.Commands.AddCommand(connect);
Collection<PSObject> results = null;
Collection<ErrorRecord> errors = null;
results = powershell.Invoke();
errors = powershell.Streams.Error.ReadAll();
powershell.Commands.Clear();
Command getuser = new Command("Get-MsolUser");
getuser.Parameters.Add("MaxResults", 4);
powershell.Commands.AddCommand(getuser);
results = null;
errors = null;
results = powershell.Invoke();
foreach (PSObject psObject in results)
{
Console.WriteLine(psObject.Members["DisplayName"].Value.ToString());
}
}
}
Try appending the Get-MsolUser with -All

Categories

Resources