Cómo cargar ensamblajes en PowerShell?

El siguiente código de PowerShell

#Get a server object which corresponds to the default instance $srv = New-Object -TypeName Microsoft.SqlServer.Management.SMO.Server ... rest of the script ... 

Da el siguiente mensaje de error:

 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 

Cada respuesta en Internet escribe que tengo que cargar el ensamblado, y estoy seguro de que puedo leerlo desde el mensaje de error 🙂 – la pregunta es:

¿Cómo carga el ensamblaje y hace que el script funcione?

    LoadWithPartialName ha quedado en desuso. La solución recomendada para PowerShell V3 es usar el cmdlet Add-Type por ejemplo:

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

    Existen múltiples versiones diferentes y es posible que desee elegir una versión en particular. 🙂

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

    La mayoría de la gente sabe ahora que System.Reflection.Assembly.LoadWithPartialName está en desuso, pero resulta que Add-Type -AssemblyName Microsoft.VisualBasic no se comporta mucho mejor que LoadWithPartialName :

    En lugar de intentar analizar su solicitud en el contexto de su sistema, [Agregar-Tipo] mira una tabla interna estática para traducir el “nombre parcial” a un “nombre completo”.

    Si su “nombre parcial” no aparece en su tabla, su script fallará.

    Si tiene múltiples versiones del ensamblaje instaladas en su computadora, no existe un algoritmo inteligente para elegir entre ellas. Obtendrá el que aparezca en su mesa, probablemente el más antiguo y anticuado.

    Si las versiones que ha instalado son todas más nuevas que la obsoleta de la tabla, su secuencia de comandos fallará.

    Add-Type no tiene un analizador inteligente de “nombres parciales” como .LoadWithPartialNames .

    Lo que Microsoft dice que se supone que debes hacer es algo como esto:

     Add-Type -AssemblyName 'Microsoft.VisualBasic, Version=10.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' 

    O, si conoce el camino, algo como esto:

     Add-Type -Path 'C:\WINDOWS\Microsoft.Net\assembly\GAC_MSIL\Microsoft.VisualBasic\v4.0_10.0.0.0__b03f5f7f11d50a3a\Microsoft.VisualBasic.dll' 

    Ese nombre largo dado para el ensamblado se conoce como el nombre fuerte , que es único para la versión y el conjunto, y también se conoce como el nombre completo.

    Pero esto deja un par de preguntas sin respuesta:

    1. ¿Cómo determino el nombre fuerte de lo que se está cargando realmente en mi sistema con un nombre parcial dado?

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

    2. Si quiero que mi script siempre use una versión específica de .dll pero no puedo estar seguro de dónde está instalado, ¿cómo puedo determinar cuál es el nombre fuerte de .dll?

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

    3. Si conozco el nombre fuerte, ¿cómo determino el camino .dll?

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

    4. Y, en una línea similar, si conozco el nombre de tipo de lo que estoy usando, ¿cómo sé de qué ensamblaje proviene?

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

    5. ¿Cómo veo qué ensamblajes están disponibles?

    Sugiero el módulo GAC PowerShell . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName funciona bastante bien.

    1. ¿Cómo puedo ver la lista que usa Add-Type ?

    Esto es un poco más complejo. No veo ninguna lista documentada en línea, pero puedo describir cómo acceder a ella con un reflector .Net.

    En primer lugar, averigüe de qué biblioteca viene Add-Type :

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

    Abra la DLL resultante con su reflector. He usado ILSpy para esto porque es FLOSS, pero cualquier reflector C # debería funcionar. Abra esa biblioteca y busque en Microsoft.Powershell.Commands.Utility . En Microsoft.Powershell.Commands , debe haber AddTypeCommand . En la lista de códigos para eso, hay una clase privada, InitializeStrongNameDictionary() . Eso enumera el diccionario que asigna los nombres cortos a los nombres fuertes. Hay casi 750 entradas en la biblioteca que he visto.

    Aquí hay algunas publicaciones en el blog con numerosos ejemplos de formas de cargar ensamblajes en PowerShell v1, v2 y v3.

    Las formas incluyen:

    • dinámicamente desde un archivo fuente
    • dinámicamente desde un ensamblado
    • usando otros tipos de código, es decir, F #

    v1.0 Cómo cargar ensamblajes .NET en una sesión de PowerShell
    v2.0 Uso del código CSharp (C #) en los scripts de PowerShell 2.0
    v3.0 Uso de ensamblados de .NET Framework en Windows PowerShell

    Si desea cargar un ensamblaje sin bloquearlo durante la sesión de PowerShell , use esto:

     $bytes = [System.IO.File]::ReadAllBytes($storageAssemblyPath) [System.Reflection.Assembly]::Load($bytes) 

    Donde $storageAssemblyPath es la $storageAssemblyPath archivo de su ensamblaje.

    Esto es especialmente útil si necesita limpiar los recursos dentro de su sesión. Por ejemplo, en un script de despliegue.

    Puede cargar el conjunto completo * .dll con

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

    [System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo") funcionó para mí.

    Ninguna de las respuestas me ayudó, así que estoy publicando la solución que funcionó para mí, todo lo que tuve que hacer es importar el módulo SQLPS, me di cuenta de esto cuando accidentalmente ejecuté el comando Restore-SqlDatabase y comencé a trabajar, lo que significa que el conjunto fue referenciado en ese módulo de alguna manera.

    Solo corre:

     Import-module SQLPS 

    Nota: Gracias Jason por notar que SQLPS está en desuso

    en lugar de ejecutar:

     Import-Module SqlServer 

    o

     Install-Module SqlServer 

    Puede usar LoadWithPartialName . Sin embargo, eso está en desuso ya que dijeron.

    De hecho, puede seguir con Add-Type , y además de las otras respuestas, si no desea especificar la ruta completa del archivo .dll, simplemente puede hacer:

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

    Para mí esto devolvió un error, porque no tengo SQL Server instalado (supongo), sin embargo, con esta misma idea, pude cargar el ensamblado de Windows Forms:

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

    Puede encontrar el nombre de ensamblado preciso que pertenece a la clase particular en el sitio de MSDN:

    Ejemplo de averiguar el nombre del ensamblado perteneciente a una clase particular

    Agregue las referencias de ensamblaje en la parte superior.

    Cargue los ensamblados necesarios SMO y SmoExtended.

    [System.Reflection.Assembly] :: LoadWithPartialName (“Microsoft.SqlServer.SMO”) | Out-Null [System.Reflection.Assembly] :: LoadWithPartialName (“Microsoft.SqlServer.SmoExtended”) | Out-Null

    Asegúrate de tener las siguientes funciones instaladas en orden

    1-Microsoft System CLR Types para SQL Server

    Objetos de administración compartida de 2-Microsoft SQL Server

    Extensiones de 3-Microsoft Windows PowerShell

    También es posible que tengas que cargar

    Add-Type -Path “C: \ Archivos de progtwig \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.Smo.dll”

    Add-Type -Path “C: \ Archivos de progtwig \ Microsoft SQL Server \ 110 \ SDK \ Assemblies \ Microsoft.SqlServer.SqlWmiManagement.dll”