Większość ludzi już wie, że System.Reflection.Assembly.LoadWithPartialName
jest to przestarzałe, ale okazuje się, że Add-Type -AssemblyName Microsoft.VisualBasic
nie zachowuje się dużo lepiej niżLoadWithPartialName
:
Zamiast próbować analizować żądanie w kontekście systemu, [Add-Type] sprawdza statyczną, wewnętrzną tabelę, aby przetłumaczyć „częściową nazwę” na „pełną nazwę”.
Jeśli Twoja „częściowa nazwa” nie pojawi się w ich tabeli, skrypt zawiedzie.
Jeśli masz wiele wersji zestawu zainstalowanych na komputerze, nie ma inteligentnego algorytmu do wyboru między nimi. Otrzymasz dowolny, który pojawi się w ich tabeli, prawdopodobnie starszy, nieaktualny.
Jeśli wszystkie zainstalowane wersje są nowsze niż przestarzała w tabeli, skrypt nie powiedzie się.
Add-Type nie ma inteligentnego analizatora składni „nazw częściowych”, takich jak
.LoadWithPartialNames
.
Microsoft twierdzi, że faktycznie powinieneś zrobić coś takiego:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Lub, jeśli znasz ścieżkę, coś takiego:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Ta długa nazwa nadana zespołowi jest znana jako silna nazwa , która jest unikalna zarówno dla wersji, jak i zestawu, a czasami jest również nazywana pełną nazwą.
Ale to pozostawia kilka pytań bez odpowiedzi:
Jak określić silną nazwę tego, co faktycznie jest ładowane w moim systemie z podaną nazwą częściową?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Te też powinny działać:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Jeśli chcę, aby mój skrypt zawsze korzystał z określonej wersji pliku .dll, ale nie mam pewności, gdzie jest zainstalowany, w jaki sposób mogę określić, jaka jest silna nazwa z pliku .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Lub:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Jeśli znam silną nazwę, jak określić ścieżkę .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
I w podobny sposób, jeśli znam nazwę typu tego, czego używam, skąd mam wiedzieć, z jakiego zespołu pochodzi?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Jak mogę sprawdzić, jakie zestawy są dostępne?
Proponuję moduł GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
działa całkiem nieźle.
- Jak mogę zobaczyć listę, która
Add-Type
używa?
To jest trochę bardziej złożone. Mogę opisać, jak uzyskać do niego dostęp dla dowolnej wersji programu PowerShell z reflektorem .Net (zobacz aktualizację poniżej dotyczącą programu PowerShell Core 6.0).
Najpierw dowiedz się, z której biblioteki Add-Type
pochodzi:
Get-Command -Name Add-Type | Select-Object -Property DLL
Otwórz wynikową bibliotekę DLL za pomocą reflektora. Użyłem ILSpy za to, bo to FLOSS, ale wszelkie C # reflektor powinien działać. Otwórz tę bibliotekę i zajrzyj do środka Microsoft.Powershell.Commands.Utility
. Pod Microsoft.Powershell.Commands
spodem powinno być AddTypeCommand
.
W kodzie witryny, że znajduje się prywatny klasy InitializeStrongNameDictionary()
. Zawiera słownik, który odwzorowuje krótkie nazwy na silne nazwy. W bibliotece, którą przeglądałem, jest prawie 750 pozycji.
Aktualizacja: teraz, gdy program PowerShell Core 6.0 jest oprogramowaniem typu open source. W przypadku tej wersji możesz pominąć powyższe kroki i zobaczyć kod bezpośrednio online w ich repozytorium GitHub . Nie mogę jednak zagwarantować, że ten kod pasuje do dowolnej innej wersji programu PowerShell.