Comment charger des assemblages dans PowerShell?

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 écrit que je dois charger l’assemblage – bien sûr, je peux le lire à partir du message d’erreur 🙂 – la question est:

Comment chargez-vous l’assemblage et faites fonctionner le script?

    LoadWithPartialName est obsolète. La solution recommandée pour PowerShell V3 consiste à utiliser l’applet de commande 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’parsingr votre requête dans le contexte de votre système, [Add-Type] examine une table statique interne 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 l’assembly sont installées sur votre ordinateur, il n’y a pas d’algorithme intelligent à choisir entre elles. Vous allez obtenir celui qui apparaît dans leur tableau, probablement le plus ancien et le plus ancien.

    Si les versions que vous avez installées sont toutes plus récentes que celles obsolètes de la table, votre script échouera.

    Add-Type n’a pas d’parsingur intelligent de “noms partiels” comme .LoadWithPartialNames .

    Ce que Microsoft est censé faire est 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' 

    Le nom long donné à l’assembly s’appelle le nom fort , qui est à la fois unique à la version et à l’assembly. Il est également parfois appelé nom complet.

    Mais cela laisse quelques questions sans réponse:

    1. Comment déterminer le nom fort de ce qui est chargé sur mon système avec un nom partiel donné?

      [System.Reflection.Assembly]::LoadWithPartialName($TypeName).Location; [System.Reflection.Assembly]::LoadWithPartialName($TypeName).FullName;

    2. Si je veux que mon script utilise toujours une version spécifique d’un fichier .dll mais que je ne suis pas certain de son emplacement, comment puis-je déterminer le nom fort du fichier .dll?

      [System.Reflection.AssemblyName]::GetAssemblyName($Path).FullName;

    3. Si je connais le nom fort, comment puis-je déterminer le chemin d’access .dll?

      [Reflection.Assembly]::Load('Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a').Location;

    4. Et, dans la même veine, si je connais le nom de type de ce que j’utilise, comment puis-je savoir de quel assemblage il provient?

      [Reflection.Assembly]::GetAssembly([Type]).Location [Reflection.Assembly]::GetAssembly([Type]).FullName

    5. Comment voir quels assemblages sont disponibles?

    Je suggère le module GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName fonctionne assez bien.

    1. Comment puis-je voir la liste utilisée par Add-Type ?

    C’est un peu plus complexe. Je ne vois aucune liste documentée en ligne, mais je peux décrire comment y accéder avec un réflecteur .Net.

    Tout d’abord, déterminer quelle bibliothèque Add-Type provient de:

     Get-Command -Name Add-Type | Select-Object -Property DLL 

    Ouvrez la DLL résultante avec votre réflecteur. J’ai utilisé ILSpy pour cela parce que c’est FLOSS, mais tout réflecteur C # devrait fonctionner. Ouvrez cette bibliothèque et recherchez Microsoft.Powershell.Commands.Utility . Sous Microsoft.Powershell.Commands , il devrait y avoir AddTypeCommand . Dans la liste de codes pour cela, il existe une classe privée, InitializeStrongNameDictionary() . Cela répertorie le dictionnaire qui associe les noms abrégés aux noms forts. Il y a presque 750 entrées dans la bibliothèque que j’ai examinées.

    Voici quelques articles de blog contenant de nombreux exemples de méthodes permettant de charger des assemblys dans PowerShell v1, v2 et v3.

    Les moyens incluent:

    • dynamicment depuis un fichier source
    • dynamicment d’un assemblage
    • en utilisant d’autres types de code, par exemple F #

    v1.0 Comment charger des assemblys .NET dans une session PowerShell
    v2.0 Utilisation du code CSharp (C #) dans les scripts PowerShell 2.0
    v3.0 Utilisation d’ assemblys .NET Framework dans Windows 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) 

    $storageAssemblyPath est le chemin du fichier de votre assembly.

    Ceci est particulièrement utile si vous devez nettoyer les ressources de votre session. Par exemple, dans un script de déploiement.

    Vous pouvez charger l’ensemble complet * .dll avec

     $Assembly = [System.Reflection.Assembly]::LoadFrom("C:\folder\file.dll"); 

    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") fonctionnait pour moi.

    Aucune des réponses ne m’a aidé, alors je poste la solution qui a fonctionné pour moi, tout ce que j’avais à faire était d’importer le module SQLPS, j’ai réalisé cela par accident quand j’ai exécuté la commande Restore-SqlDatabase et commencé à travailler. l’assemblage a été référencé dans ce module d’une manière ou d’une autre.

    Il suffit de courir:

     Import-module SQLPS 

    Note: Merci Jason d’avoir noté que SQLPS est obsolète

    au lieu de cela courir:

     Import-Module SqlServer 

    ou

     Install-Module SqlServer 

    Vous pouvez utiliser LoadWithPartialName . Cependant, cela est déconseillé, comme ils l’ont dit.

    Vous pouvez en effet suivre Add-Type , et en plus des autres réponses, si vous ne souhaitez pas spécifier le chemin complet du fichier .dll, vous pouvez simplement faire:

     Add-Type -AssemblyName "Microsoft.SqlServer.Management.SMO" 

    Pour moi, cela a renvoyé une erreur, car je n’ai pas installé SQL Server (je suppose), cependant, avec cette même idée, j’ai pu charger l’assembly Windows Forms:

     Add-Type -AssemblyName "System.Windows.Forms" 

    Vous pouvez trouver le nom d’assembly précis appartenant à la classe particulière sur le site MSDN:

    Exemple de recherche de nom d'assembly appartenant à une classe particulière

    Ajoutez les références d’assemblage en haut.

    Chargez les assemblages requirejs SMO et SmoExtended.

    [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

    1-Types de système CLR Microsoft pour SQL Server

    Objets de gestion partagée Microsoft SQL Server 2

    3-Extensions Microsoft Windows PowerShell

    Aussi, vous devrez peut-être charger

    Add-Type -Path “C: \ Program Files \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.Smo.dll”

    Add-Type -Path “C: \ Program Files \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.SqlWmiManagement.dll”