Server Fault is a question and answer site for system and network administrators. It's 100% free, no registration required.

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

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!!

share|improve this question

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
{
    $_.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}

P.S. I would have put this as a comment, but I do not have enough reputation at the moment...

share|improve this answer
    
This didn't work for me, but it got me in the ballpark. Inside the catch, the LoaderExceptions object is located here: $_.Exception.LoaderExceptions – Brett Nov 10 '15 at 16:11

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.

share|improve this answer

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

share|improve this answer
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. – jscott Mar 10 '13 at 3:20

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.

share|improve this answer
    
Try $Error[0].Exception.LoaderExceptions and following Eris's advise. – Tahir Hassan Jun 11 '14 at 15:33

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.

share|improve this answer
2  
And... what was the proper constructor string? This doesn't really answer the question the way it's written. Also, welcome to ServerFault! – austinian Aug 5 '15 at 3:48

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.