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
- Verify the uninstaller path exists and is an executable before calling: File.Exists on the parsed command's filename.
- Inspect how ProcessTools.SeparateArgsFromCommand splits the command and ensure the executable and arguments are separated correctly (quote paths containing spaces).
- Run the parent process from an elevated, interactive desktop session so the uninstaller can be spawned and later attached via UI automation.
- 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
- Validate the uninstaller path with File.Exists before launching.
- Quote any path containing spaces in the command string so SeparateArgsFromCommand parses the filename correctly.
- Run from an elevated interactive session so the GUI uninstaller can spawn and attach.
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
- Automatic uninstallation failed.
- Reoccuring popup window detected!
- This application does not have a valid uninstaller
- File name cannot be empty.
- The uninstall list file is empty.
AI-assisted analysis of BCUninstaller/Bulk-Crap-Uninstaller@608321de98 (2026-08-13).
Data as JSON: /api/errors/7ca5623f93013a1d.
Report an issue: GitHub.