Більшість людей до цих пір знає, що System.Reflection.Assembly.LoadWithPartialName
це застаріле, але виявляється, що Add-Type -AssemblyName Microsoft.VisualBasic
він веде себе не набагато краще, ніжLoadWithPartialName
:
Замість того, щоб робити будь-які спроби аналізувати ваш запит у контексті вашої системи, [Add-Type] розглядає статичну внутрішню таблицю, щоб перевести "часткове ім'я" на "повне ім'я".
Якщо ваше "часткове ім'я" не відображається в їхній таблиці, ваш сценарій вийде з ладу.
Якщо на вашому комп'ютері встановлено кілька версій збірки, не існує інтелектуального алгоритму вибору між ними. Ви збираєтесь отримати те, що з’явиться в їх таблиці, ймовірно, старіше, застаріле.
Якщо встановлені вами версії новіші, ніж застарілі в таблиці, ваш скрипт вийде з ладу.
Add-Type не має інтелектуального аналізатора типу "часткових імен"
.LoadWithPartialNames
.
Microsoft каже, що ви насправді повинні зробити, це щось подібне:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Або, якщо ви знаєте шлях, щось подібне:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Ця довга назва, дана для зборів, відома як сильна назва , яка є унікальною як для версії, так і для складання, а також іноді називається повним ім'ям.
Але це залишає кілька питань без відповіді:
Як визначити сильну назву того, що насправді завантажується в мою систему із заданим частковим іменем?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Вони також повинні працювати:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Якщо я хочу, щоб мій сценарій завжди використовував певну версію .dll, але я не можу бути впевненим, де він встановлений, як я можу визначити, що таке сильне ім'я від .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Або:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Якщо я знаю сильне ім'я, як визначити шлях .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
І, якщо я знаю назву типу того, що я використовую, як я знаю, з якої збірки вона йде?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Як я бачу, які збірки доступні?
Я пропоную модуль GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
працює досить добре.
- Як я бачу список, який
Add-Type
використовує?
Це трохи складніше. Я можу описати, як отримати доступ до нього для будь-якої версії PowerShell з відбивачем .Net (див. Оновлення нижче для PowerShell Core 6.0).
Спочатку з’ясуйте, з якої бібліотеки Add-Type
походить:
Get-Command -Name Add-Type | Select-Object -Property DLL
Відкрийте отриману DLL за допомогою рефлектора. Я використовував для цього ILSpy, тому що це FLOSS, але будь-який C # рефлектор повинен працювати. Відкрийте цю бібліотеку і загляньте Microsoft.Powershell.Commands.Utility
. Під Microsoft.Powershell.Commands
, повинно бути AddTypeCommand
.
У коді лістингу для цього є приватний клас InitializeStrongNameDictionary()
. Тут перелічено словник, який відображає короткі назви з сильними іменами. У бібліотеці, яку я переглянув, майже 750 записів.
Оновлення: Тепер, коли PowerShell Core 6.0 є відкритим кодом. У цій версії ви можете пропустити вищезазначені кроки і побачити код безпосередньо онлайн у своєму сховищі GitHub . Я не можу гарантувати, що цей код відповідає будь-якій іншій версії PowerShell.