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)
$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!")
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]):
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.)
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[,]).
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.
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() ...