Skip to content

Instantly share code, notes, and snippets.

@Iristyle
Created March 28, 2018 06:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Iristyle/8a6e6f247a5d28d70ccd7aae889666fb to your computer and use it in GitHub Desktop.
Save Iristyle/8a6e6f247a5d28d70ccd7aae889666fb to your computer and use it in GitHub Desktop.
Get scheduled tasks with compat
Get-ScheduledTask | % {
$props = [ordered]@{
TaskName = $psitem.TaskName
# note ErrorAction Ignore needed to prevent conversion problems
Compatibility = $psitem | Select -ExpandProperty Settings | Select -ExpandProperty Compatibility -ErrorAction Ignore
}
New-Object -TypeName PSObject -Property $props
}
@michaeltlombardi
Copy link

This seems to work without errors:

Get-ScheduledTask | % {
 $props = [ordered]@{
   TaskName = $psitem.TaskName
   Compatibility = $psitem.Settings.Compatibility
 }
 New-Object -TypeName PSObject -Property $props
}

@jpogran
Copy link

jpogran commented Mar 28, 2018

$props = @(
  'TaskName',
  @{ n= 'Compatibility'; e = { $_.Settings.Compatibility }}
)

Get-ScheduledTask | Select-Object $props

@Iristyle
Copy link
Author

Iristyle commented Mar 28, 2018

To get the actual [int] value for the enum instead of having PS giving us the "friendly" enum name:

Get-ScheduledTask | Select TaskName, @{Name="Compat";Expression={[int]$_.Settings.Compatibility}}

Then we can manually figure out how PowerShell is generating the mapping:

1 - V1
2 - Vista
3 - ?? (no tasks set to 3)
4 - Win8

Docs refer to a CompatibilityEnum but don't link to / document it in New-ScheduledTaskSettingsSet cmdlet, and lists accepted values as At, V1, Vista, Win7, Win8. The odd thing is that presumably 0 should map to At, but doesn't return as such when using Get-ScheduledTask, which seems like a bug.

The MOF definition from schedprov.mof is interesting:

class MSFT_TaskSettings
{
        boolean AllowDemandStart;
        string RestartInterval;
        string ExecutionTimeLimit;
        string DeleteExpiredTaskAfter;
        boolean RunOnlyIfIdle;
        boolean AllowHardTerminate;
        [ValueMap{"0", "1", "2", "3", "4"}: ToSubClass, Values{"8", "9", "10", "11", "12"}: ToSubClass Amended, read: ToSubClass] sint32 Compatibility;
        boolean DisallowStartIfOnBatteries;
        boolean Enabled;
        boolean Hidden;
        [ValueMap{"0", "1", "2", "3"}: ToSubClass, Values{"13", "14", "15", "16"}: ToSubClass Amended, read: ToSubClass] sint32 MultipleInstances;
        uint32 Priority;
        uint32 RestartCount;
        boolean RunOnlyIfNetworkAvailable;
        boolean StartWhenAvailable;
        boolean StopIfGoingOnBatteries;
        boolean WakeToRun;
        [EmbeddedInstance("MSFT_TaskIdleSettings"): ToSubClass] MSFT_TaskIdleSettings IdleSettings;
        [EmbeddedInstance("MSFT_TaskNetworkSettings"): ToSubClass] MSFT_TaskNetworkSettings NetworkSettings;
};
class MSFT_TaskSettings2 : MSFT_TaskSettings
{
        boolean DisallowStartOnRemoteAppSession;
        boolean UseUnifiedSchedulingEngine;
};
class MSFT_TaskSettings3 : MSFT_TaskSettings2
{
        [EmbeddedInstance("MSFT_TaskMaintenanceSettings"): ToSubClass] MSFT_TaskMaintenanceSettings MaintenanceSettings;
        boolean volatile;
};

It's still a little unclear how this directly maps over to the TASK_COMPATIBILITY values in the COM API which only understand 0, 1 and 2

@Iristyle
Copy link
Author

Uncovered a little bit more info by looking at return values from COM components and comparing them to the CIM output:

On a Windows 10 machine 10.0.14393.0 / template win-10-1607-x86_64

PS C:\Users\Administrator> $service = New-Object -ComObject Schedule.Service
PS C:\Users\Administrator> $service.Connect()
PS C:\Users\Administrator> $root = $service.GetFolder('\')

# UI Configure for "Windows Vista, Windows Server 2008"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
2
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         2  Vista


# UI Configure for "Windows 7, Windows Server 2008 R2"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
3
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         3   Win7

# UI Configure for "Windows 10"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
4
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         4   Win8

On a Windows 2016 machine 10.0.14393.0 / template win-2016-x86_64

PS C:\Users\Administrator> $service = New-Object -ComObject Schedule.Service
PS C:\Users\Administrator> $service.Connect()
PS C:\Users\Administrator> $root = $service.GetFolder('\')

# UI Configure for "Windows Vista, Windows Server 2008"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
2
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         2  Vista


# UI Configure for "Windows 7, Windows Server 2008 R2"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
3
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         3   Win7

# UI Configure for "Windows Server 2016"
PS C:\Users\Administrator> $root.GetTask('UpdateBGInfo').Definition.Settings.Compatibility
4
PS C:\Users\Administrator> Get-ScheduledTask -TaskName UpdateBGInfo | Select TaskName, @{Name="CompatInt";Expression={[int]$_.Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName     CompatInt Compat
--------     --------- ------
UpdateBGInfo         4   Win8

@Iristyle
Copy link
Author

Iristyle commented Mar 29, 2018

Hey @glennsarti - any idea where you got 6 from at https://github.com/puppetlabs/puppetlabs-scheduled_task/blob/dfca56dfc7077010c607f648eecde9193bfb3a36/lib/puppet_x/puppetlabs/scheduled_task/taskscheduler2.rb#L28 ?

Based on my digging around, that doesn't seem right... I think Windows 10 compat is the same as Windows 8 / Server 2012R2.

Nothing in https://msdn.microsoft.com/en-us/library/windows/desktop/aa384138(v=vs.85).aspx indicates anything new in 10 - just a behavior change for an existing task type.

@glennsarti
Copy link

Windows 10 1709

def enum
  result = @tasksched.task('\\Dell SupportAssistAgent AutoUpdate')
  defn = @tasksched.task_definition(result)
  puts "compat = #{ @tasksched.compatibility(defn)}"

@glennsarti
Copy link

image

@glennsarti
Copy link

C:\Users\glenn.sarti> Get-ScheduledTask -TaskName 'Dell SupportAssistAgent AutoUpdate' | Select TaskName, @{Name="CompatInt";Expression={[int]$_.
Settings.Compatibility}}, @{Name="Compat";Expression={$_.Settings.Compatibility}}

TaskName                           CompatInt Compat
--------                           --------- ------
Dell SupportAssistAgent AutoUpdate         0


@Iristyle
Copy link
Author

Answered the question about compatibility by looking at latest taskschd.h from Windows 10 SDK 10.0.17134.0 - see https://gist.github.com/Iristyle/ccf04cf085c43a72b7a57823319ebf53#file-taskschd-h-L828-L838

typedef 
enum _TASK_COMPATIBILITY
    {
        TASK_COMPATIBILITY_AT	= 0,
        TASK_COMPATIBILITY_V1	= 1,
        TASK_COMPATIBILITY_V2	= 2,
        TASK_COMPATIBILITY_V2_1	= 3,
        TASK_COMPATIBILITY_V2_2	= 4,
        TASK_COMPATIBILITY_V2_3	= 5,
        TASK_COMPATIBILITY_V2_4	= 6
    } 	TASK_COMPATIBILITY;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment