WSL 환경 프로그래밍 가능

19495 단어 windowsdevopswsl2linux
원본: https://cloudeveloper.net/make-your-wsl-environment-programmable-72be5907d1ff
WSL 아키텍처가 처음 선보인 이래로 나는 그것에 푹 빠졌다.Windows와 Linux 세계 간의 상호 운용성을 위한 우아하고 멋진 아키텍처를 갖추고 있습니다.마지막으로 WSL Win32 API, 레지스트리 모델 및 내부 응용 프로그램에 대해 자세히 살펴보았습니다.
그러나 WSL API 문서와 예제는 아주 적습니다.나중에 나는 마이크로소프트가 WSL API를 일반적인 용도로 사용하지 않고 WSL 릴리스 개발자에게 사용할 계획이라는 것을 깨달았다.또한 CLI 도구를 WSL이라고 합니다.exe 및 distro 이니시에이터가 위젯을 이동하고 있습니다. (Windows 10 주요 버전마다 기능과 명령줄 옵션이 다르기 때문입니다.)따라서 WSL 환경을 자동화하기가 어렵습니다.
여러 번의 시도와 오류를 거쳐 나는 작지만 효과적인 자동화 도구인 WSL SDK를 개발했다.이 도구는 프로세스 외 스타일의 COM 서버이기 때문에 모든 COM이 지원하는 언어로 SDK에 접근할 수 있습니다.
이 문서에서 WSL SDK의 연습을 공유하여 공식 Win32 WSL API를 사용하는 어려움을 극복하고자 합니다.

WSL의 보물


WSL API에 관심이 있는 경우 해당 API에 대한 프롬프트가 표시될 수 있습니다.예를 들어, API WslLaunch가 HRESULT 코드를 반환합니다.WSL과 관련된 COM 인터페이스는 내부 구성 요소인 LXSUSerSession에 위치하고 이 API는 COM 대상을 둘러싸고 펼쳐집니다.
안타깝게도 마이크로소프트는 내부 COM 대상을 완전히 숨겼는데, 보기에 그것은 의도적인 것 같다.나는 이 방향에 대해 합리적인 결정이 있다고 생각한다.그러나 내부 COM 대상에 좋은 문서가 없습니다.

WSL API의 무정함


그렇기 때문에 WSL API는 모두가 알고 있는 디자인 동작을 가지고 있다.PowerShell, LINQPad 또는 COM 지원 환경에서 P/Invoke를 사용하여 WSL API를 호출하면 WSL API에 액세스할 수 없습니다.많은 광신자들이 이 API들을 시도했지만 운이 없었다.
왜 이러지?내가 언급한 환경들은 이미 다른 CoInitialize Security 호출을 통해 시작되었습니다.죄송합니다. WSL API에는 특정 초기화 매개 변수가 필요합니다.안전 시스템을 공동으로 초기화하여 어딘가에서 호출하기;더 이상 CoInitialize Security를 호출할 수 없습니다.이 문제를 극복하기 위해서 나는 불가피하게 과정 외 모델을 선택해야 한다.
낡은 견본을 발굴하다.
그러나 프로세스 외 모델 때문에 API를 사용하는 절차가 매우 번거롭다.너는 반드시 이 과정의 존재를 검사해야 한다.파이프, 내부 네트워크, 봉송 프로토콜 등 외부 프로세스와 통신하는 방법을 정의해야 합니다.또한 이 방법으로는 API 호출 및 기능을 확장하고 유지하기 어렵습니다.
나는 이 점에서 매우 오랫동안 버텼다.하지만 마이크로소프트가 개발한 All-In-ONe Code Framework라는 오래된 프로젝트에 감사드립니다. 멋진 해결 방안을 찾았습니다.그래.프로세스 외 COM 서버 모델!그래서, 나는 프로세스 COM 서버 코드에서 이 예시를 개편했는데, 그것의 효과는 매우 좋다.

엔진 덮개


클라이언트 응용 프로그램이 COM API를 통해 WSL SDK 서비스 객체를 요청하면 Windows는 적절한 객체 참조를 얻기 위해 실행 파일을 자동으로 시작합니다.그리고 프록시 인터페이스로 포장하면 클라이언트 프로그램이 이 인용을 검색합니다.더 잘 이해하기 위해 아래 그림을 보십시오.

공정하게 말하면 WSL SDK 실행 파일은 WSL API와 통신하기 위해 정확한 매개 변수를 사용하여CoInitialize API를 호출합니다.그런 다음 외부 RPC 요청과 Windows GUI와 관련된 모든 요청을 처리하기 위해 메시지 펌프를 시작합니다.요청 대상의 인용을 요청할 때 인용 수가 증가하거나 감소합니다.그리고 계수가 0에 도달하기;실행 가능한 프로세스가 닫힙니다.다시 한 번, 다른 요청이 도착했을 때, 같은 라운드는 등록표에서 COM 정보를 취소할 때까지 다시 발생할 것이다.
따라서 WSL SDK는 COM 보안 모델과 응용 프로그램의 보안 모델, WSL의 수요를 분리한다.운영 체제의 기초 구조와 인용 계수 메커니즘으로 처리되는 절차의 생명주기 관리.모든 WSL SDK 클라이언트는 세부 사항에 신경 쓸 필요가 없습니다.그들은 평소와 같이 WSL SDK 인터페이스를 요청했고 모든 것이 순조롭게 진행되었다.

direct P/Invoke와 WSL API 비교 및 WSL SDK 사용


나는 간단한 시범을 보여줄 것이다.

PowerShell 예제 코드는 다음과 같습니다.GitHub 문제에서 예시 코드를 발췌했는데 WSL API는 PowerShell·문제 #4058·microsoft/WSL(GitHub.com)에서 작용하지 않는다.
# Excerpted from https://github.com/microsoft/WSL/issues/4058
Write-Host 'Calling WslIsDistributionRegistered directrly (Ubuntu-20.04):'
Add-Type -TypeDefinition @'
using System.Runtime.InteropServices;
public class wslutil
{
 [DllImport("wslapi.dll", CharSet = CharSet.Unicode)]
 public static extern uint WslIsDistributionRegistered([In, MarshalAs(UnmanagedType.LPWStr)] string distributionName);
public static void Main(string[] args)
 {
  System.Console.WriteLine(WslIsDistributionRegistered("Ubuntu-20.04"));
 }
}
'@
[wslutil]::Main({})
Write-Host
PowerShell 코드는 WSLAPI의 C 함수를 참조합니다.dll.겉으로 보기에 이것은 일리가 있는 것으로 매우 효과적일 것이다.그러나 코드가 0으로 되돌아와 현재 상태를 반영하지 않습니다.
그러나 WSL SDK는 올바른 값을 반환합니다.
Write-Host 'Calling WSL SDK API (Ubuntu-20.04):'
$DistroName = 'Ubuntu-20.04'
$obj = New-Object -ComObject 'WslSdk.WslService'
$Result = $obj.IsDistroRegistered($DistroName)
Write-Host "$Result"
Write-Host
본질적으로 이 두 코드는 모두 WslIs Distribution Registered 함수에 의존하지만 PowerShell에서CoInitialize Security를 호출했습니다. 이것은 WSL API의 요구에 부합되지 않습니다.그래서 첫 번째 예는 작용하지 않는다.

데모: 샌드박스 WSL 릴리스


나는 또 다른 더 복잡한 예시 각본을 보여줄 것이다.다음 코드는 Alpine Linux 루트 파일 시스템 이미지를 공식 미러에서 자동으로 다운로드합니다.그런 다음 릴리스에 VI 개선 편집기를 추가합니다.
$ErrorActionPreference = "Stop"
$obj = New-Object -ComObject 'WslSdk.WslService'
Write-Output 'A WslSdk.WslService object is created.'
Pause

# Get installed distro list
Write-Output 'Currently installed WSL distro list: '
$list = $obj.GetDistroList()
Write-Output $list
Pause

# Generate Random Name
$RandomName = $obj.GenerateRandomName($false)
Write-Output "We will use $RandomName as a new distro"

# Download Alpine Linux RootFS Image
Write-Output 'Downloading alpine linux root file system image'
$TargetUrl = 'https://dl-cdn.alpinelinux.org/alpine/v3.14/releases/x86_64/alpine-minirootfs-3.14.0-x86_64.tar.gz'
$RootfsFilePath = "$env:TEMP\alpine.tar.gz"
$InstallPath = "C:\Distro\$RandomName"
Invoke-WebRequest -UseBasicParsing -Uri $TargetUrl -OutFile $RootfsFilePath
Pause

# Register Distro
Write-Output "Distro installation begins"
Write-Output " - Distro Name: $RandomName"
Write-Output " - Source RootFS File Path: $RootfsFilePath"
Write-Output " - Destination Install Path: $InstallPath"
$obj.RegisterDistro($RandomName, $RootfsFilePath, $InstallPath)
Pause

# Distro Register Check
$Result = $obj.IsDistroRegistered($RandomName)
Write-Output "Distro Name $RandomName Installed: $Result"
Pause

# Metadata Query
Write-Output "Querying $RandomName metadata..."
$o = $obj.QueryDistroInfo($RandomName)
Write-Output " - Distro ID: $($o.DistroId())"
Write-Output " - Distro Name: $($o.DistroName())"
Write-Output " - Environment Variabls: $($o.DefaultEnvironmentVariables())"
Write-Output " - Default Uid: $($o.DefaultUid())"
Write-Output " - Flags: $($o.DistroFlags())"
Write-Output " - Win32 Interop Enabled: $($o.EnableInterop())"
Write-Output " - Drive Mounting Enabled: $($o.EnableDriveMounting())"
Write-Output " - NT Path Append Enabled: $($o.AppendNtPath())"
Write-Output " - WSL Version: $($o.WslVersion())"
Pause

# Run WSL command
Write-Output "Installing vim..."
$res = $obj.RunWslCommand($o.DistroName(), "apk add vim")
Write-Output $res
Pause

# Revealing launcher executable
Write-Output "Revealing launcher executable file"
Start-Process -FilePath "$env:windir\explorer.exe" -ArgumentList "/select,$InstallPath\$RandomName.exe"
Pause

# Unregister Distro
Write-Output "Unregister $RandomName distro..."
$obj.UnregisterDistro($RandomName)
Pause

# Get installed distro list
Write-Output 'Currently installed WSL distro list: '
$list = $obj.GetDistroList()
Write-Output $list
Pause
$obj = $null
이것은 WSL을 위한 기본 루트 파일 시스템 이미지가 아닙니다.WSL은 알려진 대로 정확한 프로세서 아키텍처에 맞는 Linux 루트 파일 시스템 이미지를 가져올 수 있습니다.

WSL SDK는 PowerShell 환경에서도 동적 배포 등록 및 작업을 처리할 수 있습니다.
다만 Microsoft Excel에서도 WSL 환경과 상호 작용할 수 있습니다.


WSL SDK의 다양한 예제 코드에 액세스할 수 있습니다.https://github.com/wslhub/wsl-sdk-com/tree/main/sample.

향후 로드맵


https://github.com/marketplace/actions/setup-wsl 플러그인과 GitHub팀은 Windows 서버 작업 부하에서 WSL 구성 요소를 사용하기로 결정했기 때문에 최근에 GitHub 조작 파이프를 만들었습니다.
그렇기 때문에 WSL SDK에 지속적인 통합을 만들어 발표를 더욱 자신 있게 할 수 있습니다.https://github.com/wslhub/wsl-sdk-com/actions/workflows/wsl-sdk-com-build.yml 이 작업은 WSL SDK 로드맵의 큰 성과입니다.
이 밖에도 내 버킷리스트에는 이런 목표가 담겨 있다.
  • 무등록 COM 서버(가능한 경우)
  • ARM64 네이티브 지원
  • 이전 내 프로젝트에 WSL SDK 적용(WSL 관리자)
  • 다양한 언어 팩(C#, Python, Go lang, PowerShell 또는 COM 지원 언어)
  • WSL SDK 프로젝트에 관심이 있으면 GitHub repo에 참여하십시오.( https://github.com/wslhub/wsl-sdk-com )

    좋은 웹페이지 즐겨찾기