[powershell] PowerShell에서 어셈블리를로드하는 방법은 무엇입니까?

다음 PowerShell 코드

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

다음과 같은 오류 메시지가 나타납니다.

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

인터넷의 모든 대답은 어셈블리를로드해야한다고 기록합니다. 오류 메시지 :-)에서 읽을 수 있는지 확인하십시오. 질문은 다음과 같습니다.

어셈블리를 어떻게로드하고 스크립트를 작동하게합니까?



답변

LoadWithPartialName더 이상 사용되지 않습니다. PowerShell V3에 권장되는 솔루션은 다음과 같은 Add-Typecmdlet 을 사용하는 것입니다 .

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

여러 버전이 있으며 특정 버전을 선택할 수 있습니다. 🙂


답변

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


답변

대부분의 사람들은 지금까지 System.Reflection.Assembly.LoadWithPartialName더 이상 사용 Add-Type -AssemblyName Microsoft.VisualBasic 되지 않는다고LoadWithPartialName 알고 있지만 다음 보다 훨씬 잘 작동하지 않는 것으로 나타났습니다 .

[Add-Type]은 시스템 컨텍스트에서 요청을 구문 분석하지 않고 “부분 이름”을 “전체 이름”으로 변환하기 위해 정적 내부 테이블을 찾습니다.

“부분 이름”이 표에 나타나지 않으면 스크립트가 실패합니다.

컴퓨터에 여러 버전의 어셈블리가 설치되어 있으면 선택할 수있는 지능형 알고리즘이 없습니다. 테이블에 나타날 것, 아마도 오래되고 오래된 것 중 하나를 얻을 것입니다.

설치 한 버전이 표에서 더 이상 사용되지 않는 버전 인 경우 스크립트가 실패합니다.

추가 유형에는와 같은 “부분 이름”에 대한 지능적인 구문 분석기가 없습니다
.LoadWithPartialNames.

Microsoft가 실제로 해야 할 일은 다음과 같습니다.

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

또는 경로를 알고 있다면 다음과 같이하십시오.

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

어셈블리에 제공된 긴 이름은 강력한 이름 으로 알려져 있으며 버전과 어셈블리에 고유하며 때로는 전체 이름으로도 알려져 있습니다.

그러나 이것은 몇 가지 질문에 답하지 않습니다.

  1. 주어진 부분 이름으로 시스템에 실제로로드되는 내용의 강력한 이름을 어떻게 확인합니까?

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

이것들은 또한 작동해야합니다 :

Add-Type -AssemblyName $TypeName -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
  1. 스크립트가 항상 특정 버전의 .dll을 사용하기를 원하지만 설치 위치를 확인할 수없는 경우 .dll에서 강력한 이름이 무엇인지 어떻게 알 수 있습니까?

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

또는:

Add-Type $Path -PassThru | Select-Object -ExpandProperty Assembly | Select-Object -ExpandProperty FullName -Unique
  1. 강력한 이름을 알고 있으면 .dll 경로를 어떻게 확인합니까?

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

  2. 그리고 비슷한 맥락에서 내가 사용하는 유형의 이름을 알고 있다면 그것이 어떤 어셈블리에서 나오는지 어떻게 알 수 있습니까?

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

  3. 어떤 어셈블리를 사용할 수 있는지 어떻게 알 수 있습니까?

GAC PowerShell 모듈을 제안합니다 . Get-GacAssembly -Name 'Microsoft.SqlServer.Smo*' | Select Name, Version, FullName꽤 잘 작동합니다.

  1. Add-Type사용 하는 목록을 어떻게 볼 수 있습니까?

이것은 조금 더 복잡합니다. .Net 리플렉터를 사용하여 모든 버전의 PowerShell에서 액세스하는 방법을 설명 할 수 있습니다 (PowerShell Core 6.0의 경우 아래 업데이트 참조).

먼저, 어떤 라이브러리 Add-Type가 제공 되는지 확인하십시오 .

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

리플렉터로 결과 DLL을 엽니 다. FLOSS이기 때문에 ILSpy 를 사용 했지만 C # 리플렉터가 작동해야합니다. 해당 라이브러리를 열고에서 찾아보십시오 Microsoft.Powershell.Commands.Utility. 아래 Microsoft.Powershell.Commands에 있어야합니다 AddTypeCommand.

이를위한 코드 목록에는 개인 클래스가 InitializeStrongNameDictionary()있습니다. 여기에는 짧은 이름을 강력한 이름으로 매핑하는 사전이 나열됩니다. 내가 본 라이브러리에는 거의 750 개의 항목이 있습니다.

업데이트 : 이제 PowerShell Core 6.0이 오픈 소스입니다. 해당 버전의 경우 위의 단계를 건너 뛰고 GitHub 리포지토리에서 직접 온라인으로 코드를 볼 수 있습니다 . 그러나 해당 코드가 다른 버전의 PowerShell과 일치한다고 보장 할 수는 없습니다.


답변

PowerShell 세션 동안 어셈블리 를 잠그지 않고 어셈블리를로드 하려면 다음을 사용하십시오.

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

$storageAssemblyPath어셈블리의 파일 경로는 어디에 있습니까 ?

세션 내 리소스를 정리해야하는 경우 특히 유용합니다. 예를 들어 배포 스크립트에서.


답변

다음은 PowerShell v1, v2 및 v3에서 어셈블리를로드하는 방법에 대한 많은 예제가 포함 된 블로그 게시물입니다.

방법은 다음과 같습니다.

  • 소스 파일에서 동적으로
  • 어셈블리에서 동적으로
  • 다른 코드 타입을 사용하는 것, 즉 F #

v1.0 PowerShell 세션에서 .NET 어셈블리를로드하는 방법
v2.0 PowerShell 스크립트에서 CSharp (C #) 코드를 사용하는 방법 2.0
v3.0 Windows PowerShell에서 .NET Framework 어셈블리 사용


답변

전체 * .dll 어셈블리를로드 할 수 있습니다.

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


답변

어떤 대답도 도움이되지 않아 저에게 도움이되는 솔루션을 게시하고 있습니다 .SQLPS 모듈을 가져 오는 것만으로 실수로 Restore-SqlDatabase 명령을 실행하고 작업을 시작했을 때 이것을 깨달았습니다. 그 모듈에서 어셈블리가 어떻게 든 참조되었습니다.

그냥 실행 :

Import-module SQLPS

참고 : SQLPS가 더 이상 사용되지 않는다는 점에 대해 Jason에게 감사합니다.

대신 다음을 실행하십시오.

Import-Module SqlServer

또는

Install-Module SqlServer