Added samples to the API#40930
Conversation
There was a problem hiding this comment.
Pull request overview
This PR adds a set of standalone samples under doc/samples/ demonstrating how to use the WSL Container API (Microsoft.WSL.Containers) from C, C++/WinRT, and C#—intended to be referenced from WSL documentation.
Changes:
- Adds three runnable “pull/run” samples: C (HelloWorld), C++/WinRT (Neofetch), and C# (Nextcloud).
- Adds a C# sample that demonstrates building and running a custom container image via the SDK’s
<WslcImage>MSBuild integration. - Adds a samples index README plus a samples-local
.gitignoreto support keeping these hand-authored project files in-repo.
Reviewed changes
Copilot reviewed 21 out of 21 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| doc/samples/WSLC-NextCloud/WSLCNextCloud.csproj | New .NET 8 console project referencing Microsoft.WSL.Containers. |
| doc/samples/WSLC-NextCloud/README.md | Build/run/storage instructions for the Nextcloud sample. |
| doc/samples/WSLC-NextCloud/Program.cs | C# sample that pulls nextcloud and runs it with port + volume mapping. |
| doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj.filters | VS filters file for the Neofetch sample project. |
| doc/samples/WSLC-Neofetch/WSLCNeofetch.vcxproj | C++/WinRT sample project wiring NuGet packages + build settings. |
| doc/samples/WSLC-Neofetch/WSLCNeofetch.sln | VS solution for building the Neofetch sample. |
| doc/samples/WSLC-Neofetch/README.md | Build/run instructions for the Neofetch sample. |
| doc/samples/WSLC-Neofetch/packages.config | NuGet dependencies for the C++/WinRT Neofetch sample. |
| doc/samples/WSLC-Neofetch/neofetch.cpp | C++/WinRT sample that runs neofetch in a container and streams output. |
| doc/samples/WSLC-HelloWorld/WSLCHelloWorld.vcxproj | C sample project wiring the WSLC SDK package. |
| doc/samples/WSLC-HelloWorld/WSLCHelloWorld.sln | VS solution for building the HelloWorld C sample. |
| doc/samples/WSLC-HelloWorld/README.md | Build/run instructions for the HelloWorld sample. |
| doc/samples/WSLC-HelloWorld/packages.config | NuGet dependency for the HelloWorld sample. |
| doc/samples/WSLC-HelloWorld/helloworld.c | Minimal C sample using the flat wslcsdk.h API to run echo. |
| doc/samples/WSLC-CustomContainer/WSLCCustomContainer.csproj | C# project that auto-builds a custom image via <WslcImage>. |
| doc/samples/WSLC-CustomContainer/README.md | Explains the <WslcImage> auto-build flow and how to run the sample. |
| doc/samples/WSLC-CustomContainer/Program.cs | C# sample that loads a locally-built image tar and runs a Python tool inside. |
| doc/samples/WSLC-CustomContainer/Container/qr.py | Python tool that prints an ASCII/Unicode QR code in the container. |
| doc/samples/WSLC-CustomContainer/Container/Containerfile | Containerfile that installs qrcode and copies qr.py. |
| doc/samples/README.md | Top-level index describing all four samples. |
| doc/samples/.gitignore | Samples-local ignore rules + re-includes for project files normally ignored at repo root. |
| process.Start(); | ||
| WaitForSingleObject(exitEvent.get(), 30000); | ||
|
|
| WaitForSingleObject(g_exitEvent, 30000); | ||
| result = g_exitCode; |
| catch (Exception ex) | ||
| { | ||
| Console.Error.WriteLine($"[wslc] Error: {ex.Message}"); | ||
| } |
| process?.Dispose(); | ||
| if (container is not null) | ||
| { | ||
| try { container.Stop(Signal.SIGTERM, TimeSpan.FromSeconds(10)); } catch { /* best effort */ } |
| } | ||
| if (session is not null) | ||
| { | ||
| try { session.Terminate(); } catch { /* best effort */ } |
OneBlue
left a comment
There was a problem hiding this comment.
Change looks good overall, couple minor comments
I also recommend add a pipeline to validate that all of these actually build (we can use a GH pipeline to make this easy, and only trigger it when doc/samples is edited
| VhdRequirements = new VhdOptions(string.Empty, 4UL * 1024 * 1024 * 1024, VhdType.Dynamic), | ||
| }; | ||
|
|
||
| session = new Session(sessionSettings); |
There was a problem hiding this comment.
nit: session is IDisposable so we can use using here
There was a problem hiding this comment.
(Same for containers, processes, and such)
| HANDLE output = (ioHandle == WSLC_PROCESS_IO_HANDLE_STDOUT) ? GetStdHandle(STD_OUTPUT_HANDLE) : GetStdHandle(STD_ERROR_HANDLE); | ||
| DWORD written = 0; | ||
| (void)context; | ||
| WriteFile(output, data, dataSize, &written, NULL); |
There was a problem hiding this comment.
Given that this is text, I recommend using fprintf to write on stderr / stdout (we can use %.*s to write non-null terminated strings)
| { | ||
| (void)context; | ||
| g_exitCode = exitCode; | ||
| SetEvent(g_exitEvent); |
There was a problem hiding this comment.
We should check the exit code of SetEvent here
| PCSTR initArgv[2] = { "/bin/sleep", "60" }; | ||
| PCSTR echoArgv[2] = { "/bin/echo", "Hello, World from a WSL container!" }; | ||
|
|
||
| CoInitializeEx(NULL, COINIT_MULTITHREADED); |
There was a problem hiding this comment.
We should check the error code are here as well
| hr = WslcCreateContainerProcess(container, &execProcess, &process, &error); | ||
| if (FAILED(hr)) { PrintError(L"Run echo", hr, error); goto cleanup; } | ||
|
|
||
| WaitForSingleObject(g_exitEvent, 30000); |
There was a problem hiding this comment.
We should display an error if WaitForSingleObject times out here
| void WriteToConsole(DWORD stdHandle, array_view<uint8_t const> data) | ||
| { | ||
| DWORD written = 0; | ||
| WriteFile(GetStdHandle(stdHandle), data.data(), static_cast<DWORD>(data.size()), &written, nullptr); |
There was a problem hiding this comment.
I also recommend using fprintf here
| process.ErrorReceived([](array_view<uint8_t const> data) { WriteToConsole(STD_ERROR_HANDLE, data); }); | ||
| process.Exited([&](int32_t code) { | ||
| exitCode = code; | ||
| SetEvent(exitEvent.get()); |
There was a problem hiding this comment.
Error check for SetEvent(), createEvent() and WaitForSingleObject()
| VhdRequirements = new VhdOptions(string.Empty, 10UL * 1024 * 1024 * 1024, VhdType.Dynamic), | ||
| }; | ||
|
|
||
| session = new Session(sessionSettings); |
There was a problem hiding this comment.
using for IDisposable classes
Added 4 basic samples for the WSLC API that will be referenced in the WSL docs.