| 1 | # End-to-End Example |
| 2 | |
| 3 | The example below shows one full lifecycle matching the C API example: |
| 4 | |
| 5 | 1. Check prerequisites |
| 6 | 2. Print SDK version |
| 7 | 3. Create a session (4 CPUs, 4 GB RAM) |
| 8 | 4. Pull alpine:latest |
| 9 | 5. Configure an init process (`/bin/echo "Hello from WSL Container!"`) |
| 10 | 6. Create and start the container |
| 11 | 7. Wait for the init process to exit |
| 12 | 8. Print exit code |
| 13 | 9. Stop and delete the container |
| 14 | 10. Terminate the session |
| 15 | |
| 16 | ```cpp |
| 17 | #include <cstdio> |
| 18 | #include <string> |
| 19 | #include <chrono> |
| 20 | #include <winrt/Microsoft.WSL.Containers.h> |
| 21 | #include <winrt/Windows.Foundation.h> |
| 22 | #include <winrt/Windows.Foundation.Collections.h> |
| 23 | |
| 24 | using namespace winrt; |
| 25 | using namespace winrt::Microsoft::WSL::Containers; |
| 26 | using namespace winrt::Windows::Foundation; |
| 27 | using namespace winrt::Windows::Foundation::Collections; |
| 28 | using namespace std::chrono_literals; |
| 29 | |
| 30 | int main() |
| 31 | { |
| 32 | init_apartment(); |
| 33 | |
| 34 | // 0. Check prerequisites |
| 35 | auto missing = WslcService::GetMissingComponents(); |
| 36 | if (missing != static_cast<Component>(0)) |
| 37 | { |
| 38 | printf("WSL components are missing. Run: wsl --install\n"); |
| 39 | return 1; |
| 40 | } |
| 41 | |
| 42 | auto ver = WslcService::GetVersion(); |
| 43 | printf("WSL version: %u.%u.%u\n", ver.Major(), ver.Minor(), ver.Revision()); |
| 44 | |
| 45 | // 1. Create a session |
| 46 | SessionSettings sessionSettings{ L"MyApp", L"C:\\WslcData" }; |
| 47 | sessionSettings.CpuCount(4); |
| 48 | sessionSettings.MemorySizeInMB(4096); |
| 49 | |
| 50 | Session session{ sessionSettings }; |
| 51 | session.Start(); |
| 52 | |
| 53 | // 2. Pull an image |
| 54 | PullImageOptions pullOpts{ L"docker.io/library/alpine:latest" }; |
| 55 | auto pullOp = session.PullImageAsync(pullOpts); |
| 56 | co_await pullOp; |
| 57 | |
| 58 | // 3. Configure an init process |
| 59 | ProcessSettings initProcSettings; |
| 60 | initProcSettings.OutputMode(ProcessOutputMode::Event); |
| 61 | auto argv = single_threaded_vector<hstring>(); |
| 62 | argv.Append(L"/bin/echo"); |
| 63 | argv.Append(L"Hello from WSL Container!"); |
| 64 | initProcSettings.CommandLine(argv); |
| 65 | |
| 66 | // 4. Configure and create a container |
| 67 | ContainerSettings containerSettings{ L"alpine:latest" }; |
| 68 | containerSettings.Name(L"hello-container"); |
| 69 | containerSettings.InitProcess(initProcSettings); |
| 70 | |
| 71 | auto container = session.CreateContainer(containerSettings); |
| 72 | |
| 73 | // 5. Subscribe to init process events before starting |
| 74 | auto initProcess = container.InitProcess(); |
| 75 | auto exitedEvent = handle{ CreateEvent(nullptr, TRUE, FALSE, nullptr) }; |
| 76 | int32_t initExitCode = -1; |
| 77 | |
| 78 | initProcess.OutputReceived([](auto const& data) |
| 79 | { |
| 80 | std::string text(data.begin(), data.end()); |
| 81 | printf("%s", text.c_str()); |
| 82 | }); |
| 83 | initProcess.Exited([&](int32_t exitCode) |
| 84 | { |
| 85 | initExitCode = exitCode; |
| 86 | SetEvent(exitedEvent.get()); |
| 87 | }); |
| 88 | |
| 89 | // 6. Start the container |
| 90 | container.Start(); |
| 91 | |
| 92 | // 7. Wait for the init process to exit (30-second timeout) |
| 93 | WaitForSingleObject(exitedEvent.get(), 30000); |
| 94 | printf("Process exited with code: %d\n", initExitCode); |
| 95 | |
| 96 | // 8. Clean up |
| 97 | if (container.State() == ContainerState::Running) |
| 98 | { |
| 99 | container.Stop(Signal::SIGTERM, 10s); |
| 100 | } |
| 101 | container.Delete(DeleteContainerOption::None); |
| 102 | session.Terminate(); |
| 103 | |
| 104 | return 0; |
| 105 | } |
| 106 | ``` |