Le code PowerShell suivant
#Get a server object which corresponds to the default instance
$srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server
... rest of the script ...
Donne le message d'erreur suivant:
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
Chaque réponse sur Internet indique que je dois charger l'Assemblée - bien sûr, je peux le lire dans le message d'erreur :-) - la question est la suivante:
Comment charger l'assembly et faire en sorte que le script fonctionne?
LoadWithPartialName
est obsolète. La solution recommandée pour PowerShell V3 consiste à utiliser la cmdlet Add-Type
par exemple:
Add-Type -Path 'C:\Program Files\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll'
Il existe plusieurs versions différentes et vous pouvez choisir une version particulière. :-)
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
La plupart des gens savent maintenant que System.Reflection.Assembly.LoadWithPartialName
est obsolète, mais il s'avère que Add-Type -AssemblyName Microsoft.VisualBasic
ne se comporte pas beaucoup mieux que LoadWithPartialName
:
Plutôt que d'essayer d'analyser votre demande dans le contexte de votre système, [Add-Type] examine une table interne statique pour traduire le "nom partiel" en un "nom complet".
Si votre "nom partiel" n'apparaît pas dans leur tableau, votre script échouera.
Si plusieurs versions de Assembly sont installées sur votre ordinateur, aucun algorithme intelligent ne permet de choisir entre elles. Vous obtiendrez celui qui apparaît dans leur tableau, probablement le plus ancien et obsolète.
Si les versions que vous avez installées sont toutes plus récentes que la version obsolète du tableau, votre script échouera.
Add-Type n'a pas d'analyseur intelligent de "noms partiels" comme
.LoadWithPartialNames
.
Qu'est-ce que Microsoft dit que vous êtes réellement supposé faire quelque chose comme ceci:
Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a'
Ou, si vous connaissez le chemin, quelque chose comme ceci:
Add-Type -Path 'C:\WINDOWS\Microsoft.Net\Assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll'
Ce nom long donné à l’Assemblée est appelé nom fort , qui est à la fois unique à la version et à l’Assemblée, et parfois aussi appelé nom complet.
Mais cela laisse quelques questions sans réponse:
Comment déterminer le nom fort de ce qui est réellement chargé sur mon système avec un nom partiel donné?
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location;
[System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;
Ceux-ci devraient également fonctionner:
Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Si je veux que mon script utilise toujours une version spécifique d'un fichier .dll mais que je ne puisse pas savoir avec certitude où il est installé, comment puis-je déterminer le nom fort du fichier .dll?
[System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;
Ou:
Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
Si je connais le nom fort, comment puis-je déterminer le chemin d'accès .dll?
[Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;
Et, dans le même ordre d'idées, si je connais le nom du type que j'utilise, comment puis-je savoir de quelle assemblée il s'agit?
[Reflection.Assembly]::GetAssembly([Type]).Location
[Reflection.Assembly]::GetAssembly([Type]).FullName
Comment voir quels assemblages sont disponibles?
Je suggère le module GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName
fonctionne plutôt bien.
Add-Type
?C'est un peu plus complexe. Je peux décrire comment y accéder pour n’importe quelle version de PowerShell avec un réflecteur .Net (voir la mise à jour ci-dessous pour PowerShell Core 6.0).
D'abord, déterminez de quelle bibliothèque Add-Type
provient:
Get-Command -Name Add-Type | Select-Object -Property DLL
Ouvrez le DLL résultant avec votre réflecteur. J'ai utilisé ILSpy pour cela car c'est FLOSS, mais tout réflecteur C # devrait fonctionner. Ouvrez cette bibliothèque et cherchez dans Microsoft.Powershell.Commands.Utility
. Sous Microsoft.Powershell.Commands
, il devrait y avoir AddTypeCommand
.
Dans la liste de code pour cela, il y a une classe privée, InitializeStrongNameDictionary()
. Cela répertorie le dictionnaire qui associe les noms abrégés aux noms forts. Il y a près de 750 entrées dans la bibliothèque que j'ai consultées.
Mise à jour: Maintenant que PowerShell Core 6.0 est open source. Pour cette version, vous pouvez ignorer les étapes ci-dessus et voir le code directement en ligne dans leur référentiel GitHub . Je ne peux cependant pas garantir que ce code correspond à une autre version de PowerShell.
Si vous souhaitez charger un assembly sans le verrouiller pendant la durée de la session PowerShell, utilisez ceci:
$bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath)
[System.Reflection.Assembly]::Load($bytes)
Où $storageAssemblyPath
est le chemin de fichier de votre assemblage.
Ceci est particulièrement utile si vous devez nettoyer les ressources de votre session. Par exemple, dans un script de déploiement.
Voici quelques articles de blog avec de nombreux exemples de méthodes de chargement d'assemblages dans PowerShell v1, v2 et v3.
Les moyens incluent:
v1.0 Comment charger des assemblages .NET dans une session PowerShell
v2.0 tilisation du code CSharp (C #) dans les scripts PowerShell 2.
v3.0 tilisation d'assemblages .NET Framework dans Windows PowerShell
Vous pouvez charger l’ensemble * .dll Assembly avec
$Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll");
Aucune des réponses ne m’a aidé. Je publie donc la solution qui a fonctionné pour moi. Tout ce que j’avais à faire est d’importer le module SQLPS. l'Assemblée a été référencée dans ce module d'une manière ou d'une autre.
Il suffit de courir:
Import-module SQLPS
Remarque: Merci à Jason d'avoir noté que SQLPS est obsolète.
à la place, lancez:
Import-Module SqlServer
ou
Install-Module SqlServer
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")
a travaillé pour moi.
Vous pouvez utiliser LoadWithPartialName
. Cependant, cela est déconseillé comme ils l'ont dit.
Vous pouvez en effet aller avec Add-Type
, et en plus des autres réponses, si vous ne voulez pas spécifier le chemin complet du fichier .dll, vous pouvez simplement faire:
Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO"
Cela m'a renvoyé une erreur, car SQL Server n'est pas installé (je suppose), mais avec cette même idée, j'ai pu charger l'assemblage de Windows Forms:
Add-Type -AssemblyName "System.Windows.Forms"
Vous pouvez trouver le nom d'assembly précis appartenant à la classe en question sur le site MSDN:
Ajoutez les références d'assemblage en haut.
[System.Reflection.Assembly] :: LoadWithPartialName ("Microsoft.SqlServer.SMO") | Out-Null [System.Reflection.Assembly] :: LoadWithPartialName ("Microsoft.SqlServer.SmoExtended") | Out-Null
Assurez-vous que les fonctionnalités ci-dessous sont installées dans l'ordre.
Types 1-Microsoft System CLR pour SQL Server
2-Objets de gestion partagée Microsoft SQL Server
3-Microsoft Windows PowerShell Extensions
Aussi, vous devrez peut-être charger
Add-Type -Path "C:\Programmes\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.Smo.dll"
Add-Type -Path "C:\Programmes\Microsoft SQL Server\110\SDK\Assemblies\Microsoft.SqlServer.SqlWmiManagement.dll"