2

I am using C# to send PowerShell commands interacting with Exchange. I have a method called initconnection which sets up my connection to Exchange.

I have another method that I call when I click a button that will send a command to powershell after the connection is established. However I am not able to continue the created connection. When I try to run a command it says the command is not found. More than likely because it doesn't have the exchange cmdlets.

Runspace runspace = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace();

runspace.Open();

Pipeline pipeline = runspace.CreatePipeline();
pipeline.Commands.AddScript("Set-ExecutionPolicy Unrestricted -Scope process -Force;$password = ConvertTo-SecureString -AsPlainText -Force " + password + ";$mycred = new-object -typename System.Management.Automation.PSCredential -argumentlist " + username + ",$password;$LiveCred = Get-Credential -Credential $mycred; $Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell/ -Credential $LiveCred -Authentication Basic –AllowRedirection; Import-PSSession $Session");
// pipeline.Commands.Add("Out-String");

pipeline.Invoke();
mpeAdd.Hide();

This is the initconnection method that creates the connection.

protected void Get_Mailboxes(object sender, EventArgs e) {

    PowerShell powershell = PowerShell.Create();
    PSCommand command = new PSCommand();
    command = new PSCommand();
    command.AddCommand("Get-Mailbox");

    powershell.Commands = command;
    powershell.Runspace = runspace; //Also it says runsapce doesn't exist in this context.
    Collection<PSObject> commandResults = powershell.Invoke();

    StringBuilder sb = new StringBuilder();

    ArrayList boxesarray = new ArrayList();

    foreach (PSObject ps in commandResults)
    {
        boxesarray.Add(ps.Properties["Alias"].Value.ToString());
    }

    boxes.DataSource = boxesarray;
    boxes.DataBind();
}

This is my method I call when I click a button after the connection is create however it is not working.

2 Answers 2

2

You have to add the Exchange snap-in to your runspace. Take a look at Exchange for developers.

Sign up to request clarification or add additional context in comments.

Comments

1

If "runspace" doesn't exist, that explains why the Get-Mailbox command is failing. Rather than managing a runspace, you could create a PowerShell instance in your initConnection method and use it wherever needed. Note this is shown with native code rather than a script.

ps = PowerShell.Create(); 

Set the execution policy.

ps.ClearCommands()
 .AddCommand("Set-ExecutionPolicy")
 .AddParameter("Scope", "Process") 
 .AddParameter("ExecutionPolicy", "Unrestricted")    
 .AddParameter("Confirm", false)
 .AddParameter("Force", true)
 .Invoke();

Create the credentials. Note that you should not need to call Get-Credential.

SecureString pass;   
var creds = new PSCredential(username, pass);

Create and import a session.

var newSession = ps.ClearCommands()
 .AddCommand("New-PSSession")
 .AddParameter("ConfigurationName", "Microsoft.Exchange")
 .AddParameter("ConnectionUri", "https://ps.outlook.com/powershell/")
 .AddParameter("Credential", creds)
 .AddParameter("Authentication", "Basic")
 .AddParameter("AllowRedirection", true)
 .Invoke();

var session = newSession[0];
var import = ps.ClearCommands()
 .AddCommand("Import-PSSession")
 .AddParameter("Session", session)
 .Invoke();

ps.ClearCommands() is an extension method, added so it can be chained with AddCommand(), AddParameter(), etc:

public static PowerShell ClearCommands(this PowerShell ps)
{
    if (ps.Commands != null)
        ps.Commands.Clear();

    return ps;
}

Use it in Get_Mailboxes()

protected void Get_Mailboxes(object sender, EventArgs e) {

  var commandResults = ps.ClearCommands().AddCommand("Get-Mailbox").Invoke();
  StringBuilder sb = new StringBuilder();
  ArrayList boxesarray = new ArrayList();

  foreach (PSObject ps in commandResults)
  {
      boxesarray.Add(ps.Properties["Alias"].Value.ToString());
  }

  boxes.DataSource = boxesarray;
  boxes.DataBind();
}

When you close the app, or somewhere appropriate:

ps.ClearCommands()
 .AddCommand("Get-PSSession")
 .AddCommand("Remove-PSSession")
 .Invoke();

ps.Dispose();

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.