docs: def remove(name=None, pkgs=None, **kwargs):
      '''
      Remove the passed package(s) from the system using winrepo
  
      .. versionadded:: 0.16.0
  
      Args:
          name (str):
              The name(s) of the package(s) to be uninstalled. Can be a
              single package or a comma delimited list of packages, no spaces.
  
          pkgs (list):
              A list of packages to delete. Must be passed as a python list. The
              ``name`` parameter will be ignored if this option is passed.
  
      Kwargs:
  
          version (str):
              The version of the package to be uninstalled. If this option is
              used to to uninstall multiple packages, then this version will be
              applied to all targeted packages. Recommended using only when
              uninstalling a single package. If this parameter is omitted, the
              latest version will be uninstalled.
  
          saltenv (str): Salt environment. Default ``base``
          refresh (bool): Refresh package metadata. Default ``False``
  
      Returns:
          dict: Returns a dict containing the changes.
  
          If the package is removed by ``pkg.remove``:
  
              {'<package>': {'old': '<old-version>',
                             'new': '<new-version>'}}
  
          If the package is already uninstalled:
  
              {'<package>': {'current': 'not installed'}}
  
      CLI Example:
  
      .. code-block:: bash
  
          salt '*' pkg.remove <package name>
          salt '*' pkg.remove <package1>,<package2>,<package3>
          salt '*' pkg.remove pkgs='["foo", "bar"]'
      '''
      saltenv = kwargs.get('saltenv', 'base')
      refresh = salt.utils.data.is_true(kwargs.get('refresh', False))
      # no need to call _refresh_db_conditional as list_pkgs will do it
      ret = {}
  
      # Make sure name or pkgs is passed
      if not name and not pkgs:
          return 'Must pass a single package or a list of packages'
  
      # Get package parameters
      pkg_params = __salt__['pkg_resource.parse_targets'](name, pkgs, **kwargs)[0]
  
      # Get a list of currently installed software for comparison at the end
      old = list_pkgs(saltenv=saltenv, refresh=refresh, versions_as_list=True)
  
      # Loop through each package
      changed = []  # list of changed package names
      for pkgname, version_num in six.iteritems(pkg_params):
  
          # Load package information for the package
          pkginfo = _get_package_info(pkgname, saltenv=saltenv)
  
          # Make sure pkginfo was found
          if not pkginfo:
              msg = 'Unable to locate package {0}'.format(pkgname)
              log.error(msg)
              ret[pkgname] = msg
              continue
  
          # Check to see if package is installed on the system
          if pkgname not in old:
              log.debug('%s %s not installed', pkgname, version_num if version_num else '')
              ret[pkgname] = {'current': 'not installed'}
              continue
  
          removal_targets = []
          # Only support a single version number
          if version_num is not None:
              #  Using the salt cmdline with version=5.3 might be interpreted
              #  as a float it must be converted to a string in order for
              #  string matching to work.
              version_num = six.text_type(version_num)
  
          # At least one version of the software is installed.
          if version_num is None:
              for ver_install in old[pkgname]:
                  if ver_install not in pkginfo and 'latest' in pkginfo:
                      log.debug('%s %s using package latest entry to to remove', pkgname, version_num)
                      removal_targets.append('latest')
                  else:
                      removal_targets.append(ver_install)
          else:
              if version_num in pkginfo:
                  # we known how to remove this version
                  if version_num in old[pkgname]:
                      removal_targets.append(version_num)
                  else:
                      log.debug('%s %s not installed', pkgname, version_num)
                      ret[pkgname] = {'current': '{0} not installed'.format(version_num)}
                      continue
              elif 'latest' in pkginfo:
                  # we do not have version entry, assume software can self upgrade and use latest
                  log.debug('%s %s using package latest entry to to remove', pkgname, version_num)
                  removal_targets.append('latest')
  
          if not removal_targets:
              log.error('%s %s no definition to remove this version', pkgname, version_num)
              ret[pkgname] = {
                      'current': '{0} no definition, cannot removed'.format(version_num)
                  }
              continue
  
          for target in removal_targets:
              # Get the uninstaller
              uninstaller = pkginfo[target].get('uninstaller', '')
              cache_dir = pkginfo[target].get('cache_dir', False)
              uninstall_flags = pkginfo[target].get('uninstall_flags', '')
  
              # If no uninstaller found, use the installer with uninstall flags
              if not uninstaller and uninstall_flags:
                  uninstaller = pkginfo[target].get('installer', '')
  
              # If still no uninstaller found, fail
              if not uninstaller:
                  log.error(
                      'No installer or uninstaller configured for package %s',
                      pkgname,
                  )
                  ret[pkgname] = {'no uninstaller defined': target}
                  continue
  
              # Where is the uninstaller
              if uninstaller.startswith(('salt:', 'http:', 'https:', 'ftp:')):
  
                  # Check for the 'cache_dir' parameter in the .sls file
                  # If true, the entire directory will be cached instead of the
                  # individual file. This is useful for installations that are not
                  # single files
  
                  if cache_dir and uninstaller.startswith('salt:'):
                      path, _ = os.path.split(uninstaller)
                      __salt__['cp.cache_dir'](path,
                                               saltenv,
                                               False,
                                               None,
                                               'E@init.sls$')
  
                  # Check to see if the uninstaller is cached
                  cached_pkg = __salt__['cp.is_cached'](uninstaller, saltenv)
                  if not cached_pkg:
                      # It's not cached. Cache it, mate.
                      cached_pkg = __salt__['cp.cache_file'](uninstaller, saltenv)
  
                      # Check if the uninstaller was cached successfully
                      if not cached_pkg:
                          log.error('Unable to cache %s', uninstaller)
                          ret[pkgname] = {'unable to cache': uninstaller}
                          continue
  
                  # Compare the hash of the cached installer to the source only if
                  # the file is hosted on salt:
                  # TODO cp.cache_file does cache and hash checking? So why do it again?
                  if uninstaller.startswith('salt:'):
                      if __salt__['cp.hash_file'](uninstaller, saltenv) != \
                              __salt__['cp.hash_file'](cached_pkg):
                          try:
                              cached_pkg = __salt__['cp.cache_file'](
                                  uninstaller, saltenv)
                          except MinionError as exc:
                              return '{0}: {1}'.format(exc, uninstaller)
  
                          # Check if the installer was cached successfully
                          if not cached_pkg:
                              log.error('Unable to cache %s', uninstaller)
                              ret[pkgname] = {'unable to cache': uninstaller}
                              continue
              else:
                  # Run the uninstaller directly
                  # (not hosted on salt:, https:, etc.)
                  cached_pkg = os.path.expandvars(uninstaller)
  
              # Fix non-windows slashes
              cached_pkg = cached_pkg.replace('/', '\\')
              cache_path, _ = os.path.split(cached_pkg)
  
              # os.path.expandvars is not required as we run everything through cmd.exe /s /c
  
              if kwargs.get('extra_uninstall_flags'):
                  uninstall_flags = '{0} {1}'.format(
                      uninstall_flags, kwargs.get('extra_uninstall_flags', ''))
  
              # Compute msiexec string
              use_msiexec, msiexec = _get_msiexec(pkginfo[target].get('msiexec', False))
              cmd_shell = os.getenv('ComSpec', '{0}\\system32\\cmd.exe'.format(os.getenv('WINDIR')))
  
              # Build cmd and arguments
              # cmd and arguments must be separated for use with the task scheduler
              if use_msiexec:
                  # Check if uninstaller is set to {guid}, if not we assume its a remote msi file.
                  # which has already been downloaded.
                  arguments = '"{0}" /X "{1}"'.format(msiexec, cached_pkg)
              else:
                  arguments = '"{0}"'.format(cached_pkg)
  
              if uninstall_flags:
                  arguments = '{0} {1}'.format(arguments, uninstall_flags)
  
              # Uninstall the software
              changed.append(pkgname)
              # Check Use Scheduler Option
              if pkginfo[target].get('use_scheduler', False):
                  # Create Scheduled Task
                  __salt__['task.create_task'](name='update-salt-software',
                                               user_name='System',
                                               force=True,
                                               action_type='Execute',
                                               cmd=cmd_shell,
                                               arguments='/s /c "{0}"'.format(arguments),
                                               start_in=cache_path,
                                               trigger_type='Once',
                                               start_date='1975-01-01',
                                               start_time='01:00',
                                               ac_only=False,
                                               stop_if_on_batteries=False)
                  # Run Scheduled Task
                  if not __salt__['task.run_wait'](name='update-salt-software'):
                      log.error('Failed to remove %s', pkgname)
                      log.error('Scheduled Task failed to run')
                      ret[pkgname] = {'uninstall status': 'failed'}
              else:
                  # Launch the command
                  result = __salt__['cmd.run_all'](
                          '"{0}" /s /c "{1}"'.format(cmd_shell, arguments),
                          output_loglevel='trace',
                          python_shell=False,
                          redirect_stderr=True)
                  if not result['retcode']:
                      ret[pkgname] = {'uninstall status': 'success'}
                      changed.append(pkgname)
                  elif result['retcode'] == 3010:
                      # 3010 is ERROR_SUCCESS_REBOOT_REQUIRED
                      report_reboot_exit_codes = kwargs.pop(
                          'report_reboot_exit_codes', True)
                      if report_reboot_exit_codes:
                          __salt__['system.set_reboot_required_witnessed']()
                      ret[pkgname] = {'uninstall status': 'success, reboot required'}
                      changed.append(pkgname)
                  elif result['retcode'] == 1641:
                      # 1641 is ERROR_SUCCESS_REBOOT_INITIATED
                      ret[pkgname] = {'uninstall status': 'success, reboot initiated'}
                      changed.append(pkgname)
                  else:
                      log.error('Failed to remove %s', pkgname)
                      log.error('retcode %s', result['retcode'])
                      log.error('uninstaller output: %s', result['stdout'])
                      ret[pkgname] = {'uninstall status': 'failed'}
  
      # Get a new list of installed software
      new = list_pkgs(saltenv=saltenv, refresh=False)
  
      # Take the "old" package list and convert the values to strings in
      # preparation for the comparison below.
      __salt__['pkg_resource.stringify'](old)
  
      # Check for changes in the registry
      difference = salt.utils.data.compare_dicts(old, new)
      found_chgs = all(name in difference for name in changed)
      end_t = time.time() + 3  # give it 3 seconds to catch up.
      while not found_chgs and time.time() < end_t:
          time.sleep(0.5)
          new = list_pkgs(saltenv=saltenv, refresh=False)
          difference = salt.utils.data.compare_dicts(old, new)
          found_chgs = all(name in difference for name in changed)
  
      if not found_chgs:
          log.warning('Expected changes for package removal may not have occured')
  
      # Compare the software list before and after
      # Add the difference to ret
      ret.update(difference)
      return ret