BCUninstaller/Bulk-Crap-Uninstaller · warning · ArgumentException

Multiple UpdateIDs specified

Error message

Multiple UpdateIDs specified

What it means

ArgumentException thrown in the default case when a token is being treated as an UpdateID (i.e. _queryType is Uninstall) but _updateId is already non-null. The uninstall command accepts exactly one UpdateID; a second positional token after the command is rejected.

Source

Thrown at source/WinUpdateHelper/Program.cs:92

                switch (arg.ToLowerInvariant())
                {
                    case @"u":
                    case @"uninstall":
                        if (_queryType != QueryType.None) throw new ArgumentException(@"Multiple commands specified");
                        _queryType = QueryType.Uninstall;
                        break;

                    case @"l":
                    case @"list":
                        if (_queryType != QueryType.None) throw new ArgumentException(@"Multiple commands specified");
                        _queryType = QueryType.List;
                        break;

                    default:
                        if (_queryType != QueryType.Uninstall)
                            throw new ArgumentException($@"Unknown argument: {arg}");
                        if (_updateId != null)
                            throw new ArgumentException(@"Multiple UpdateIDs specified");
                        _updateId = arg;
                        break;
                }
            }

            if (_queryType == QueryType.None)
                throw new ArgumentException(@"No commands specified");

            if (_queryType == QueryType.Uninstall && _updateId == null)
                throw new ArgumentException(@"No UpdateID specified");
        }

        private enum QueryType
        {
            None,
            Uninstall,
            List
        }

View on GitHub (pinned to 608321de98)

Solutions

  1. Pass exactly one UpdateID per invocation.
  2. For batch removal, invoke the helper once per ID in a loop rather than one call with many IDs.
  3. Trim/quote arguments in the wrapper so a single ID is not split into two tokens.

Example fix

// before
WinUpdateHelper.exe uninstall id1 id2
// after
foreach ($id in $ids) { WinUpdateHelper.exe uninstall $id }
Defensive patterns

Strategy: validation

Validate before calling

var positional = args.SkipWhile(a => a.ToLowerInvariant() != "u" && a.ToLowerInvariant() != "uninstall").Skip(1);
if (positional.Count() > 1) throw new ArgumentException("Multiple UpdateIDs specified");

Type guard

bool HasSingleUpdateId(IList<string> args)
{
    var cmdIdx = Enumerable.Range(0, args.Count)
        .FirstOrDefault(i => new[]{"u","uninstall"}.Contains(args[i].ToLowerInvariant()));
    return args.Skip(cmdIdx + 1).Count() <= 1;
}

Prevention

When it happens

Trigger: Invoking 'uninstall <id1> <id2>' where two ID tokens follow the command. A stray trailing argument after the real UpdateID.

Common situations: Caller script passes a list of IDs assuming batch uninstall is supported (it is not). A copy-paste duplicate. An extra quoted segment parsed as a separate token.

Related errors


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