C# code to powershell

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

IObjectReader<MonitoringObject> reader = mg.EntityObjects.GetObjectReader<MonitoringObject>(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

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.

Scratch that. How do I call a parameterless generic method from Powershell v3? - Stack Overflow 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!")

Thank you Dave. I am looking into this.

Cheers

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 https://www.leeholmes.com/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 GitHub - 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)

hi Dave,

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

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

Cheers
Tore

Thanks :slight_smile:

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<T>), 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<string> 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.

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<List<T>> . 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.

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[,]).

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” :slight_smile: that i refer to, if you have some time please take a look.

$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<WorksheetPart>()

Powershell?

addnewpart method description
AddNewPart Method T AddNewPartT, 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: (:slight_smile: [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
    

Hi Kiran,

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

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