frostcake
frostcake

Reputation: 105

How to display PSObject in C#

I'm building a PowerShell host by C#, and I want to display the result after invoking PowerShell. Now I use the following method:

public static string GetLogQueriedString(
    PSMemberInfoCollection<PSPropertyInfo> PSPropertyCollection)
{
    string line = string.Empty;
    foreach (var item in PSPropertyCollection)
    {
        if (!line.Equals(string.Empty)) line += ",";
        line += item.Name + " : " + item.Value;
    }

    return line;
}

It works if the PSObject has many properties that I need, but in this situation, if the PSObject is a string, the result is not what I want. It will display "Length: 40", rather than the string itself.

And another question: if I execute several PowerShell commands, why will it display all the results, including the previous result. For example, I execute "ls; get-process", and it will display the result of "ls" and the result of "get-process".

Upvotes: 5

Views: 17133

Answers (2)

Parker C
Parker C

Reputation: 1

More of your code is needed, but just a clarification of the previous answer.... It may be helpful to think of PSObject LIKE an array, in that each value is a key-value pair. Because of this, if you try to explicitly cast like ToString, you'll get the object type, much like if you try to cast an array to a string you'll get a memory reference.

An easy solution is to use a foreach. For your code:

foreach(var r in results) {
  string toConsole = r.ToString()
}

Console.WriteLine(toConsole);

Upvotes: 0

Keith Hill
Keith Hill

Reputation: 201652

I think we need to see more of your code. The typical approach to display returned PSObjects is:

using (var ps = PowerShell.Create()) {
    while (true) {
        Console.WriteLine("Enter an expression:");
        string input = Console.ReadLine();
        if (String.IsNullOrWhiteSpace(input)) break;

        ps.AddScript(input);
        Collection<PSObject> results = ps.Invoke();
        foreach (var result in results) {
            Console.WriteLine(result);
        }
    }
}

If you don't need to access properties on the returned objects and all you're interested in is the formatted text try changing this line:

ps.AddScript(input + " | Out-String");

If you want to do custom formatting based on object type, you will need to test for the type and format as you see fit:

foreach (var result in results) {
    var baseObj = result.BaseObject;
    if (baseObj is System.Diagnostics.Process)
    {
        var p = (System.Diagnostics.Process) baseObj;
        Console.WriteLine("Handles:{0}, NPM:{1}, PM:{2}, etc", p.HandleCount, p.NonpagedSystemMemorySize, p.PagedMemorySize);
    }
    else {
        Console.WriteLine(result);
    }
}

Upvotes: 5

Related Questions