Showing posts with label reflection. Show all posts
Showing posts with label reflection. Show all posts

Wednesday, April 19, 2017

Calling constructor of an internal class

I keep running into code that tries to "hide" from being used such as making classes internal or private. It is a royal pain in the ass when debugging.

Fortunately, reflection is very easy with powershell so we can do something like this:

$parameters = @(some-array-of-parameters)
$assemblyName='full-name-of-the-assembly'
$typeName = 'full-name-of-the-type'
Add-Type -AssemblyName $assemblyName
$assembly = [Reflection.Assembly]::Load($assemblyName)
$bindingFlags = [Reflection.BindingFlags]"Default,NonPublic" # also include Static if needed
$t = $assembly.GetType($typeName)
$m = $t.GetConstructors() | Where-Object {$_.GetParameters().Count -gt 0} # in my case, I happen to be looking for a non-default constructor
$myclassinstance = $m.Invoke($parameters)



Monday, December 1, 2014

Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information

I have been using the following Powershell to browse around some assemblies
$assembly = [Reflection.Assembly]::Load('myassembly')
$assembly.GetTypes()

Sometimes, I get the following exception:
Exception calling "GetTypes" with "0" argument(s): "Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information."
At line:1 char:19
+ $assembly.GetTypes <<<< ()
    + CategoryInfo          : NotSpecified: (:) [], MethodInvocationException
    + FullyQualifiedErrorId : DotNetMethodException


To get at the actual error, I use the following:
$x = $Error[0]
$x.Exception.GetBaseException().LoaderExceptions

Then all I had to do was to load the assemblies that were listed and my initial Load() now works.

Monday, May 26, 2014

Calling private member using reflection in Powershell

Often I have to put together some Powershell scripts for troubleshooting. These scripts are based on some c# code. Recently, I had to mimic the behaviour of a call to a private member overload of GetTags in the Microsoft.Office.Server.SocialData.SocialTagManager class.

$site = Get-SPSite my-site-url
$context = Get-SPServiceContext($site)
$socialTagManager = New-Object -TypeName Microsoft.Office.server.SocialData.SocialTagManager -ArgumentList $context

# Get the type definition
$type = [type]'Microsoft.Office.Server.SocialData.SocialTagManager'

# List the GetTags members
($socialTagManager | Get-Member GetTags).Definition.Replace("), ", ")`n")

This results in (just the public members):
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.Office.Server.UserProfiles.UserProfile user)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.Office.Server.UserProfiles.UserProfile user, int maximumItemsToReturn)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.Office.Server.UserProfiles.UserProfile user, int maximumItemsToReturn, int startIndex)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri url)


Now use Reflection

# Which methods to list
$bindingFlags = [Reflection.BindingFlags] "Default,NonPublic,Instance"

# List the methods
$type.GetMethods($bindingFlags) | Where-Object {$_.Name -eq 'GetTags'} | ForEach-Object {$_.GetParameters() | Select-Object Member -First 1}

This results in (both public and private members);
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.DateTime, System.DateTime)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.DateTime, System.DateTime, Int32)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.DateTime, System.DateTime, Int32, Int32)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri, Microsoft.Office.Server.UserProfiles.UserProfile, System.Nullable`1[System.DateTime], System.Nullable`1[System.DateTime])
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri, Int32)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.Uri, Int32, Microsoft.Office.Server.SocialData.SocialItemPrivacy)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.SharePoint.Taxonomy.Term[], Int32, Microsoft.Office.Server.SocialData.SocialItemPrivacy)
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.Office.Server.UserProfiles.UserProfile, Int32, Int32, Boolean, System.Nullable`1[System.DateTime], System.Nullable`1[System.DateTime])
Microsoft.Office.Server.SocialData.SocialTag[] GetTags(Microsoft.Office.Server.UserProfiles.UserProfile, Int32, Int32, Boolean, System.Nullable`1[System.DateTime], System.Nullable`1[System.DateTime], System.Nullable`1[System.Guid])


Now to call a private member. Let's call: Microsoft.Office.Server.SocialData.SocialTag[] GetTags(System.DateTime, System.DateTime, Int32, Int32)


$startTime = [DateTime]'2014-05-01 00:00:00'
$endTime = [DateTime]'2014-05-31 00:00:00'
$maximumItemsToReturn = 1000
$startIndex = 0
$typeList = @([type]'DateTime', [type]'DateTime', [type]'Int32', [type]'Int32')
$method = $socialTagManager.GetType().GetMethod('GetTags', $bindingFlags, $null, $typeList, $null)
$terms = $method.Invoke($socialTagManager, [Object[]] @($startTime, $endTime, $maximumItemsToReturn, $startIndex))
$terms | Format-Table @{l='Term';e={$_.Term.Name}}, Title -AutoSize




Friday, April 5, 2013

Managing assemblies with Powershell

A simple way to access assemblies and see what's in them. Still a work in progress. I hope to add more tricks to this post soon.

Load in the assembly
$assembly = [Reflection.Assembly]::LoadFile($assemblyPath)
or
$assembly = [Reflection.Assembly]::Load($assemblyName)

Get details on a type defined in the assembly
$type = $assembly.DefinedTypes | Where-Object {$_.Name -eq $typeName}
$type.DeclaredConstructors | ForEach-Object {$_.ToString()}
$type.DeclaredMethods | ForEach-Object {$_.ToString()}

To load the assembly for use
Add-Type -Path $assemblyPath #if assembly in file
or
Add-Type -AssemblyName $assemblyName #if assembly in GAC
For some reason $assemblyName must be the full name contrary to the documentation in Add-Type

Get all assemblies in current AppDomain
[AppDomain]::CurrentDomain.GetAssemblies() | Select-Object FullName | Sort-Object FullName

References:
System.Reflection.Assembly class
Add-Type cmdlet
AppDomain class