-
Notifications
You must be signed in to change notification settings - Fork 1.6k
Initial Support for WSLC Commands #14171
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: feature/wsl-for-apps
Are you sure you want to change the base?
Conversation
| options.CpuCount = 4; | ||
| options.MemoryMb = 2048; | ||
| options.BootTimeoutMs = 30 * 1000; | ||
| options.StoragePath = dataFolder.c_str(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Dangling pointer to local; a suggestion on a pattern to fix it: https://github.com/microsoft/WSL/compare/user/amelbawa/init...JohnMcPMS:amir-suggest?expand=1
… into user/amelbawa/init
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR introduces an initial command/subcommand framework for the wslc CLI and refactors prior monolithic logic into command + service/model components to support image, container, and shell operations.
Changes:
- Replaced the old top-level verb handling with an
ICommand-based dispatcher (image,container,shell) and per-subcommand implementations. - Added services/models for sessions, images, containers, console attach/stdio wiring, and table output.
- Updated build wiring for the new
wslcsources/headers and tweaked the rootvswheredetection logic.
Reviewed changes
Copilot reviewed 28 out of 28 changed files in this pull request and generated 35 comments.
Show a summary per file
| File | Description |
|---|---|
| src/windows/wslc/main.cpp | Routes CLI execution through a new RootCommand dispatcher. |
| src/windows/wslc/ICommand.h / .cpp | Adds a command interface + shared parsing/help utilities. |
| src/windows/wslc/ShellCommand.h / .cpp | Implements wslc shell list/attach. |
| src/windows/wslc/ShellService.h / .cpp | Adds session listing and attach logic for shell sessions. |
| src/windows/wslc/ImageCommand.h / .cpp | Implements wslc image list/pull. |
| src/windows/wslc/ImageService.h / .cpp | Adds image list/pull operations via WSLA APIs. |
| src/windows/wslc/ImageModel.h | Defines image info model + serialization. |
| src/windows/wslc/ContainerCommand.h / .cpp | Implements wslc container subcommands (run/create/start/stop/kill/delete/list/exec/inspect). |
| src/windows/wslc/ContainerService.h / .cpp | Adds container lifecycle/exec/inspect operations. |
| src/windows/wslc/ContainerModel.h | Defines container option/result/info models + serialization. |
| src/windows/wslc/ConsoleService.h / .cpp | Centralizes stdio fd building and console attach/relay logic. |
| src/windows/wslc/ConsoleModel.h | Defines console attach options. |
| src/windows/wslc/SessionService.h / .cpp | Adds a session creation helper. |
| src/windows/wslc/SessionModel.h / .cpp | Defines session wrapper and default session settings. |
| src/windows/wslc/Utils.h / .cpp | Moves pull/progress logic and terminal cursor RAII helper. |
| src/windows/wslc/TableOutput.h | Adds a simple table printer for CLI output. |
| src/windows/wslc/CMakeLists.txt | Adds new command/service/model sources and headers to the build. |
| localization/strings/en-US/Resources.resw | Updates MessageWslcUsage (but currently mismatched with new command layout). |
| CMakeLists.txt | Modifies Visual Studio discovery behavior via vswhere. |
| #define CMD_ARG_REQUIRED(arg, msg) if (arg.empty()) { wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } | ||
| #define CMD_ARG_ARRAY_REQUIRED(argArray, msg) if (argArray.empty()) { wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
CMD_ARG_REQUIRED/CMD_ARG_ARRAY_REQUIRED depend on a wslutil namespace alias being defined in every .cpp that uses them, which is brittle and easy to break. Prefer referencing wsl::windows::common::wslutil::PrintMessage directly in the macros (or move these helpers into a .cpp).
| #define CMD_ARG_REQUIRED(arg, msg) if (arg.empty()) { wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } | |
| #define CMD_ARG_ARRAY_REQUIRED(argArray, msg) if (argArray.empty()) { wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } | |
| #define CMD_ARG_REQUIRED(arg, msg) if (arg.empty()) { wsl::windows::common::wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } | |
| #define CMD_ARG_ARRAY_REQUIRED(argArray, msg) if (argArray.empty()) { wsl::windows::common::wslutil::PrintMessage(msg, stderr); PrintHelp(); return E_INVALIDARG; } |
| private: | ||
| bool m_all; | ||
| std::string m_format; | ||
| bool m_quiet; | ||
| }; |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_all/m_quiet are not initialized; if the flags are omitted, the values can be indeterminate. Default-initialize them to false (e.g., bool m_all{}; bool m_quiet{};).
| wsl::windows::common::security::ConfigureForCOMImpersonation(sessionManager.get()); | ||
|
|
||
| wil::unique_cotaskmem_array_ptr<WSLA_SESSION_INFORMATION> sessions; | ||
| (sessionManager->ListSessions(&sessions, sessions.size_address<ULONG>())); |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ListSessions's HRESULT is ignored here. This should be THROW_IF_FAILED(...) (or otherwise handled), otherwise failures will be silently ignored and sessions may be in an unexpected state.
| (sessionManager->ListSessions(&sessions, sessions.size_address<ULONG>())); | |
| THROW_IF_FAILED(sessionManager->ListSessions(&sessions, sessions.size_address<ULONG>())); |
| CMD_IF_HELP_PRINT_HELP(); | ||
| auto containersToKill = Arguments(); | ||
| auto session = m_sessionService.CreateSession(); | ||
| wslc::services::ContainerService containerService; |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If --all is not set and no container IDs are provided, this command becomes a no-op and returns success. Please validate that at least one ID is provided when m_all is false and return a non-zero error code otherwise.
|
|
||
| protected: | ||
| virtual int ExecuteInternal(std::wstring_view commandLine, int parserOffset = 0) = 0; | ||
| bool m_help; |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
m_help is not initialized. Default-initialize it (e.g., bool m_help{};) so CMD_IF_HELP_PRINT_HELP() cannot read an indeterminate value if parsing fails or is bypassed.
| bool m_help; | |
| bool m_help{}; |
| wslc::services::SessionService sessionService; | ||
| auto session = sessionService.CreateSession(); | ||
|
|
||
| wslc::services::ImageService imageService; | ||
| Callback callback; | ||
| imageService.Pull(session, Image, &callback); |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PullImpl creates a new session (sessionService.CreateSession()) instead of using the Session parameter that callers pass in. This breaks the expectation that pulls happen within the caller-provided session; please use the passed-in session (or remove the parameter and update call sites).
| wslc::services::SessionService sessionService; | |
| auto session = sessionService.CreateSession(); | |
| wslc::services::ImageService imageService; | |
| Callback callback; | |
| imageService.Pull(session, Image, &callback); | |
| wslc::services::ImageService imageService; | |
| Callback callback; | |
| imageService.Pull(Session, Image, &callback); |
| SessionInformation info; | ||
| info.CreatorPid = current.CreatorPid; | ||
| info.SessionId = current.SessionId; | ||
| info.DisplayName = current.DisplayName; |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
current.DisplayName can be null (the previous implementation explicitly handled null). Assigning a null wchar_t* into std::wstring is undefined behavior. Please guard against null and use an empty string when it is not provided.
| info.DisplayName = current.DisplayName; | |
| info.DisplayName = current.DisplayName ? current.DisplayName : L""; |
| options.MemoryMb = 2048; | ||
| options.BootTimeoutMs = 30 * 1000; | ||
| options.StoragePath = dataFolder.c_str(); | ||
| options.MaximumStorageSizeMb = 10000; // 10GB. | ||
| options.NetworkingMode = WSLANetworkingModeNAT; |
Copilot
AI
Feb 6, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
options.StoragePath is set from dataFolder.c_str(), but dataFolder is a local variable and its storage is freed when Default() returns, leaving a dangling pointer in the returned settings. The settings object needs to own the backing string (e.g., keep a std::wstring buffer inside SessionOptions).
Summary of the Pull Request
🙌 Demo
🦞 Full implementation
Run
--helpfor each command and subcommand for the full list of supported options.PR Checklist
Detailed Description of the Pull Request / Additional comments
Validation Steps Performed