Оригинальный пост: https://cludeveloper.net/make-your-wsl-environment-programmable-72be5907d1ff
Я был очарован архитектурой WSL с момента своего дебюта. Он имеет элегантную и красивую архитектуру для достижения взаимодействия между Windows и Windows Linux. В конце концов, я погрузив в API WIN32 WIN32, модель реестра и внутренние тоже.
Но была только небольшая документация и образец API WSL API. Позже я понял, что Microsoft не намеревается использовать API WSL для общеобразователей, но разработчиков распространения WSL. Кроме того, инструмент CLI, известный как WSL.exe и Edro Launchers, является движущимися частями (поскольку каждый главный выпуск Windows 10 имеет разные функции, параметры командной строки). Таким образом, эти ситуации трудно автоматизировать среду WSL.
После многих испытаний и ошибок я разработал небольшой, но эффективный инструмент автоматизации под названием WSL SDK. Этот инструмент является внепроцессором COM-сервером, так что вы можете получить доступ к SDK с любым любым COM-поддерживаемым языком. В этой статье я хочу поделиться прохождением WSL SDK, чтобы преодолеть трудности использования официального Win32 WSL API.
Скрытые сокровища WSL
Если вы заинтересованы в WSL API, вы можете получить намек на API. Например, API WSLLAUNC возвращает код HResult. Интерфейс COM, связанный с WSL, находится в его внутренней композиции, известный как LXSSUSESSESSESSESSES, и этот API обернутся вокруг COM-объекта.
К сожалению, внутренний COM-объект полностью прятался от Microsoft, и похоже, что он был довольно предназначен. Я предполагаю, что существуют разумные решения об этом направлении. Тем не менее, его внутренний COM-объект также не имеет документации хорошо.
Недобротость WSL API
Из-за этого есть известное и попод-дизайнерское поведение о APIS WSL. Если вы вызываете API на WSL с P/Invoke через PowerShell, LinqPAD или любую среду с поддержкой COM-стержень, вы не можете достичь ни одного WSL API. Многие энтузиасты пробовали API, но нет удачи. И почему так? Эти среды, которые я упомянул, уже инициировал с помощью другого звонка CoinitializalizeSecurity. К сожалению, APIS WSL требует определенного параметра инициализации. И мотилизирует окрестность куда-то; Вы никогда не сможете снова вызвать моюнтилировать окрестность. Чтобы преодолеть этот вопрос неизбежно, я должен выбрать модель вне процесса. Требуются раскопки старых образцов, модель вне процесса делает громоздкие шаги для использования API. Вы должны проверить существование процесса. Вам придется определить, как общаться с внешним процессом, таким как труба, внутренние сетевые или любые маршалированные протоколы. Более того, этот подход делает его трудно расширить и поддерживать вызовы и функциональные возможности API.
Я застрял в этот момент так долго. Но благодаря старому проекту названо All-In-One Code Framework, разработанная Microsoft, я нашел красивое решение. да. Модель вне процесса COM-сервера! Таким образом, я адаптировал образец кода Out-Process COM-сервера, и он работает как очарование.
Под капотом
Когда клиентское приложение запрашивает объект службы WSL SDK через COM API, Windows автоматически запускает исполняемый файл для получения соответствующего ссылки на объект. Затем оберните его прокси-интерфейсом, и клиентское приложение извлекает эту ссылку. Для лучшего понимания, пожалуйста, посмотрите на картинку ниже.
Добственно, исполняемый файл WSL SDK призывает Coinitializeapi с помощью правильного параметра для связи с APIS WSL. Затем запустите насос сообщений, чтобы обрабатывать внешние запросы RPC и любые запросы, связанные с графическим интерфейсом Windows. Когда ссылка на объект запрашивается, его ссылочный счет увеличится или уменьшится. Тогда количество достигает нуля; Исполняемый процесс отключен. И опять же, еще один запрос прибыл, один и тот же раунд произойдет снова до регистрации информации о компании из реестра.
Таким образом, WSL SDK определяет модель COM Security между требованием к использованию приложения и WSL. И управление процессом жизненного цикла обрабатывается инфраструктурой операционной системы и механизмом ссылочного подсчета. Каждый клиент WSL SDK не должен заботиться о каких-либо деталях. Они запрашивают интерфейс WSL SDK как обычно, и все происходит хорошо.
Сравнение прямого p/вызывает на API WSL и с использованием WSL SDK
Я покажу простую демонстрацию.
Код пример PowerShell выглядит как ниже. Я выдержен образец кода из выпуска GitHub Whife 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 ссылается на C-функцию из WSLAPI.DLL. Казалось бы, это имеет смысл и должно хорошо работать. Но код возвращает ноль, не отражает текущий статус.
Однако 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
По сути, оба кодексе зависит от функции WSLISDistributionregistered, но PowerShell уже вызывает CoinitializalizeSecurity, которая не соответствует требованиям для APIS WSL. Первый пример не будет работать из-за этого.
Демо: петербоксинг WSL EDRO
Я покажу другого, более сложный пример сценария. Ниже приведен код автоматически загружают альпийское изображение корневой файловой системы 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 SDKS здесь: https://github.com/wslhub/wsl-sdk-com/tree/main/sample Отказ
Будущая дорожная карта
Я недавно создал активный трубопровод GitHub благодаря https://github.com/marketplace/4se/setup-wsl Плагин и решение команды GitHub, чтобы включить компонент WSL в их рабочей нагрузке сервера Windows.
Из-за этого я мог бы создать непрерывную интеграцию для WSL SDK, что делает более уверенные релизы. ( https://github.com/wslhub/wsl-sdk-com/rus/workflows/wsl-sdk-com-build.yml ) Эта работа является значительным достижением дорожной карты WSL SDK.
Кроме того, мой список ведра содержит эти цели.
- Без регистрации COM-сервера (если возможно)
- ARM64 Нативная поддержка
- Принятие WSL SDK к другому моему предыдущему проекту (WSL Manager)
- Различные языковые обертки (C #, Python, Go-lang, PowerShell или любой COM поддерживает языки)
Если вы заинтересованы в проекте WSL SDK, пожалуйста, приходите и внесите свой вклад в GitHub Repo. ( https://github.com/wslhub/wsl-sdk-com )
Оригинал: «https://dev.to/rkttu/make-your-wsl-environment-programmable-fi5»