How to access or set .NET class property from PowerShell

Microsoft

I have a .NET library and I want to call it's function/constructor from PowerShell. In this case expecting it to print a HyperLink on console. 

Here is the schema for the Log class 
pooja520_0-1668005563715.png

pooja520_2-1668005756852.png

 

pooja520_1-1668005728357.png


In C#, it is called as 

Log.Trace(new CommentTrace("Comment message") { XmlAnnotation="<SupportingInfo><Item /></SupportingInfo>" });
    Log.Trace(new  CommentTrace("Error message") { XmlAnnotation
        = "<SupportingInfo>"
        + "<Item Name=\"Test Wiki\" Value=\"htpps://xyz.com\" Type =\"url\" />"
        + "</SupportingInfo>"
     });

 

How do I call it in powershell?

Trying 

[LOG]::Trace((New-Object CommentTrace 'URL Argument' -Property @{ XmlAnnotation="<SupportingInfo><Item Name='URL Hyperlink' Value='$URLValue' Type ='url'></item></SupportingInfo>"} ))

 

 

 

 

 

 

[LOG]::Trace((New-Object CommentTrace 'URL Argument' -Property @{ XmlAnnotation="<SupportingInfo><Item Name='URL Hyperlink' Value='$URLValue' Type ='url'></item></SupportingInfo>"} ))

 

 

 

 

 

 

However it ends up ignoring the XMLAnnotation property entirely. 

pooja520_0-1668008724739.png

Expected: to consider the XMLAnnotation passed and print the hyperlink


How to achieve get this working in powershell.
And how to learn converting .NET OOOPs code in powershell



 

1 Reply

@pooja520 

 

Without being familiar with the LogTrace class you reference, and without seeing the definition behind the TraceImpl method, it's hard to be specific. I'd also wager this isn't the best place to ask simply because most of the enquiries in here are more of the basic "how to use PowerShell" variety.

 

For my part, based on the above limitations, all I can put forward is a loose analogy that is structurally similar to yours.

 

Here is the reductionist C# code, where - roughly:

 

  • SomeRandomClass = your LogTrace class/struc (I don't know which but it doesn't really matter);
  • SomeRandomStruc = your CommentTrace struc;
  • SomeRandomConsumer = your static Log class containing the Trace method.

 

 

using System;

namespace FooLibrary
{
    public class SomeRandomClass
    {
        public string Message;
        public string Annotation;

        public SomeRandomClass(string message)
        {
            Message = message;
        }

        public override string ToString()
        {
            if (!string.IsNullOrWhiteSpace(Annotation))
                return ($"{ Message } -> { Annotation }");
            else
            if (!string.IsNullOrWhiteSpace(Message))
                return (Message);
            else
                return (null);
        }
    }

    public struct SomeRandomStruct
    {
        internal SomeRandomClass RandoClass;

        public string Annotation
        {
            set
            {
                RandoClass.Annotation = value;
            }
        }

        public SomeRandomStruct(string message)
        {
            RandoClass = new SomeRandomClass(message);
        }
    }

    public static class SomeRandomConsumer
    {
        public static void Print(SomeRandomStruct randoStruct)
        {
            Console.WriteLine(randoStruct.RandoClass);
        }
    }
}

 

 

Compiling this and importing it using Add-Type, I've produced the following four examples:

 

LainRobertson_0-1668166467329.png

 

I'm going to focus on the Annotation member from the above examples as the analogy for your XmlAnnotation.

 

Example 1: Constructor-only instantiation.

Like the constructor from your CommentTrace struc, I'm initialising "Message" in the underlying RandoClass variable but not "Annotation".

 

You can see in the output from this first example that PowerShell can only see the members from the struc, which in this case is only Annotation, which in turn has no getter, hence the null value for Annotation.

 

Example 2: Verifying the impact of having no getter.

Not much to say here. The error's just confirming that trying to read Annotation generates the expected "forget about it" response from PowerShell since no getter is defined in the struc - the same as your struc.

 

So, now we move on to looking at your static Trace method, which in my case is the Print method. At this point, my SomeRandomStruc (your CommentTrace) struc is largely irrelevant, as the output string is really coming from the underlying SomeRandomClass (your LogTrace) via the RandoClass (your LogTrace) variable within the struc.

 

Example 3: Calling static Print using constructor-only instantiation.

No surprises here. Because Annotation is still null, the output only features Message.

 

Example 4: Calling static Print whilst providing a value for Annotation.

And now we finally get to the scenario most relevant to your question, and the only important takeaway here is that it works using exactly the same PowerShell command line structure you have used.

 

Having use "-Property @{ Annotation = "FunkyTown" }", my output does indeed reflect the fact that the property specification has worked.

 

Summary

I don't think you're running into issues with the command line you've used within PowerShell - that looks fine to me and works as shown above in Example 4.

 

I can only conclude there is something wrong with the C# implementation.

 

However, as I pointed out at the start, I've had to generalise a lot given the absence of important artefacts, so if I've missed something in the process, my apologies. By all means fill in the gaps where I've had to make assumptions.

 

Additional notes

Leaving out the getter isn't a great idea when it comes to PowerShell, as the general rule of thumb is that if you're going to have a property expose at all then the value really should be readable. In this scenario, we're talking about Annotation within the CommentTrace struc.

 

PowerShell has got a different audience and purpose compared to more formal, structured languages like C#. If you put the two in a Venn diagram, there'd certainly be good overlap, but in PowerShell there's more of a bent towards ad hoc engagement and intuitiveness, meaning things like properties that can never - by design - contain a value are out of place in PowerShell despite making perfect sense within C#.

 

Using PowerShell nomenclature, a method named something like "void SetXmlAnnotation" would be more intuitive to the PowerShell community, who frequently don't have a formal programming background.

 

Cheers,

Lain