Something went wrong. Try again.
Open a URI in the user's chosen application from Zig: the desktop portal on Linux, ShellExecuteExW on Windows, Launch Services on macOS.
Something went wrong. Try again.
2.9 kB · 82 lines
Zig
at main
1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283// SPDX-FileCopyrightText: © 2026 Jeffrey C. Ollie <jeff@ocjtech.us>// SPDX-License-Identifier: MIT
//! Opening a URI with `ShellExecuteExW`, the shell's own "open" verb://! https://learn.microsoft.com/en-us/windows/win32/api/shellapi/nf-shellapi-shellexecuteexw//!//! `SEE_MASK_NOASYNC` makes the call finish its work before returning, which//! a program about to exit needs, and `SEE_MASK_FLAG_NO_UI` keeps the shell//! from showing its own error dialogs, so that failures come back as errors.//! Some protocol handlers need COM initialized on the calling thread; the//! library leaves that to the application.
const std = @import("std");const Io = std.Io;const Allocator = std.mem.Allocator;const windows = std.os.windows;
const root = @import("root.zig");const Error = root.Error;const Options = root.Options;const Outcome = root.Outcome;
const SEE_MASK_NOASYNC: windows.ULONG = 0x00000100;const SEE_MASK_FLAG_NO_UI: windows.ULONG = 0x00000400;const SW_SHOWNORMAL: windows.INT = 1;
const SHELLEXECUTEINFOW = extern struct { cbSize: windows.DWORD = @sizeOf(SHELLEXECUTEINFOW), fMask: windows.ULONG = 0, hwnd: ?windows.HWND = null, lpVerb: ?windows.LPCWSTR = null, lpFile: ?windows.LPCWSTR = null, lpParameters: ?windows.LPCWSTR = null, lpDirectory: ?windows.LPCWSTR = null, nShow: windows.INT = 0, hInstApp: ?windows.HINSTANCE = null, lpIDList: ?windows.LPVOID = null, lpClass: ?windows.LPCWSTR = null, hkeyClass: ?windows.HKEY = null, dwHotKey: windows.DWORD = 0, hIconOrMonitor: ?windows.HANDLE = null, hProcess: ?windows.HANDLE = null,};
extern "shell32" fn ShellExecuteExW(info: *SHELLEXECUTEINFOW) callconv(.winapi) windows.BOOL;
pub fn open( io: Io, gpa: Allocator, environ: std.process.Environ, uri: []const u8, is_file: bool, options: Options,) Error!Outcome { _ = io; _ = environ; _ = is_file; _ = options;
const wide = std.unicode.utf8ToUtf16LeAllocZ(gpa, uri) catch |err| return switch (err) { error.OutOfMemory => error.OutOfMemory, error.InvalidUtf8 => error.InvalidUri, }; defer gpa.free(wide);
var info: SHELLEXECUTEINFOW = .{ .fMask = SEE_MASK_NOASYNC | SEE_MASK_FLAG_NO_UI, .lpVerb = std.unicode.utf8ToUtf16LeStringLiteral("open"), .lpFile = wide.ptr, .nShow = SW_SHOWNORMAL, }; if (ShellExecuteExW(&info).toBool()) return .opened; return switch (windows.GetLastError()) { // The user said no to an elevation prompt the handler needed. .CANCELLED => .cancelled, .FILE_NOT_FOUND, .PATH_NOT_FOUND => error.FileNotFound, .NO_ASSOCIATION => error.NoHandler, .ACCESS_DENIED => error.AccessDenied, .NOT_ENOUGH_MEMORY, .OUTOFMEMORY => error.OutOfMemory, else => error.Unexpected, };}