C# code to powershell

This topic contains 11 replies, has 3 voices, and was last updated by  kiran 3 years, 4 months ago.

  • Author
    Posts
  • #13971

    Tore Groneng
    Participant

    I am currently trying to convert some c# code for the SCOM SDK to powershell, however I am struck on this line:

    IObjectReader reader = mg.EntityObjects.GetObjectReader(monClass, ObjectQueryOptions.Default);

    ObjectQueryOptions.Default needs to be replaced with: [Microsoft.EnterpriseManagement.Common.ObjectQueryOptions]::Default, and I have the monClass like so:

    [string]$criteria = "Name = 'system.computer'"
    $monClass = New-Object Microsoft.EnterpriseManagement.Configuration.ManagementPackClassCriteria($criteria)

    Any suggestions

    C# code file is attached

  • #13973

    Dave Wyatt
    Moderator

    If I remember correctly, there's currently no way to call generic methods from powershell. I'll test it later today and see if I can get it working.

  • #13974

    Dave Wyatt
    Moderator

    Scratch that. http://stackoverflow.com/questions/18774889/how-do-i-call-a-parameterless-generic-method-from-powershell-v3 gives an example of how to accomplish this using Reflection:

    $nonGenericClass = New-Object NonGenericClass
    $method = [NonGenericClass].GetMethod("SimpleGenericMethod")
    $gMethod = $method.MakeGenericMethod([string]) 
    # replace [string] with the type you want to use for T. 
    $gMethod.Invoke($nonGenericClass, "Welcome!")
    
  • #13978

    Tore Groneng
    Participant

    Thank you Dave. I am looking into this.

    Cheers

  • #13986

    Dave Wyatt
    Moderator

    This got me interested, so I've been tinkering with code to allow one to call a generic method with a single PowerShell command (and to make it as robust as possible.) After I worked on this for a while, I realized that Lee Holmes did something very similar years ago (see http://www.leeholmes.com/blog/2007/06/19/invoking-generic-methods-on-non-generic-classes-in-powershell/ ), but his version seems to have had a couple of limitations. For example, if you need to pass a value of $null to any argument of the generic method, his code will throw an error when it tries to call GetType() on that argument. There's also a complete lack of the usual type conversion magic that goes on when you call .NET methods from PowerShell, when you use Reflection in this way, which will either result in not finding the method, or throwing an exception when you try to Invoke it.

    I haven't had a huge amount of time to spend on this yet, but what I have so far is up at https://github.com/dlwyatt/PSGenericMethods , and it seems to be working well in my tests so far. Calling a generic method with the function would look something like this (though I don't have the SCOM classes to test this, and you'd obviously need full type names instead of just [MonitoringObject] and [ObjectQueryOptions]):

    $reader = Invoke-GenericMethod -InputObject $mg.EntityObjects `
                                   -MethodName GetObjectReader `
                                   -GenericType MonitoringObject `
                                   -ArgumentList ($monClass, [ObjectQueryOptions]::Default)
    
  • #14021

    Tore Groneng
    Participant

    hi Dave,

    Hot-Dog, you don't beat about in the bush do you 🙂 A strike of brilliance above you usual genius stuff 🙂 Thank you, I really appreciate this.

    Let me give it a run and see if I can use those methods of yours.

    Cheers
    Tore

  • #14026

    Dave Wyatt
    Moderator

    Thanks 🙂

    I've spent some more time on this, and have it working with methods that contain optional parameters (parameters with default values). I've separated the worker functions out into a psm1 module and added some basic comment-based help to Invoke-GenericMethod.

    I also updated the code to handle methods that contain parameters that are generic types (ie, List), but am running into some problems invoking that type of method (even non-generic methods). I suspect that if I rewrite this function as a C# cmdlet, that problem will go away; it appears to be something PowerShell-related, and I may not be able to fix it. I'm getting the following exception:

    Exception calling "Invoke" with "2" argument(s): "Object of type 'System.Management.Automation.PSObject' cannot be converted to type 'System.Collections.Generic.List`1[System.String]'."

    Even though I've verified that the value being passed to Invoke is an object[] array containing a List object. I'm not sure where PSObject is entering the picture there. Aside from that little hiccup, it seems to be working great. If you get any other errors, let me know.

  • #14028

    Dave Wyatt
    Moderator

    Fixed the problem I was having with Generic types as arguments. I never did figure out 'why' it was happening, but I worked around it by writing a small C# helper to convert the PSObject instances back to their BaseObject references before calling MethodInfo.Invoke(). The latest version is up on the same GitHub link, and at this point, has worked in every test I've thought of to try to break it (including really annoying stuff like nested Generic type arguments, ie List> . I don't know if anyone would ever pass in something like that, but I wanted the function to work properly no matter what type of argument was being sent in.)

    Let me know if you have any trouble with it.

  • #14032

    Dave Wyatt
    Moderator

    Not sure if you've been following along with the updates today, but I found a few more ways to break the function and have updated it this evening to account for them (ref / out parameters, and generic array parameters, ie T[] and T[,]).

  • #14052

    Dave Wyatt
    Moderator

    Hi Kiran,

    Thanks for pointing that out! 🙂 I've updated the code; you can grab the latest version from GitHub.

  • #14106

    kiran
    Participant

    yup i dont get the error anymore :), thx for updating the module.

  • #14051

    kiran
    Participant

    Hi Dave

    i was looking for something similar and happened to stumble upon this post but having some difficulty getting it to work. If am hijacking this thread let me know i will start a new one. Just posted it here because my question is related.
    Here is the "it" 🙂 that i refer to, if you have some time please take a look.

    [reflection.assembly]::LoadWithPartialName("DocumentFormat.OpenXml.Packaging")
    [reflection.assembly]::LoadWithPartialName("DocumentFormat.OpenXml.Spreadsheet")

    $filename = "c:\temp\test.xlsx"
    $package1 = [DocumentFormat.OpenXml.Packaging.SpreadsheetDocument]::Create($fileName, [DocumentFormat.OpenXml.SpreadsheetDocumentType]::'Workbook', $false)
    $package1.AddWorkbookPart()
    $package1.WorkbookPart.Workbook = New-Object DocumentFormat.OpenXml.Spreadsheet.Workbook

    here is what i need to do:
    c#

    package1.WorkbookPart.AddNewPart()

    Powershell?

    addnewpart method description
    AddNewPart Method T AddNewPart[T](), T AddNewPart[T](string id), T AddNewPart[T](string contentType, string id)
    here the generic typename is : 'worksheetpart' and the methodname is 'addnewpart' , no arguements

    so i ran your function like so:

    Invoke-GenericMethod -InputObject $package1.WorkbookPart
    -MethodName AddNewPart
    -GenericType DocumentFormat.OpenXml.Packaging.WorksheetPart

    Get an error –


    Test-GenericMethodParameters : Cannot bind argument to parameter 'ParameterList' because it is an empty array.
    At psgenericmethods.psm1:153 char:57
    + if (Test-GenericMethodParameters -ParameterList $method.GetParameters() ...
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Test-GenericMethodParameters], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyArrayNotAllowed,Test-GenericMethodParameters

    Test-GenericMethodParameters : Cannot bind argument to parameter 'ParameterList' because it is an empty array.
    At psgenericmethods.psm1:153 char:57
    + if (Test-GenericMethodParameters -ParameterList $method.GetParameters() ...
    + ~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidData: (:) [Test-GenericMethodParameters], ParameterBindingValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorEmptyArrayNotAllowed,Test-GenericMethodParameters

    Invoke-GenericMethod : No matching method was found
    At line:1 char:1
    + Invoke-GenericMethod -InputObject $package1.WorkbookPart

    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Invoke-GenericMethod

You must be logged in to reply to this topic.