about_Windows_PowerShell_Compatibility

about_Windows_PowerShell_Compatibility

Windows PowerShell로 만든 기존 모듈을 PowerShell 7에서 그대로 쓰려면 어떻게 해야 하는지 궁금할 때가 있어요. 그럴 때 쓸 수 있는 게 Windows PowerShell 호환(Compatibility) 기능이에요. 모듈이 PowerShell Core와 호환된다고 표시돼 있지 않으면, 이 기능이 Windows PowerShell 5.1 프로세스를 백그라운드로 띄워서 그 모듈을 대신 불러와 줘요.

출처: about_Windows_PowerShell_Compatibility — Microsoft Learn

본문

간단한 설명

PowerShell 7의 Windows PowerShell 호환(Compatibility) 기능에 대해 설명해요.

자세한 설명

모듈 매니페스트가 그 모듈이 PowerShell Core와 호환된다고 표시하지 않는 경우, %windir%\system32\WindowsPowerShell\v1.0\Modules 폴더에 있는 모듈은 Windows PowerShell Compatibility 기능에 의해 백그라운드 Windows PowerShell 5.1 프로세스에서 로드돼요.

Compatibility 기능 사용하기

Windows PowerShell Compatibility 기능으로 첫 번째 모듈을 가져오면, PowerShell은 WinPSCompatSession이라는 원격 세션을 만들어요. 이 세션은 백그라운드 Windows PowerShell 5.1 프로세스에서 실행돼요. PowerShell은 Compatibility 기능이 첫 모듈을 가져올 때 이 프로세스를 만들고, 마지막 모듈이 제거되거나(Remove-Module 사용) PowerShell 프로세스가 종료될 때 이 프로세스를 닫아요.

WinPSCompatSession 세션에 로드된 모듈은 암시적 원격(implicit remoting)을 통해 사용되고 현재 PowerShell 세션에 반영돼요. 이건 PowerShell 작업(Jobs)에서 쓰는 것과 똑같은 전송 방식이에요.

모듈이 WinPSCompatSession 세션으로 가져와지면, implicit remoting은 사용자의 $Env:TEMP 디렉터리에 프록시 모듈을 만들고 이 프록시 모듈을 현재 PowerShell 세션으로 가져와요. 이 프록시 모듈 덕분에 PowerShell은 그 모듈이 Windows PowerShell Compatibility 기능으로 로드됐다는 걸 감지할 수 있어요.

세션이 만들어지고 나면, 역직렬화(deserialized)된 객체에서는 제대로 동작하지 않는 작업에 그 세션을 쓸 수 있어요. 파이프라인 전체가 Windows PowerShell에서 실행되고, 최종 결과만 돌려받아요. 예시를 볼게요.

$s = Get-PSSession -Name WinPSCompatSession
Invoke-Command -Session $s -ScriptBlock {
  "Running in Windows PowerShell version $($PSVersionTable.PSVersion)"
}

Compatibility 기능은 두 가지 방식으로 호출할 수 있어요.

  • 명시적으로: UseWindowsPowerShell 매개 변수를 사용해 모듈을 가져오는 방법
Import-Module -Name ScheduledTasks -UseWindowsPowerShell
  • 암시적으로: 모듈 이름이나 경로로 가져오거나, 명령 검색(command discovery)을 통한 자동 로드로 Windows PowerShell 모듈을 가져오는 방법
Import-Module -Name ServerManager
Get-AppLockerPolicy -Local

아직 로드돼 있지 않다면, Get-AppLockerPolicy를 실행할 때 AppLocker 모듈이 자동으로 로드돼요.

Windows PowerShell Compatibility는 PowerShell 구성 파일의 WindowsPowerShellCompatibilityModuleDenyList 설정에 나열된 모듈의 로드를 차단해요.

이 설정의 기본값은 다음과 같아요.

"WindowsPowerShellCompatibilityModuleDenyList":  [
   "PSScheduledJob","BestPractices","UpdateServices"
]

암시적 모듈 로드 관리하기

Windows PowerShell Compatibility 기능의 암시적 가져오기(implicit import) 동작을 끄려면, PowerShell 구성 파일에서 DisableImplicitWinCompat 설정을 사용해요. 이 설정은 powershell.config.json 파일에 추가할 수 있어요. 자세한 내용은 about_PowerShell_Config를 참고하세요.

이 예시는 Windows PowerShell Compatibility의 암시적 모듈 로드 기능을 끄는 구성 파일을 만드는 방법을 보여줘요.

$ConfigPath = "$PSHOME\DisableWinCompat.powershell.config.json"
$ConfigJSON = ConvertTo-Json -InputObject @{
  "DisableImplicitWinCompat" = $true
  "Microsoft.PowerShell:ExecutionPolicy" = "RemoteSigned"
}
$ConfigJSON | Out-File -Force $ConfigPath
pwsh -SettingsFile $ConfigPath

모듈 호환성에 대한 최신 정보는 PowerShell 7 module compatibility 목록을 참고하세요.

cmdlet 덮어쓰기(clobbering) 관리하기

Windows PowerShell Compatibility 기능은 호환 모드에서 모듈을 로드하기 위해 암시적 원격(implicit remoting)을 사용해요. 그 결과, 모듈이 내보내는 명령은 현재 PowerShell 7 세션에서 같은 이름의 명령보다 우선하게 돼요. PowerShell 7.0.0 릴리스에서는 여기에 PowerShell과 함께 제공되는 핵심 모듈도 포함됐어요.

PowerShell 7.1에서 동작이 바뀌어서, 다음 핵심 PowerShell 모듈들은 덮어써지지 않아요.

  • Microsoft.PowerShell.ConsoleHost
  • Microsoft.PowerShell.Diagnostics
  • Microsoft.PowerShell.Host
  • Microsoft.PowerShell.Management
  • Microsoft.PowerShell.Security
  • Microsoft.PowerShell.Utility
  • Microsoft.WSMan.Management

PowerShell 7.1은 호환 모드가 덮어쓰기에서 제외할 모듈을 더 추가할 수 있는 기능도 도입했어요.

PowerShell 구성 파일에 WindowsPowerShellCompatibilityNoClobberModuleList 설정을 추가할 수 있어요. 이 설정의 값은 쉼표로 구분된 모듈 이름 목록이에요. 이 설정의 기본값은 다음과 같아요.

"WindowsPowerShellCompatibilityNoClobberModuleList": [ ]

제한 사항(Limitations)

Windows PowerShell Compatibility 기능은:

  • Windows 컴퓨터에서 로컬로만 동작해요
  • Windows PowerShell 5.1이 필요해요
  • 직렬화(serialized)된 cmdlet 매개 변수와 반환 값을 대상으로 하지, 실시간(live) 객체를 대상으로 하지 않아요
  • Windows PowerShell 원격 세션으로 가져온 모든 모듈이 단일 runspace를 공유해요

임시 파일

Windows PowerShell Compatibility 기능은 Windows PowerShell 5.1 모듈을 PowerShell 7에서 사용할 수 있게 하기 위해 암시적 원격(implicit remoting)을 사용해요. Implicit remoting은 $Env:TEMP 디렉터리에 임시 파일을 만들어요. 각 프록시 모듈은 다음 명명 규칙을 따르는 별도 폴더에 저장돼요.

  • remoteIpMoProxy_<ModuleName>_<ModuleVersion>_localhost_<SessionGuid>.

세션에서 마지막 프록시 모듈을 제거하거나 세션을 닫으면, PowerShell은 임시 파일을 제거해요.

참고 자료

더 알아보기