Skip to content

Added samples to the API#40930

Open
craigloewen-msft wants to merge 1 commit into
masterfrom
user/crloewen/wslc-api-samples
Open

Added samples to the API#40930
craigloewen-msft wants to merge 1 commit into
masterfrom
user/crloewen/wslc-api-samples

Conversation

@craigloewen-msft

Copy link
Copy Markdown
Member

Added 4 basic samples for the WSLC API that will be referenced in the WSL docs.

Copilot AI review requested due to automatic review settings June 26, 2026 21:36
@craigloewen-msft craigloewen-msft requested a review from a team as a code owner June 26, 2026 21:36

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

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 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 .gitignore to 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.

Comment on lines +109 to +111
process.Start();
WaitForSingleObject(exitEvent.get(), 30000);

Comment on lines +137 to +138
WaitForSingleObject(g_exitEvent, 30000);
result = g_exitCode;
Comment on lines +112 to +115
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 OneBlue left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: session is IDisposable so we can use using here

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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());

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Error check for SetEvent(), createEvent() and WaitForSingleObject()

VhdRequirements = new VhdOptions(string.Empty, 10UL * 1024 * 1024 * 1024, VhdType.Dynamic),
};

session = new Session(sessionSettings);

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

using for IDisposable classes

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants