0

Currently I have a Powershell script that creates a session with and then queries an Exchange email with the following query:

Get-MessageTrace -StartDate "10/07/2017 12:00 AM" -EndDate "11/06/2017 11:59 PM" -PageSize 5000 -Page $Page | Select Received,SenderAddress,RecipientAddress,Size

I'm wanting to update this script so thay it runs within C# so that I can run it as a service with fields like the start and end dates updating automatically. To this end I have it to the point where I can create a session with the server and then run the following method:

private static List<PSObject> RetrieveCurrentEmailList(string previousDate, DateTime currentDate, int pageSize,
        int currentPage, IReadOnlyList<PSObject> psConnection, Runspace runspace)
    {
        var powershell = PowerShell.Create();
        var command = new PSCommand();
        command.AddCommand("Invoke-Command");
        command.AddParameter("ScriptBlock",
            ScriptBlock.Create(
                "Get-MessageTrace -StartDate \"" + previousDate
                + "\" -EndDate \"" + currentDate.ToString("MM/dd/yyyy", CultureInfo.CreateSpecificCulture("en-US"))
                + "\" -pageSize " + pageSize
                + " -Page " + currentPage));
        //+ " | Select Received,SenderAddress,RecipientAddress,Size"));
        command.AddParameter("Session", psConnection[0]);
        powershell.Commands = command;
        powershell.Runspace = runspace;
        Console.WriteLine("Executing query for page: " + currentPage);
        return powershell.Invoke().ToList();
    }

Which returns the entire PSObject. However when I attempt to include the "| Select Received,SenderAddress,RecipientAddress,Size" filtering it stops returning results. On top of this there is an issue where I have to dispose of the runspace and re-create it every time I want to run this method (or any query, it seems to be 1 runspace, 1 query). It usually brings back about 30,000 results and the max size I can get at a time is 5,000, making the process pretty time-consuming.

I'm new to this kind of Powershell/C# integration so I'm not sure what I'm missing. If any of you know how I might include the filtering or have any advice/best practices when dealing with this type of operations I would greatly appreciate it.

1 Answers1

0

You shouldn't need to use Invoke-Command, assuming your runspace is connected to Exchange via New-PSSession & Import-PSSession. See this post on how to do that: Exchange PowerShell commands through C#.

The reason adding "| Select..." failed is it needs to be in the ScriptBlock.Create() string. Anyhow, below is (imho) a cleaner way to do this:

using (var powershell = PowerShell.Create())
{
    powershell.Runspace = runspace;
    powershell
       .AddCommand("Get-MessageTrace")
       .AddParameter("StartDate", previousDate)
       .AddParameter("EndDate", currentDate)
       .AddParameter("PageSize", pageSize)
       .AddParameter("Page", currentPage)
       .AddCommand("Select-Object")
       .AddParameter("Property", new string[] { "Received", "SenderAddress", "RecipientAddress", "Size" });

    Console.WriteLine("Executing query for page: " + currentPage);
    return powershell.Invoke().ToList();
}

You should be able to re-use your runspace without recreating it each time. However, another way to do this is to use a PowerShell object instead of the runspace. See the above link for details on that as well.

Michael Tucker
  • 205
  • 2
  • 10
  • Thanks for the advice! I managed to get it working without the Select statement but this promises a much better and way more efficient solution to the problem :) – GameCrazed Feb 14 '18 at 16:54