docs: function (args, detached, callback) {
    let error, errorEmitted, stderr, stdout
  
    try {
      // Ensure we don't spawn multiple squirrel processes
      // Process spawned, same args:        Attach events to alread running process
      // Process spawned, different args:   Return with error
      // No process spawned:                Spawn new process
      if (spawnedProcess && !isSameArgs(args)) {
        // Disabled for backwards compatibility:
        // eslint-disable-next-line standard/no-callback-literal
        return callback(`AutoUpdater process with arguments ${args} is already running`)
      } else if (!spawnedProcess) {
        spawnedProcess = spawn(updateExe, args, {
          detached: detached,
          windowsHide: true
        })
        spawnedArgs = args || []
      }
    } catch (error1) {
      error = error1
  
      // Shouldn't happen, but still guard it.
      process.nextTick(function () {
        return callback(error)
      })
      return
    }
    stdout = ''
    stderr = ''
  
    spawnedProcess.stdout.on('data', (data) => { stdout += data })
    spawnedProcess.stderr.on('data', (data) => { stderr += data })
  
    errorEmitted = false
    spawnedProcess.on('error', (error) => {
      errorEmitted = true
      callback(error)
    })
  
    return spawnedProcess.on('exit', function (code, signal) {
      spawnedProcess = undefined
      spawnedArgs = []
  
      // We may have already emitted an error.
      if (errorEmitted) {
        return
      }
  
      // Process terminated with error.
      if (code !== 0) {
        // Disabled for backwards compatibility:
        // eslint-disable-next-line standard/no-callback-literal
        return callback(`Command failed: ${signal != null ? signal : code}\n${stderr}`)
      }
  
      // Success.
      callback(null, stdout)
    })
  }