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은 임시 파일을 제거해요.