BCUninstaller/Bulk-Crap-Uninstaller · error · IOException

Process failed to start.

Error message

Process failed to start.

What it means

Thrown as IOException when ProcessTools.SeparateArgsFromCommand(uninstallerCommand).ToProcessStartInfo().Start() returns null, meaning the NSIS uninstaller process could not be launched or attached. The library treats a null Start() result as a hard failure because without a live process handle the entire extraction/attach flow cannot proceed. It is the first guard in UninstallNsisQuietly, fired before any UI automation begins.

Source

Thrown at source/UninstallerAutomatizer/Automation/AutomatedUninstallManager.cs:108

                HideAutomatizedWindowsChanged?.Invoke(null, EventArgs.Empty);
            }
        }

        /// <summary>
        ///     Automate uninstallation of an NSIS uninstaller.
        /// </summary>
        /// <param name="uninstallerCommand">Command line used to launch the NSIS uninstaller. (Usually path to uninstall.exe.)</param>
        /// <param name="statusCallback">Information about the process is relayed here</param>
        public static void UninstallNsisQuietly(string uninstallerCommand, Action<string> statusCallback)
        {
            Process pr = null;
            Application app = null;
            try
            {

                pr = ProcessTools.SeparateArgsFromCommand(uninstallerCommand).ToProcessStartInfo().Start();
                if (pr == null)
                    throw new IOException(Localization.Message_Automation_ProcessFailedToStart);

                // NSIS uninstallers are first extracted by the executable to a temporary directory, and then ran from there.
                // Wait for the extracting exe to close and grab the child process that it started.
                statusCallback(Localization.Message_Automation_WaitingForNsisExtraction);
                pr.WaitForExit();

                // Attempt to get the extracted exe by looking up child processes, might not work in some cases
                var prs = ProcessTools.GetChildProcesses(pr.Id).FirstOrDefault();

                if (prs != 0)
                {
                    app = Application.Attach(prs);
                }
                else
                {
                    // Get all processes with name in format [A-Z]u_ (standard NSIS naming scheme, e.g. "Au_.exe") 
                    // and select the last one to launch. (Most likely to be ours)
                    var uninstallProcess = Process.GetProcesses()

View on GitHub (pinned to 608321de98)

Solutions

  1. Verify the uninstaller path exists and is an executable before calling: File.Exists on the parsed command's filename.
  2. Inspect how ProcessTools.SeparateArgsFromCommand splits the command and ensure the executable and arguments are separated correctly (quote paths containing spaces).
  3. Run the parent process from an elevated, interactive desktop session so the uninstaller can be spawned and later attached via UI automation.
  4. Check that no security software (AV, AppLocker, SRP) is silently blocking process creation; test launching the command manually first.

Example fix

// before
pr = ProcessTools.SeparateArgsFromCommand(uninstallerCommand).ToProcessStartInfo().Start();
if (pr == null)
    throw new IOException(Localization.Message_Automation_ProcessFailedToStart);

// after - validate the parsed executable before launching
var parsed = ProcessTools.SeparateArgsFromCommand(uninstallerCommand);
if (!File.Exists(parsed.FileName))
    throw new IOException($"Uninstaller not found: {parsed.FileName}");
pr = parsed.ToProcessStartInfo().Start();
if (pr == null)
    throw new IOException(Localization.Message_Automation_ProcessFailedToStart);
Defensive patterns

Strategy: validation

Validate before calling

var parsed = ProcessTools.SeparateArgsFromCommand(uninstallerCommand);
if (string.IsNullOrWhiteSpace(parsed.FileName) || !File.Exists(parsed.FileName))
    throw new FileNotFoundException("Uninstaller executable not found", parsed.FileName);

Type guard

// Ensure the command resolves to a real executable before calling UninstallNsisQuietly.
bool CanLaunch(string command)
{
    var p = ProcessTools.SeparateArgsFromCommand(command);
    return !string.IsNullOrWhiteSpace(p.FileName) && File.Exists(p.FileName);
}

Try / catch

try { UninstallNsisQuietly(cmd, cb); }
catch (IOException io) when (io.Message == Localization.Message_Automation_ProcessFailedToStart)
{
    // log cmd, prompt user for correct uninstaller path
}

Prevention

When it happens

Trigger: Calling UninstallNsisQuietly with a command string whose executable path does not exist, is not an .exe, lacks execute permission, or cannot be spawned under the current user/UAC context. Also when SeparateArgsFromCommand mis-parses the command so ToProcessStartInfo produces an invalid ProcessStartInfo that Start() rejects. Any case where the Start() extension returns null rather than a Process object.

Common situations: Uninstaller command points to a path that was already removed (uninstall.exe deleted mid-batch). Quoting/argument splitting in uninstallerCommand breaks the filename from its args. Running the automation from a service/SYSTEM account without an interactive desktop, so the GUI uninstaller cannot be spawned. Antivirus or SRP/AppLocker blocking the launch of the extracted uninstaller.

Related errors


AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13). Data as JSON: /api/errors/7ca5623f93013a1d. Report an issue: GitHub.