sourcecode

PowerShell에서 어셈블리를 로드하는 방법

codebag 2023. 4. 8. 08:26
반응형

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에서는 cmdlet을 사용하는 것이 좋습니다.다음은 예를 제시하겠습니다.

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 는 다음과 같이 동작합니다.

[Add-Type]는 시스템 컨텍스트에서 요청을 구문 분석하는 대신 정적 내부 테이블을 보고 "부분 이름"을 "전체 이름"으로 변환합니다.

"부분 이름"이 테이블에 나타나지 않으면 스크립트가 실패합니다.

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

설치한 버전이 모두 테이블의 오래된 버전보다 최신 버전인 경우 스크립트는 실패합니다.

에는 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-TypeUses)

이게 좀 더 복잡해요.를 사용하여 모든 버전의 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의 다른 버전과 일치하는지 여부는 보증할 수 없습니다.

업데이트 2: Powershell 7+에서는 해시 테이블 조회가 더 이상 표시되지 않습니다.대신 LoadWithPartialName에 대한 코멘트가 "가능한 가장 가까운 근사치"라고 부르는 메서드를 사용합니다.기본적으로 다음과 같은 작업을 수행합니다.

loadedAssembly = Assembly.Load(new AssemblyName(assemblyName));

'사용자는 '사용할 수 있다'라고 하면 .Add-Type -AssemblyName Forms(일부러)「. Forms)」. 2004의 않습니다Windows 10 2004 hellhell v Powershell v7 . 0 . 3 。

# Returns an error
Add-Type -AssemblyName Forms

# Returns an error
[System.Reflection.Assembly]::Load([System.Reflection.AssemblyName]::new('Forms'))

# Works fine
Add-Type -AssemblyName System.Windows.Forms

# Works fine
[System.Reflection.Assembly]::Load([System.Reflection.AssemblyName]::new('System.Windows.Forms'))

그래서 댓글은 좀 미스터리해 보여요.

에 잘 Assembly.Load(AssemblyName)버전 또는 공개 키 토큰이 지정되지 않은 경우.LoadWithPartialName이(가) 여러 개 설치되어 있는 경우 잘못된 버전의 어셈블리를 로드하는 것과 동일한 문제가 많이 발생할 것으로 예상됩니다.

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 스크립트 2.0에서 CSharp(C#) 코드 사용
v3.0 사용.Windows PowerShell의 NET 프레임워크 어셈블리

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

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

어떤 답변도 도움이 되지 않았기 때문에 저에게 맞는 솔루션을 게시합니다.제가 해야 할 일은 SQLPS 모듈을 Import하는 것뿐입니다.Restore-SqlDatabase 명령을 실행하고 작업을 시작했을 때 우연히 이 사실을 깨달았습니다.즉, 어셈블리가 그 모듈에서 참조된 것입니다.

그냥 실행:

Import-module SQLPS

주의: Jason에게 SQLPS가 권장되지 않음을 알려 주셔서 감사합니다.

대신 다음을 실행합니다.

Import-Module SqlServer

또는

Install-Module SqlServer

[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.Smo")날 위해 일했어

사용할 수 있습니다.LoadWithPartialName하지만, 그것은 그들이 말한 것처럼 더 이상 사용되지 않는다.

넌 정말 따라갈 수 있어Add-Type다른 답변과 더불어 .timeout 파일의 전체 경로를 지정하지 않으면 다음 작업을 수행할 수 있습니다.

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

SQL Server가 설치되어 있지 않기 때문에 오류가 반환되었지만(아마도), Windows Forms 어셈블리를 로드할 수 있었습니다.

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

MSDN 사이트에서 특정 클래스에 속하는 정확한 어셈블리 이름을 확인할 수 있습니다.

특정 클래스에 속하는 어셈블리 이름 찾기 예제

다음의 기능이 순서대로 인스톨 되어 있는 것을 확인해 주세요.

  1. SQL Server용 Microsoft System CLR 유형
  2. Microsoft SQL Server 공유 관리 개체
  3. Microsoft Windows PowerShell 확장 기능

또한 로드해야 할 수도 있습니다.

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"

맨 위에 어셈블리 참조를 추가합니다.

#Load the required assemblies SMO and SmoExtended.
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SMO") | Out-Null
[System.Reflection.Assembly]::LoadWithPartialName("Microsoft.SqlServer.SmoExtended") | Out-Null

언급URL : https://stackoverflow.com/questions/12923074/how-to-load-assemblies-in-powershell

반응형