Hầu hết mọi người đều biết rằng điều đó System.Reflection.Assembly.LoadWithPartialName
không được chấp nhận, nhưng hóa ra điều Add-Type -AssemblyName Microsoft.VisualBasic
đó không hành xử tốt hơn nhiều so vớiLoadWithPartialName
:
Thay vì thực hiện bất kỳ nỗ lực nào để phân tích yêu cầu của bạn trong ngữ cảnh hệ thống của bạn, [Loại bổ sung] nhìn vào một bảng nội bộ tĩnh để dịch "tên một phần" thành "tên đầy đủ".
Nếu "tên một phần" của bạn không xuất hiện trong bảng của họ, tập lệnh của bạn sẽ thất bại.
Nếu bạn có nhiều phiên bản lắp ráp được cài đặt trên máy tính của bạn, không có thuật toán thông minh nào để chọn giữa chúng. Bạn sẽ nhận được bất cứ cái nào xuất hiện trong bảng của họ, có thể là cái cũ hơn, lỗi thời.
Nếu các phiên bản bạn đã cài đặt hoàn toàn mới hơn phiên bản lỗi thời trong bảng, tập lệnh của bạn sẽ thất bại.
Add-Type không có trình phân tích cú pháp thông minh của "tên một phần" như thế nào
.LoadWithPartialNames
.
Những gì Microsoft nói bạn thực sự cần phải làm là một cái gì đó như thế này:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Hoặc, nếu bạn biết đường dẫn, một cái gì đó như thế này:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Tên dài được đặt cho lắp ráp được gọi là tên mạnh , cả hai đều là duy nhất cho phiên bản và lắp ráp, và đôi khi còn được gọi là tên đầy đủ.
Nhưng điều này để lại một vài câu hỏi chưa được trả lời:
Làm cách nào để xác định tên mạnh của những gì thực sự được tải trên hệ thống của tôi với một phần tên nhất định?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Chúng cũng nên hoạt động:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Nếu tôi muốn tập lệnh của mình luôn sử dụng một phiên bản cụ thể của một tệp dll nhưng tôi không thể chắc chắn về nơi nó được cài đặt, làm cách nào để xác định tên mạnh là gì từ dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Hoặc là:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Nếu tôi biết tên mạnh, làm cách nào để xác định đường dẫn dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
Và, trên một mạch tương tự, nếu tôi biết tên loại của những gì tôi đang sử dụng, làm thế nào để tôi biết nó được lắp ráp từ đâu?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Làm thế nào để tôi thấy những gì lắp ráp có sẵn?
Tôi đề nghị mô-đun GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
hoạt động khá tốt.
- Làm thế nào tôi có thể xem danh sách
Add-Type
sử dụng?
Điều này phức tạp hơn một chút. Tôi có thể mô tả cách truy cập nó cho bất kỳ phiên bản PowerShell nào bằng bộ phản xạ .Net (xem bản cập nhật bên dưới cho PowerShell Core 6.0).
Đầu tiên, hãy tìm ra thư viện nào Add-Type
đến từ:
Get-Command -Name Add-Type | Select-Object -Property DLL
Mở DLL kết quả với phản xạ của bạn. Tôi đã sử dụng ILSpy cho việc này vì nó là FLOSS, nhưng bất kỳ bộ phản xạ C # nào cũng hoạt động. Mở thư viện đó và nhìn vào Microsoft.Powershell.Commands.Utility
. Dưới Microsoft.Powershell.Commands
, nên có AddTypeCommand
.
Trong danh sách mã cho điều đó, có một lớp riêng , InitializeStrongNameDictionary()
. Đó là danh sách từ điển ánh xạ các tên ngắn thành tên mạnh. Có gần 750 mục trong thư viện tôi đã xem.
Cập nhật: Bây giờ PowerShell Core 6.0 là nguồn mở. Đối với phiên bản đó, bạn có thể bỏ qua các bước trên và xem mã trực tuyến trong kho lưu trữ GitHub của họ . Tuy nhiên, tôi không thể đảm bảo rằng mã đó phù hợp với bất kỳ phiên bản PowerShell nào khác.