# Buggy code
def info(name, location="\\"):
    r"""
    Get the details about a task in the task scheduler.

    :param str name: The name of the task for which to return the status

    :param str location: A string value representing the location of the task.
        Default is '\\' which is the root for the task scheduler
        (C:\Windows\System32\tasks).

    :return:
    :rtype: dict

    CLI Example:

    .. code-block:: bash

        salt 'minion-id' task.info <task_name>
    """
    # Check for existing folder
    if name not in list_tasks(location):
        return "{0} not found in {1}".format(name, location)

    # connect to the task scheduler
    pythoncom.CoInitialize()
    task_service = win32com.client.Dispatch("Schedule.Service")
    task_service.Connect()

    # get the folder to delete the folder from
    task_folder = task_service.GetFolder(location)
    task = task_folder.GetTask(name)

    properties = {
        "enabled": task.Enabled,
        "last_run": _get_date_value(task.LastRunTime),
        "last_run_result": results[task.LastTaskResult],
        "missed_runs": task.NumberOfMissedRuns,
        "next_run": _get_date_value(task.NextRunTime),
        "status": states[task.State],
    }

    def_set = task.Definition.Settings

    settings = {}
    settings["allow_demand_start"] = def_set.AllowDemandStart
    settings["force_stop"] = def_set.AllowHardTerminate

    if def_set.DeleteExpiredTaskAfter == "":
        settings["delete_after"] = False
    elif def_set.DeleteExpiredTaskAfter == "PT0S":
        settings["delete_after"] = "Immediately"
    else:
        settings["delete_after"] = _reverse_lookup(
            duration, def_set.DeleteExpiredTaskAfter
        )

    if def_set.ExecutionTimeLimit == "":
        settings["execution_time_limit"] = False
    else:
        settings["execution_time_limit"] = _reverse_lookup(
            duration, def_set.ExecutionTimeLimit
        )

    settings["multiple_instances"] = _reverse_lookup(
        instances, def_set.MultipleInstances
    )

    if def_set.RestartInterval == "":
        settings["restart_interval"] = False
    else:
        settings["restart_interval"] = _reverse_lookup(
            duration, def_set.RestartInterval
        )

    if settings["restart_interval"]:
        settings["restart_count"] = def_set.RestartCount
    settings["stop_if_on_batteries"] = def_set.StopIfGoingOnBatteries
    settings["wake_to_run"] = def_set.WakeToRun

    conditions = {}
    conditions["ac_only"] = def_set.DisallowStartIfOnBatteries
    conditions["run_if_idle"] = def_set.RunOnlyIfIdle
    conditions["run_if_network"] = def_set.RunOnlyIfNetworkAvailable
    conditions["start_when_available"] = def_set.StartWhenAvailable

    if conditions["run_if_idle"]:
        idle_set = def_set.IdleSettings
        conditions["idle_duration"] = idle_set.IdleDuration
        conditions["idle_restart"] = idle_set.RestartOnIdle
        conditions["idle_stop_on_end"] = idle_set.StopOnIdleEnd
        conditions["idle_wait_timeout"] = idle_set.WaitTimeout

    if conditions["run_if_network"]:
        net_set = def_set.NetworkSettings
        conditions["network_id"] = net_set.Id
        conditions["network_name"] = net_set.Name

    actions = []
    for actionObj in task.Definition.Actions:
        action = {}
        action["action_type"] = _reverse_lookup(action_types, actionObj.Type)
        if actionObj.Path:
            action["cmd"] = actionObj.Path
        if actionObj.Arguments:
            action["arguments"] = actionObj.Arguments
        if actionObj.WorkingDirectory:
            action["working_dir"] = actionObj.WorkingDirectory
        actions.append(action)

    triggers = []
    for triggerObj in task.Definition.Triggers:
        trigger = {}
        trigger["trigger_type"] = _reverse_lookup(trigger_types, triggerObj.Type)
        if triggerObj.ExecutionTimeLimit:
            trigger["execution_time_limit"] = _reverse_lookup(
                duration, triggerObj.ExecutionTimeLimit
            )
        if triggerObj.StartBoundary:
            start_date, start_time = triggerObj.StartBoundary.split("T", 1)
            trigger["start_date"] = start_date
            trigger["start_time"] = start_time
        if triggerObj.EndBoundary:
            end_date, end_time = triggerObj.EndBoundary.split("T", 1)
            trigger["end_date"] = end_date
            trigger["end_time"] = end_time
        trigger["enabled"] = triggerObj.Enabled
        if triggerObj.RandomDelay == "":
            trigger["random_delay"] = False
        else:
            trigger["random_delay"] = _reverse_lookup(duration, triggerObj.RandomDelay)
        triggers.append(trigger)

    properties["settings"] = settings
    properties["conditions"] = conditions
    properties["actions"] = actions
    properties["triggers"] = triggers
    ret = properties

    return ret


# Traceback (AttributeError)
[DEBUG   ] Reading configuration from /etc/salt/master
[DEBUG   ] Missing configuration file: /root/.saltrc
[TRACE   ] The required configuration section, 'fluent_handler', was not found the in the configuration. Not loading the fluent logging handlers module.
[TRACE   ] None of the required configuration sections, 'logstash_udp_handler' and 'logstash_zmq_handler', were found in the configuration. Not loading the Logstash logging handlers module.
[DEBUG   ] Configuration file path: /etc/salt/master
[WARNING ] Insecure logging configuration detected! Sensitive data may be logged.
[DEBUG   ] Reading configuration from /etc/salt/master
[DEBUG   ] Missing configuration file: /root/.saltrc
[DEBUG   ] MasterEvent PUB socket URI: /var/run/salt/master/master_event_pub.ipc
[DEBUG   ] MasterEvent PULL socket URI: /var/run/salt/master/master_event_pull.ipc
[DEBUG   ] Initializing new AsyncZeroMQReqChannel for ('/etc/salt/pki/master', 'ux.disc0rd.com_master', 'tcp://127.0.0.1:6506', 'clear')
[TRACE   ] Inserted key into loop_instance_map id 140313310181424 for key ('/etc/salt/pki/master', 'ux.disc0rd.com_master', 'tcp://127.0.0.1:6506', 'clear') and process 27072
[DEBUG   ] Initializing new IPCClient for path: /var/run/salt/master/master_event_pub.ipc
[TRACE   ] IPCClient: Connecting to socket: /var/run/salt/master/master_event_pub.ipc
[TRACE   ] func get_cli_event_returns()
[DEBUG   ] LazyLoaded local_cache.get_load
[DEBUG   ] Reading minion list from /var/cache/salt/master/jobs/b8/29f5a7366ad73111d97d309a60cfbce5bcd48bce686f2a96013cecf41b8bed/.minions.p
[DEBUG   ] get_iter_returns for jid 20171025020027377960 sent to set(['gs-desktop']) will timeout at 02:00:32.388436
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] get_event() received = {'tag': 'salt/job/20171025020027377960/new', 'data': {'tgt_type': 'glob', 'jid': '20171025020027377960', 'tgt': 'gs*', '_stamp': '2017-10-25T02:00:27.380124', 'user': 'root', 'arg': [{'location': '\\Microsoft\\XblGameSave', 'name': 'XblGameSaveTaskLogon', '__kwarg__': True}], 'fun': 'task.info', 'minions': ['gs-desktop']}}
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] _get_event() waited 0 seconds and received nothing
[TRACE   ] get_event() received = {'tag': 'salt/job/20171025020027377960/ret/gs-desktop', 'data': {'fun_args': [{'location': '\\Microsoft\\XblGameSave', 'name': 'XblGameSaveTaskLogon'}], 'jid': '20171025020027377960', 'return': 'The minion function caused an exception: Traceback (most recent call last):\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\minion.py", line 1468, in _thread_return\n    return_data = executor.execute()\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\executors\\direct_call.py", line 28, in execute\n    return self.func(*self.args, **self.kwargs)\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\modules\\win_task.py", line 1383, in info\n    if triggerObj.RandomDelay == \'\':\n  File "c:\\salt\\bin\\lib\\site-packages\\win32com\\client\\dynamic.py", line 522, in __getattr__\n    raise AttributeError("%s.%s" % (self._username_, attr))\nAttributeError: <unknown>.RandomDelay\n', 'success': False, 'cmd': '_return', '_stamp': '2017-10-25T02:00:29.425738', 'fun': 'task.info', 'id': 'gs-desktop', 'out': 'nested'}}
[DEBUG   ] jid 20171025020027377960 return from gs-desktop
[DEBUG   ] return event: {'gs-desktop': {'jid': '20171025020027377960', 'ret': 'The minion function caused an exception: Traceback (most recent call last):\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\minion.py", line 1468, in _thread_return\n    return_data = executor.execute()\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\executors\\direct_call.py", line 28, in execute\n    return self.func(*self.args, **self.kwargs)\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\modules\\win_task.py", line 1383, in info\n    if triggerObj.RandomDelay == \'\':\n  File "c:\\salt\\bin\\lib\\site-packages\\win32com\\client\\dynamic.py", line 522, in __getattr__\n    raise AttributeError("%s.%s" % (self._username_, attr))\nAttributeError: <unknown>.RandomDelay\n', 'out': 'nested'}}
[DEBUG   ] LazyLoaded nested.output
[TRACE   ] data = {'gs-desktop': 'The minion function caused an exception: Traceback (most recent call last):\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\minion.py", line 1468, in _thread_return\n    return_data = executor.execute()\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\executors\\direct_call.py", line 28, in execute\n    return self.func(*self.args, **self.kwargs)\n  File "c:\\salt\\bin\\lib\\site-packages\\salt\\modules\\win_task.py", line 1383, in info\n    if triggerObj.RandomDelay == \'\':\n  File "c:\\salt\\bin\\lib\\site-packages\\win32com\\client\\dynamic.py", line 522, in __getattr__\n    raise AttributeError("%s.%s" % (self._username_, attr))\nAttributeError: <unknown>.RandomDelay\n'}
gs-desktop:
The minion function caused an exception: Traceback (most recent call last):
File "c:\salt\bin\lib\site-packages\salt\minion.py", line 1468, in _thread_return
return_data = executor.execute()
File "c:\salt\bin\lib\site-packages\salt\executors\direct_call.py", line 28, in execute
return self.func(*self.args, **self.kwargs)
File "c:\salt\bin\lib\site-packages\salt\modules\win_task.py", line 1383, in info
if triggerObj.RandomDelay == '':
File "c:\salt\bin\lib\site-packages\win32com\client\dynamic.py", line 522, in __getattr__
raise AttributeError("%s.%s" % (self._username_, attr))
AttributeError: <unknown>.RandomDelay
[TRACE   ] _get_event() waited 0 seconds and received nothing
[DEBUG   ] jid 20171025020027377960 found all minions set(['gs-desktop'])

# Fixed code
def info(name, location="\\"):
    r"""
    Get the details about a task in the task scheduler.

    Args:

        name (str):
            The name of the task for which to return the status

        location (str):
            A string value representing the location of the task. Default is
            ``\`` which is the root for the task scheduler
            (``C:\Windows\System32\tasks``).

    Returns:
        dict: A dictionary containing the task configuration

    CLI Example:

    .. code-block:: bash

        salt 'minion-id' task.info <task_name>
    """
    # Check for existing folder
    if name not in list_tasks(location):
        return "{0} not found in {1}".format(name, location)

    # connect to the task scheduler
    pythoncom.CoInitialize()
    task_service = win32com.client.Dispatch("Schedule.Service")
    task_service.Connect()

    # get the folder to delete the folder from
    task_folder = task_service.GetFolder(location)
    task = task_folder.GetTask(name)

    properties = {
        "enabled": task.Enabled,
        "last_run": _get_date_value(task.LastRunTime),
        "last_run_result": results[task.LastTaskResult],
        "missed_runs": task.NumberOfMissedRuns,
        "next_run": _get_date_value(task.NextRunTime),
        "status": states[task.State],
    }

    def_set = task.Definition.Settings

    settings = {
        "allow_demand_start": def_set.AllowDemandStart,
        "force_stop": def_set.AllowHardTerminate,
    }

    if def_set.DeleteExpiredTaskAfter == "":
        settings["delete_after"] = False
    elif def_set.DeleteExpiredTaskAfter == "PT0S":
        settings["delete_after"] = "Immediately"
    else:
        settings["delete_after"] = _reverse_lookup(
            duration, def_set.DeleteExpiredTaskAfter
        )

    if def_set.ExecutionTimeLimit == "":
        settings["execution_time_limit"] = False
    else:
        settings["execution_time_limit"] = _reverse_lookup(
            duration, def_set.ExecutionTimeLimit
        )

    settings["multiple_instances"] = _reverse_lookup(
        instances, def_set.MultipleInstances
    )

    if def_set.RestartInterval == "":
        settings["restart_interval"] = False
    else:
        settings["restart_interval"] = _reverse_lookup(
            duration, def_set.RestartInterval
        )

    if settings["restart_interval"]:
        settings["restart_count"] = def_set.RestartCount
    settings["stop_if_on_batteries"] = def_set.StopIfGoingOnBatteries
    settings["wake_to_run"] = def_set.WakeToRun

    conditions = {
        "ac_only": def_set.DisallowStartIfOnBatteries,
        "run_if_idle": def_set.RunOnlyIfIdle,
        "run_if_network": def_set.RunOnlyIfNetworkAvailable,
        "start_when_available": def_set.StartWhenAvailable,
    }

    if conditions["run_if_idle"]:
        idle_set = def_set.IdleSettings
        conditions["idle_duration"] = idle_set.IdleDuration
        conditions["idle_restart"] = idle_set.RestartOnIdle
        conditions["idle_stop_on_end"] = idle_set.StopOnIdleEnd
        conditions["idle_wait_timeout"] = idle_set.WaitTimeout

    if conditions["run_if_network"]:
        net_set = def_set.NetworkSettings
        conditions["network_id"] = net_set.Id
        conditions["network_name"] = net_set.Name

    actions = []
    for actionObj in task.Definition.Actions:
        action = {"action_type": _reverse_lookup(action_types, actionObj.Type)}
        if actionObj.Path:
            action["cmd"] = actionObj.Path
        if actionObj.Arguments:
            action["arguments"] = actionObj.Arguments
        if actionObj.WorkingDirectory:
            action["working_dir"] = actionObj.WorkingDirectory
        actions.append(action)

    triggers = []
    for triggerObj in task.Definition.Triggers:
        trigger = {"trigger_type": _reverse_lookup(trigger_types, triggerObj.Type)}
        if triggerObj.ExecutionTimeLimit:
            trigger["execution_time_limit"] = _reverse_lookup(
                duration, triggerObj.ExecutionTimeLimit
            )
        if triggerObj.StartBoundary:
            start_date, start_time = triggerObj.StartBoundary.split("T", 1)
            trigger["start_date"] = start_date
            trigger["start_time"] = start_time
        if triggerObj.EndBoundary:
            end_date, end_time = triggerObj.EndBoundary.split("T", 1)
            trigger["end_date"] = end_date
            trigger["end_time"] = end_time
        trigger["enabled"] = triggerObj.Enabled
        if hasattr(triggerObj, "RandomDelay"):
            if triggerObj.RandomDelay:
                trigger["random_delay"] = _reverse_lookup(
                    duration, triggerObj.RandomDelay
                )
            else:
                trigger["random_delay"] = False
        if hasattr(triggerObj, "Delay"):
            if triggerObj.Delay:
                trigger["delay"] = _reverse_lookup(duration, triggerObj.Delay)
            else:
                trigger["delay"] = False
        triggers.append(trigger)

    properties["settings"] = settings
    properties["conditions"] = conditions
    properties["actions"] = actions
    properties["triggers"] = triggers
    ret = properties

    return ret