Bagaimana cara menambahkan rakitan .NET dengan benar ke sesi Powershell?

24

Saya memiliki .NET assembly (dll) yang merupakan API untuk membuat cadangan perangkat lunak yang kami gunakan di sini. Ini berisi beberapa properti dan metode yang ingin saya manfaatkan dalam skrip Powershell saya. Namun, saya mengalami banyak masalah dengan pertama-tama memuat rakitan, kemudian menggunakan salah satu jenis setelah rakitan dimuat.

Jalur file lengkap adalah:

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

Di Powershell saya menggunakan:

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

Saya mendapatkan kesalahan di bawah ini:

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.

Menggunakan cmdlet yang sama pada rakitan .NET lainnya, DotNetZip , yang memiliki contoh penggunaan fungsi yang sama di situs juga tidak berfungsi untuk saya.

Saya akhirnya menemukan bahwa saya tampaknya dapat memuat perakitan menggunakan refleksi:

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

Meskipun saya tidak mengerti perbedaan antara metode Load, LoadFrom, atau LoadFile, metode terakhir ini sepertinya berfungsi.

Namun, sepertinya saya masih tidak dapat membuat instance atau menggunakan objek. Setiap kali saya mencoba, saya mendapatkan kesalahan yang menggambarkan bahwa Powershell tidak dapat menemukan tipe publik apa pun.

Saya tahu kelas ada di sana:

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

---- mulai dari kutipan ----

   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)

---- Akhir kutipan ----

Mencoba menggunakan metode statis gagal, saya tidak tahu kenapa !!!

[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

Bimbingan apa pun dihargai !!

amandion
sumber

Jawaban:

15

Bisakah Anda mengelilinginya Add-Typedengan mencoba menangkap dan mencetak properti LoaderExceptions, karena kesalahannya adalah untuk melakukan. Mungkin memberikan pengecualian dengan pesan kesalahan yang lebih rinci.

try
{
    Add-Type -Path "C:\rnd\CloudBerry.Backup.API.dll"
}
catch
{
    $_.Exception.LoaderExceptions | %
    {
        Write-Error $_.Message
    }
}
jessenich
sumber
9
Ini tidak berhasil untuk saya, tapi itu membuat saya di stadion baseball. Di dalam tangkapan, objek LoaderExceptions terletak di sini: $ _. Exception.LoaderExceptions
Brett
apakah tidak ada cara untuk menggunakan jalur relatif?
Amit
3

Saya menemukan tautan ini: http://www.madwithpowershell.com/2013/10/add-type-vs-reflectionassembly-in.html

Dia berkata, ".LoadWithPartialName" telah ditinggalkan. Oleh karena itu, alih-alih terus mengimplementasikan Add-Type dengan metode itu, ia menggunakan tabel internal statis untuk menerjemahkan "nama parsial" menjadi "nama lengkap". Dalam contoh yang diberikan dalam pertanyaan, CloudBerry.Backup.API.dlltidak memiliki entri di tabel internal PowerShell, itulah sebabnya [System.Reflection.Assembly]::LoadFrom($dllpath)bekerja. Itu tidak menggunakan tabel untuk mencari nama parsial.

Slogmeister Luar Biasa
sumber
2

Beberapa metode di atas tidak bekerja untuk saya atau tidak jelas.

Inilah yang saya gunakan untuk menutup panggilan -AddPath dan menangkap 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)"
}

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

Ralph Willgoss
sumber
0

Saya menggunakan pengaturan berikut untuk memuat kontrol csharp kustom di PowerShell. Ini memungkinkan kontrol untuk disesuaikan dan digunakan dari dalam PowerShell.

di sini adalah tautan blog

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

dan di sini adalah tautan proyek dengan sumber

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

justcode_ca
sumber
3
Selamat Datang di Kesalahan Server! Kami benar-benar lebih suka jawaban berisi konten bukan petunjuk ke konten. Sementara ini secara teoritis dapat menjawab pertanyaan, akan lebih baik untuk memasukkan bagian-bagian penting dari jawaban di sini, dan menyediakan tautan untuk referensi.
jscott
0

The LoaderExceptionstersembunyi di dalam catatan kesalahan. Jika kesalahan add-type adalah yang terakhir dalam daftar kesalahan, gunakan $Error[0].InnerException.LoaderExceptionsuntuk menunjukkan kesalahan. Kemungkinan besar, pustaka Anda bergantung pada pustaka lain yang belum dimuat. Anda bisa Add-Typemasing - masing, atau hanya membuat daftar dan menggunakan -ReferencedAssembliesargumen untuk Add-Type.

Eris
sumber
Coba $ Error [0] .Exception.LoaderExceptions dan ikuti saran Eris.
Tahir Hassan
-1

Saya kira sekarang Anda mungkin sudah menemukan jawaban untuk fenomena ini. Saya berlari pada posting ini setelah mengalami masalah yang sama ... Saya bisa memuat perakitan, dan melihat jenis yang terkandung dalam perakitan, tetapi tidak dapat mem-instanciate instance dari kelas statis. Apakah EFTIDY. Tidy, EFTidyNet.TidyNet.Options atau apa? Ooooo Weeee ... Masalah ... masalah ... bisa jadi apa saja. Dan melihat melalui metode statis dan jenis DLL tidak mengungkapkan apa pun yang menjanjikan. Sekarang saya mengalami depresi. Saya memilikinya bekerja dalam program C # dikompilasi, tetapi untuk penggunaan saya, saya ingin menjalankannya dalam bahasa yang saling terkait ... PowerShell.

Solusi saya saya temukan, dan itu masih terbukti, tetapi saya gembira dan ingin berbagi ini. Buat aplikasi console.exe kecil yang menjalankan fungsi yang saya minati lalu melihatnya dalam sesuatu yang akan mendekompilasi atau menunjukkan kode IL. Saya menggunakan reflektor Red-Gate dan add-in generator bahasa powershell dan Wallah! itu menunjukkan apa string konstruktor yang tepat! :-) Cobalah. dan saya harap ini berhasil karena siapa pun dihadapkan dengan masalah ini.

Kim D. Alexander
sumber
2
Dan ... apa string konstruktor yang tepat? Ini tidak benar-benar menjawab pertanyaan dengan cara itu ditulis. Juga, selamat datang di ServerFault!
austinianus