Der folgende PowerShell-Code
#Get a server object which corresponds to the default instance
$srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
... rest of the script ...
Gibt die folgende Fehlermeldung aus:
New-Object : Cannot find type [Microsoft.SqlServer.Management.SMO.Server]: make sure
the assembly containing this type is loaded.
At C:\Users\sortelyn\ ... \tools\sql_express_backup\backup.ps1:6 char:8
+ $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
Jede Antwort im Internet schreibt, dass ich die Assembly laden muss - sicher kann ich das aus der Fehlermeldung lesen :-) - die Frage ist:
Wie lade ich die Assembly und lasse das Skript funktionieren?
powershell
powershell-3.0
Baxter
quelle
quelle
This API is now obsolete.
hindert die Leute natürlich nicht daran, ihn zu verwenden.LoadWithPartialName
es veraltet ist, gelten die Gründe (wie in blogs.msdn.com/b/suzcook/archive/2003/05/30/57159.aspx beschrieben ) eindeutig nicht für eine interaktive Powershell-Sitzung. Ich schlage vor, Sie fügen einen Hinweis hinzu, dass die API für die interaktive Verwendung von Powershell in Ordnung ist.quelle
Out-Null
wenn Sie nicht möchten, dass der GAC Daten wiedergibt.Add-Type -Path [...]; if (!$?) { Add-Type -Path [...] } elseif [...]
.Die meisten Menschen wissen inzwischen, dass dies
System.Reflection.Assembly.LoadWithPartialName
veraltet ist, aber es stellt sich heraus, dassAdd-Type -AssemblyName Microsoft.VisualBasic
es sich nicht viel besser verhält alsLoadWithPartialName
:Was Microsoft sagt, dass Sie eigentlich tun sollen, ist ungefähr so:
Oder, wenn Sie den Weg kennen, so etwas:
Dieser lange Name für die Versammlung ist bekannt als starker Name bezeichnet , der sowohl für die Version als auch für die Assembly eindeutig ist und manchmal auch als vollständiger Name bezeichnet wird.
Dies lässt jedoch einige Fragen offen:
Wie bestimme ich den starken Namen dessen, was tatsächlich mit einem bestimmten Teilnamen auf mein System geladen wird?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Diese sollten auch funktionieren:
Wenn ich möchte, dass mein Skript immer eine bestimmte Version einer DLL verwendet, ich aber nicht sicher bin, wo sie installiert ist, wie kann ich den starken Namen der DLL ermitteln?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Oder:
Wie bestimme ich den DLL-Pfad, wenn ich den starken Namen kenne?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
Und in ähnlicher Weise, wenn ich den Typnamen meiner Verwendung kenne, woher weiß ich, von welcher Baugruppe sie stammt?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Wie sehe ich, welche Baugruppen verfügbar sind?
Ich schlage das GAC PowerShell-Modul vor .
Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
funktioniert ziemlich gut.Add-Type
anzeigen?Das ist etwas komplexer. Ich kann beschreiben, wie für jede Version von PowerShell mit einem .Net-Reflektor darauf zugegriffen werden kann (siehe das Update unten für PowerShell Core 6.0).
Stellen Sie zunächst fest, aus welcher Bibliothek Sie
Add-Type
stammen:Öffnen Sie die resultierende DLL mit Ihrem Reflektor. Ich habe ILSpy dafür verwendet, weil es FLOSS ist, aber jeder C # -Reflektor sollte funktionieren. Öffnen Sie diese Bibliothek und schauen Sie hinein
Microsoft.Powershell.Commands.Utility
. UnterMicrosoft.Powershell.Commands
sollte es seinAddTypeCommand
.In der Codeliste dafür gibt es eine private Klasse
InitializeStrongNameDictionary()
. Das listet das Wörterbuch auf, das die Kurznamen den starken Namen zuordnet. Es gibt fast 750 Einträge in der Bibliothek, die ich mir angesehen habe.Update: Jetzt, da PowerShell Core 6.0 Open Source ist. Für diese Version können Sie die obigen Schritte überspringen und den Code direkt online in ihrem GitHub-Repository anzeigen . Ich kann jedoch nicht garantieren, dass dieser Code mit einer anderen Version von PowerShell übereinstimmt.
quelle
Add-Type
oder verwendenLoadWithPartialName()
, aber Sie müssen sich bewusst sein, dass Ersteres nicht über Versionen hinweg 100% konsistent sein wird und Letzteres eine veraltete Methode ist. Mit anderen Worten, .Net möchte, dass Sie sich um die Version der Bibliothek kümmern, die Sie laden.Add-Type -Path
den zweiten genannten Code verwenden sollten oderAssembly.LoadFrom()
der Abhängigkeiten für Sie auflöst (und, soweit ich das beurteilen kann, welcheAdd-Type -Path
verwendet werden). Sie sollten nur dann verwenden,Assembly.LoadFile()
wenn Sie mehrere Assemblys laden müssen, die dieselbe Identität, aber unterschiedliche Pfade haben. Das ist eine seltsame Situation.Wenn Sie eine Assembly während der Dauer der PowerShell-Sitzung laden möchten, ohne sie zu sperren, verwenden Sie Folgendes :
Wo
$storageAssemblyPath
ist der Dateipfad Ihrer Assembly?Dies ist besonders nützlich, wenn Sie die Ressourcen in Ihrer Sitzung bereinigen müssen. Zum Beispiel in einem Bereitstellungsskript.
quelle
Hier sind einige Blog-Beiträge mit zahlreichen Beispielen zum Laden von Assemblys in PowerShell v1, v2 und v3.
Die Möglichkeiten umfassen:
v1.0 Laden von .NET-Assemblys in einer PowerShell-Sitzung
v2.0 Verwenden von CSharp-Code (C #) in PowerShell-Skripten 2.0
v3.0 Verwenden von .NET Framework-Assemblys in Windows PowerShell
quelle
Sie können die gesamte * .dll-Assembly mit laden
quelle
Keine der Antworten hat mir geholfen, daher veröffentliche ich die für mich funktionierende Lösung. Ich musste lediglich das SQLPS-Modul importieren. Dies wurde mir klar, als ich versehentlich den Befehl Restore-SqlDatabase ausführte und anfing zu arbeiten Die Assembly wurde in diesem Modul irgendwie referenziert.
Renn einfach:
Hinweis: Vielen Dank an Jason, dass er festgestellt hat, dass SQLPS veraltet ist
Führen Sie stattdessen Folgendes aus:
oder
quelle
sqlps
das zugunsten des Moduls veraltet istsqlserver
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
arbeitete für mich.quelle
Sie könnten verwenden
LoadWithPartialName
. Dies ist jedoch wie gesagt veraltet.Sie können in der Tat
Add-Type
mitmachen und zusätzlich zu den anderen Antworten, wenn Sie nicht den vollständigen Pfad der DLL-Datei angeben möchten, können Sie einfach Folgendes tun:Für mich gab dies einen Fehler zurück, da ich SQL Server nicht installiert habe (ich denke), aber mit der gleichen Idee konnte ich die Windows Forms-Assembly laden:
Den genauen Assemblernamen der jeweiligen Klasse finden Sie auf der MSDN-Site:
quelle
Stellen Sie sicher, dass die folgenden Funktionen der Reihe nach installiert sind
Möglicherweise müssen Sie auch laden
quelle
Fügen Sie die Baugruppenreferenzen oben hinzu.
quelle