31

I have a .NET assembly (a dll) which is an API to backup software we use here. It contains some properties and methods I would like to take advantage of in my Powershell script(s). However, I am running into a lot of issues with first loading the assembly, then using any of the types once the assembly is loaded.

The complete file path is:

C:\rnd\CloudBerry.Backup.API.dll 

In Powershell I use:

$dllpath = "C:\rnd\CloudBerry.Backup.API.dll" Add-Type -Path $dllpath 

I get the error below:

Add-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. At line:1 char:9 + Add-Type <<<< -Path $dllpath + CategoryInfo : NotSpecified: (:) [Add-Type], ReflectionTypeLoadException + FullyQualifiedErrorId : System.Reflection.ReflectionTypeLoadException,Microsoft.PowerShell.Commands.AddTypeComma ndAdd-Type : Unable to load one or more of the requested types. Retrieve the LoaderExceptions property for more information. 

Using the same cmdlet on another .NET assembly, DotNetZip, which has examples of using the same functionality on the site also does not work for me.

I eventually find that I am seemingly able to load the assembly using reflection:

[System.Reflection.Assembly]::LoadFrom($dllpath) 

Although I don't understand the difference between the methods Load, LoadFrom, or LoadFile that last method seems to work.

However, I still seem to be unable to create instances or use objects. Each time I try, I get errors that describe that Powershell is unable to find any of the public types.

I know the classes are there:

$asm = [System.Reflection.Assembly]::LoadFrom($dllpath) $cbbtypes = $asm.GetExportedTypes() $cbbtypes | Get-Member -Static 

---- start of excerpt ----

 TypeName: CloudBerryLab.Backup.API.BackupProvider Name MemberType Definition ---- ---------- ---------- PlanChanged Event System.EventHandler`1[CloudBerryLab.Backup.API.Utils.ChangedEventArgs] PlanChanged(Sy... PlanRemoved Event System.EventHandler`1[CloudBerryLab.Backup.API.Utils.PlanRemoveEventArgs] PlanRemoved... CalculateFolderSize Method static long CalculateFolderSize() Equals Method static bool Equals(System.Object objA, System.Object objB) GetAccounts Method static CloudBerryLab.Backup.API.Account[], CloudBerry.Backup.API, Version=1.0.0.1, Cu... GetBackupPlans Method static CloudBerryLab.Backup.API.BackupPlan[], CloudBerry.Backup.API, Version=1.0.0.1,... ReferenceEquals Method static bool ReferenceEquals(System.Object objA, System.Object objB) SetProfilePath Method static System.Void SetProfilePath(string profilePath) 

----end of excerpt----

Trying to use static methods fail, I don't know why!!!

[CloudBerryLab.Backup.API.BackupProvider]::GetAccounts() Unable to find type [CloudBerryLab.Backup.API.BackupProvider]: make sure that the assembly containing this type is load ed. At line:1 char:42 + [CloudBerryLab.Backup.API.BackupProvider] <<<< ::GetAccounts() + CategoryInfo : InvalidOperation: (CloudBerryLab.Backup.API.BackupProvider:String) [], RuntimeException + FullyQualifiedErrorId : TypeNotFound 

Any guidance appreciated!!

6 Answers 6

19

Could you surround the Add-Type with a try catch and print the LoaderExceptions property, as the error is stating to do. It may provide an exception with a more detailed error message.

try { Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll" } catch { $_.Exception.LoaderExceptions | % { Write-Error $_.Message } } 
3
  • 2
    isn't there a way to use relative path? Commented Sep 18, 2016 at 6:06
  • 1
    The opening curly bracket must be on the same line as the percent sign: $_.Exception.LoaderExceptions | % { Commented Aug 24, 2020 at 19:41
  • At the time of posting, which was I believe PS2.0? That was valid syntax. Has this changed in 6+? Asking for my own curiosity. Commented Oct 24, 2020 at 21:46
5

Some of the methods above either did not work for me or were unclear.

Here's what I use to wrap -AddPath calls and catch LoaderExceptions:

try { Add-Type -Path "C:\path\to.dll" } catch [System.Reflection.ReflectionTypeLoadException] { Write-Host "Message: $($_.Exception.Message)" Write-Host "StackTrace: $($_.Exception.StackTrace)" Write-Host "LoaderExceptions: $($_.Exception.LoaderExceptions)" } 

Reference
https://social.technet.microsoft.com/Forums/sharepoint/en-US/dff8487f-69af-4b64-ab83-13d58a55c523/addtype-inheritance-loaderexceptions

3

I found this link: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html

He says, ".LoadWithPartialName" has been deprecated. Therefore, instead of continuing to implement Add-Type with that method, it uses a static, internal table to translate the "partial name" to a "full name". In the example given in the question, CloudBerry.Backup.API.dll does not have an entry in PowerShell's internal table, which is why [System.Reflection.Assembly]::LoadFrom($dllpath) works. It is not using the table to look up a partial name.

1

The LoaderExceptions are hidden inside the error record. If the add-type error was the last one in the error list, use $Error[0].InnerException.LoaderExceptions to show the errors. Most likely, your library is dependent on another that has not been loaded. You can either Add-Type each one, or just make a list and use the -ReferencedAssemblies argument to Add-Type.

1
  • Try $Error[0].Exception.LoaderExceptions and following Eris's advise. Commented Jun 11, 2014 at 15:33
0

I used the following setup to load a custom csharp control in powershell. It allows the control to be customized and utilized from within powershell.

here is the blog link

http://justcode.ca/wp/?p=435

and here is the codeproject link with source

http://www.codeproject.com/Articles/311705/Custom-CSharp-Control-for-Powershell

1
  • 3
    Welcome to Server Fault! We really do prefer that answers contain content not pointers to content. Whilst this may theoretically answer the question, it would be preferable to include the essential parts of the answer here, and provide the link for reference. Commented Mar 10, 2013 at 3:20
-2

I guess by now you MIGHT have found an answer to this phenomena. I ran upon this post after encountering the same problem...I could load the assembly, and view the types contained in the assembly, but was unable to instanciate a instance of it from a static class. Was it EFTIDY. Tidy, EFTidyNet.TidyNet.Options or what? Ooooo Weeee...Problems...problems...it could be anything. And looking through the static methods and types of the DLL didn't reveal anything promising. Now I was getting depressed. I had it working in a compiled C# program, but for my use I wanted to have it running in a interpeted language...powershell.

My solution I found, and it's still being proven, but I'm elated and wanted to share this. Build a small console.exe app exercising the func that I was interested in and then view it in something that would decompile it or show the IL code. I used Red-Gate's reflector and the powershell language generator add-in and Wallah! it showed what the proper constructor string was! :-) Try it. and I hope it works for whomever is faced with this problem.

1
  • 2
    And... what was the proper constructor string? This doesn't really answer the question the way it's written. Also, welcome to ServerFault! Commented Aug 5, 2015 at 3:48

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.