0

Using this code to run my Powershell code from C#, everything works fine

        using(PowerShell powershellCommand = PowerShell.Create())
        {
            powershellCommand.AddScript(File.ReadAllText(@"C:\Path_to_script")).Invoke();
            System.Collections.ObjectModel.Collection<System.Management.Automation.PSObject> results = powershellCommand.Invoke();
            foreach (PSObject result in results)
            {
                logg.AppendText(result + ""); 
            }
        }

Code in scriptfile.

$env:tmp = "env_location"
Import-PSSession $(New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri 
server_url) | Out-Null
$device = Get-Mailbox -Identity IDENTITY | Get-MailboxStatistics | Select-Object TotalItemSize

return $device

IDENTITY is the problem here since i want it to be dynamic so it can't be hard coded into the scriptfile. I have tried the solution in Execute multiple line PowerShell Script from C# like so:

        using(PowerShell powershellCommand = PowerShell.Create())
        {
            string script = @"
            $env:tmp = 'env_location'
            Import-PSSession $(New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri server_url) | Out-Null
            $device = Get-Mailbox -Identity DYNAMIC_IDENTITY | Get-MailboxStatistics | Select-Object TotalItemSize

            return $device
            ";

            powershellCommand.AddScript(script)).Invoke();
            System.Collections.ObjectModel.Collection<System.Management.Automation.PSObject> results = powershellCommand.Invoke();
            foreach (PSObject result in results)
            {
                logg.AppendText(result + ""); 
            }
        }

It feels like this should work, but there is no output at all. No crash either, any ideas?

Thanks

3
  • 2
    Surely you just want Identity to be a variable in your PowerShell script and then pass it as a parameter to that script in your dotnet program? Commented Apr 9, 2021 at 20:36
  • 2
    Also, it seems you're calling invoke twice on your PowerShell command. When I've had to call a script in the past from a dotnet app, if I am expecting output from PowerShell, I have tended to use BeginInvoke() and EndInvoke() instead. Commented Apr 9, 2021 at 21:03
  • @Ash Thank you, yes that would be great but I don't understand the syntax for it. I have tried: powershellCommand.AddScript(File.ReadAllText(@"path_to_script")).AddCommand("Get-Mailbox").AddParameter("Identity","test-identity"); and: powershellCommand.AddScript(File.ReadAllText(@"path_to_script")).AddParameter("$variable_in_script","test-identity"); Commented Apr 10, 2021 at 19:02

1 Answer 1

1

As per my comments above, try this out.

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Management.Automation;
using System.Management.Automation.Runspaces;

namespace PowerShellSample
{
    public class Exchange
    {
        public static Collection<PSObject> GetTotalMailboxSize(string identity)
        {
            using(PowerShell powershellCommand = PowerShell.Create())
            {
                powershellCommand.AddScript(File.ReadAllText(@"C:\\Path_to_script")).AddParameter("Identity", identity);
                IAsyncResult poshTask = powershellCommand.BeginInvoke();
                Collection<PSObject> returnCollection = new Collection<PSObject>();
                foreach (PSObject psObj in powershellCommand.EndInvoke(poshTask))
                {
                    returnCollection.Add(psObj);
                }
                return returnCollection;
            }
        }
    }
}

PowerShell script:

[CmdletBinding()]
Param (
    [Parameter(Mandatory = $true)]
    [System.String]
    $Identity
)

$env:tmp = "env_location"
Import-PSSession $(New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri server_url) | Out-Null
$Device = Get-Mailbox -Identity $Identity | Get-MailboxStatistics | Select-Object TotalItemSize

return $device

If you wanted to provide more parameters you can do so using a Dictionary<string, Object> in the method. This way you could pass your ConnectionUri or any other parameters you might need.

public static Collection<PSObject> GetTotalMailboxSize(string identity, Dictionary<string, Object> parameters)
{
    using(PowerShell powershellCommand = PowerShell.Create())
    {
        powershellCommand.AddScript(File.ReadAllText(@"C:\\Path_to_script"));
        foreach (var key in parameters.Keys)
        {
            powershellCommand.AddParameter(key, parameters[key]);
        }
        IAsyncResult poshTask = powershellCommand.BeginInvoke();
        Collection<PSObject> returnCollection = new Collection<PSObject>();
        foreach (PSObject psObj in powershellCommand.EndInvoke(poshTask))
        {
            returnCollection.Add(psObj);
        }
        return returnCollection;
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

Brilliant! Thank you so much for taking the time to show me this :) .

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.