Skip to content

Conversation

jakepetroules
Copy link
Collaborator

Background: on Unix platforms, running a binary with a missing dependent shared library produces a human-readable error message on stderr containing the name of the missing library. On Windows, the loader may show a graphical dialog box with missing the DLL names when a process is run from a UI context, but in most cases the process will simply exit with STATUS_DLL_NOT_FOUND and no other information. This can make debugging missing dependent shared libraries very difficult.

The program in this PR uses Loader Snaps and documented SPI to replicate the Unix experience on Windows, printing nice human readable messages like This application has failed to start because \(missingDLL) was not found. to stderr. It's implemented as a launcher (think ccache), where its arguments are the command line that would be originally executed.

Mostly putting this up to illustrate the technique, not immediately planning to land this. Not sure if this is the right place for it either, or if Swift is even a good choice of implementation language (due to the fact that the launcher itself will have DLL dependences of its own on the Swift runtime).

It also has to be a launcher binary and not a set of helper APIs, since some of the APIs called in here really only make sense in the context of a main executable and not in library code.

Thanks to https://github.com/TimMisiak/LoaderLog/blob/main/LoaderLog.cpp for some learnings behind this.

@jakepetroules jakepetroules force-pushed the eng/PR-windows-launcher branch from 9544fc6 to f9d3e7e Compare July 16, 2025 23:54
@jakepetroules jakepetroules force-pushed the eng/PR-windows-launcher branch from f9d3e7e to 9f14f77 Compare August 7, 2025 03:35
do {
var commandLine = String(decodingCString: GetCommandLineW(), as: UTF16.self)

// FIXME: This could probably be more robust
Copy link
Collaborator Author

Choose a reason for hiding this comment

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

I think I'll eliminate the command line parsing here and just re-invoke the exact command line string, requiring clients to invoke this process with the lpApplicationName parameter to CreateProcessW set to the path to the swblauncher so that this doesn't need to do any parsing.

@jakepetroules
Copy link
Collaborator Author

I will probably try to land this once @compnerd lands the static linking support for the Swift runtime on Windows.

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.

1 participant