How extract two tags from an XML export of schtasks.exe

michelle0436
michelle0436 used Ask the Experts™
on
Hello -

  I need to generate a list of Windows Scheduled tasks on a server.  I need the Registration Date and the Task Name.  If I use:
schtasks /query /xml >c:\temp\tasks.xml
Each task is returned and those two tags are included.

<!-- \test_of_date -->
<Date>


The best option would be able to run that command and only ask for those two tags.  Another option would be to read the resulting file and grab just those two tags.

Any idea how I can do this?  I have investigated the Powershell module PowerScheduledTasks, but it doesn't seem to add any functionality beyond schtasks.exe

Example from the file:

<!-- \test_of_date -->
<?xml version="1.0" encoding="UTF-16"?>
<Task version="1.2" xmlns="http://schemas.microsoft.com/windows/2004/02/mit/task">
  <RegistrationInfo>
    <Date>2015-10-15T16:22:22.9464466</Date>
    <Author>WRBTS\mmorris</Author>
  </RegistrationInfo>
  <Triggers>
    <CalendarTrigger>
      <StartBoundary>2015-10-15T16:21:58.3367566</StartBoundary>
      <Enabled>true</Enabled>
      <ScheduleByDay>
        <DaysInterval>1</DaysInterval>
      </ScheduleByDay>
    </CalendarTrigger>
  </Triggers>
  <Principals>
    <Principal id="Author">
      <RunLevel>LeastPrivilege</RunLevel>
      <UserId>WRBTS\mmorris</UserId>
      <LogonType>InteractiveToken</LogonType>
    </Principal>
  </Principals>
  <Settings>
    <MultipleInstancesPolicy>IgnoreNew</MultipleInstancesPolicy>
    <DisallowStartIfOnBatteries>true</DisallowStartIfOnBatteries>
    <StopIfGoingOnBatteries>true</StopIfGoingOnBatteries>
    <AllowHardTerminate>true</AllowHardTerminate>
    <StartWhenAvailable>false</StartWhenAvailable>
    <RunOnlyIfNetworkAvailable>false</RunOnlyIfNetworkAvailable>
    <IdleSettings>
      <Duration>PT10M</Duration>
      <WaitTimeout>PT1H</WaitTimeout>
      <StopOnIdleEnd>true</StopOnIdleEnd>
      <RestartOnIdle>false</RestartOnIdle>
    </IdleSettings>
    <AllowStartOnDemand>true</AllowStartOnDemand>
    <Enabled>true</Enabled>
    <Hidden>false</Hidden>
    <RunOnlyIfIdle>false</RunOnlyIfIdle>
    <WakeToRun>false</WakeToRun>
    <ExecutionTimeLimit>P3D</ExecutionTimeLimit>
    <Priority>7</Priority>
  </Settings>
  <Actions Context="Author">
    <ShowMessage>
      <Title>hello world</Title>
      <Body>hello world</Body>
    </ShowMessage>
  </Actions>
</Task>

Open in new window

Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
Just passing by, but here's a potential start at getting this info with just powershell.  Try this small script.

Get-ScheduledTask | foreach {
  [xml] $xml = Export-ScheduledTask -TaskName $_.TaskName -TaskPath $_.TaskPath
  $xml.Task.RegistrationInfo | Select Date,URI
}

Open in new window

~bp
Top Expert 2014

Commented:
Not all tasks have a created date.
The schtasks command needs to be modified slightly for PowerShell to work with it.  You can parse the output directly in memory instead of writing it to a file.
$x = [xml](schtasks /query /xml one)
foreach ( $i in (0..($x.Tasks.Task.Count)) )
{
    If ( ($x.Tasks.Task)[$i].registrationinfo.date )
    {
        New-Object PsObject -Property @{
                                Taskname = "$($x.Tasks.'#comment'[$i])"
                                Date = Get-Date "$(($x.Tasks.task)[$i].RegistrationInfo.Date)"
                                }
    }
}

Open in new window

Author

Commented:
Thank you so much for your assistance!

Bill - I added Author to the Select list.  However I found that a task I built has an entry with the date and author, but the URI field is empty.  Is it possible to get just the task names and not the URI?  I tried substituting TaskName for URI, but the column is empty.

Footech - How could I change your script to report back on all tasks, not just the ones that have a date?  Also - How could I add Author to the output?

Michelle
Amazon Web Services

Are you thinking about creating an Amazon Web Services account for your business? Not sure where to start? In this course you’ll get an overview of the history of AWS and take a tour of their user interface.

Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
Unfortunately it looks like the task name is actually in the first line of the extracted XML, but as a comment.  As a result no approach that loads the XML data and works with it will load the comment.

We could just treat the XML file as a TXT file I guess, and "find" the comment and look for the date, but that could be a bit less dependable.

~bp
Top Expert 2014

Commented:
Not all tasks have an author property either, and if you look at the XML you'll see that quite a few have the author as what looks like a DLL resource (they all end up being Microsoft Corporation).
$x = [xml](schtasks /query /xml one)
foreach ( $i in (0..($x.Tasks.Task.Count)) )
{
    If ( ($x.Tasks.Task)[$i].registrationinfo.date )
    {
        $date = Get-Date "$(($x.Tasks.task)[$i].RegistrationInfo.Date)"
    }
    Else
    {
        $date = ""
    }
    If ( "$(($x.Tasks.task)[$i].RegistrationInfo.Author)" -match '^\$\(@%' )
    {
        $author = "Microsoft Corporation"
    }
    Else
    {
        $author  = "$(($x.Tasks.task)[$i].RegistrationInfo.Author)"
    }
    New-Object PsObject -Property @{
                            Taskname = "$($x.Tasks.'#comment'[$i])"
                            Date = $date
                            Author = $author
                            }
}

Open in new window

If you need additional info about tasks I'd suggest taking a look at https://gallery.technet.microsoft.com/scriptcenter/Retrieve-Remote-Scheduled-72985b8f to see if it gives you all you want.
Top Expert 2014
Commented:
Here's a little refinement to the code I posted above.  I found a function that will extract the resource info, so I integrated that into the script.
# by Dr. Tobias Weltner 
# PowerShell Trainings throughout Europe 
# Hungry for a training? Get in touch: tobias.weltner (AT) email.de 
     
function Get-ResourceString { 
    param($path) 
     
    $code = @' 
    [DllImport("user32.dll", EntryPoint="LoadStringW", CallingConvention = CallingConvention.Winapi, CharSet = CharSet.Unicode)] 
    public static extern int LoadString(IntPtr hModule, int resourceID, StringBuilder resourceValue, int len); 
    [DllImport("kernel32.dll", CharSet = CharSet.Unicode, ExactSpelling = true, EntryPoint = "LoadLibraryExW")] 
    public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags); 
    [DllImport("kernel32.dll", ExactSpelling = true)] 
    public static extern int FreeLibrary(IntPtr hModule); 
'@ 
     
    $helper = Add-Type -MemberDefinition $code -Name ResourceStrings -Namespace Win32API -PassThru -UsingNamespace System.Text 
       
    $info = $path -split ','  
    $file = [System.Environment]::ExpandEnvironmentVariables( ($info[0] -replace '@','') ) 
    $id = [Math]::Abs($info[1]) 
     
    [IntPtr]$hMod = $helper::LoadLibraryEx($file, [IntPtr]::Zero, 3) 
    if($hMod -ne [IntPtr]::Zero) { 
        $sb = New-Object System.Text.StringBuilder(1024) 
        if($helper::LoadString($hMod, $id, $sb, $sb.Capacity) -ne 0) { 
            $sb.ToString() 
        } 
        [void]$helper::FreeLibrary($hMod); 
    }  
}


$x = [xml](schtasks /query /xml one)
foreach ( $i in (0..($x.Tasks.Task.Count)) )
{
    If ( ($x.Tasks.Task)[$i].registrationinfo.date )
    {
        $date = Get-Date "$(($x.Tasks.task)[$i].RegistrationInfo.Date)"
    }
    Else
    {
        $date = ""
    }
    If ( "$(($x.Tasks.task)[$i].RegistrationInfo.Author)" -match '^\$\(@%' )
    {
        $author = Get-ResourceString ("$(($x.Tasks.task)[$i].RegistrationInfo.Author)").Trim('$()')
    }
    Else
    {
        $author  = "$(($x.Tasks.task)[$i].RegistrationInfo.Author)"
    }
    New-Object PsObject -Property @{
                            Taskname = ("$($x.Tasks.'#comment'[$i])" -split "\\")[-1]
                            Date = $date
                            Author = $author
                            }
}

Open in new window

Author of the Year 2011
Top Expert 2006

Commented:
I've requested that this question be deleted for the following reason:

Not enough information to confirm an answer.
Top Expert 2014

Commented:
The script posted in https:#a41085464 does everything asked for.  Task Name, Creation Date, and Author are shown for every task where they are available.
Bill PrewIT / Software Engineering Consultant
Top Expert 2016

Commented:
I tend to agree, while we haven't heard from the OP, I feel like the solution that was suggested is useful enough I'd like to see it kept for future reference and use by others.

~bp

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial