Task scheduler scheduled task with priority changed to normal fails on disk IO

2021-12-07T11:17:03.29+00:00

Hi
I test with Windows 10 Ver 1803.
I have scheduled a task which runs a .NET application which write something to disk. I need to run this application with normal priority, so I did some tricky way and change the task priority from default below normal to normal (https://aavtech.site/2018/01/windows-task-scheduler-changing-task-priority/). From then by, this task fails with an IOException, which I see in Event viewer.
Interestingly other triggering options like manually or scheduled on an specific time, runs it normally.
I understand that Windows will restrict Disk IO for a changed priority Task while it`s trigger is on Startup. Are there any security policies or other settings that would interfere with scheduled task, on this circumstance?

Windows Server
Windows Server
A family of Microsoft server operating systems that support enterprise-level management, data storage, applications, and communications.
12,078 questions
0 comments No comments
{count} votes

Accepted answer
  1. MotoX80 31,556 Reputation points
    2021-12-19T14:55:24.107+00:00

    As you see in this log, the programs starts without first disk testing:

    That means that it sees the drive letter but not the temp folder itself. I have removed the tests for the volume, Try this.

       # Update 19-Dec - Check for the folder and driveletter, not the volume.  
       Start-Transcript -Path ("C:\temp\{0}-{1}-PSConsole.txt" -f $env:USERNAME, (get-date -format "yyyyMMdd-HHmmss" ))            # This is your log file 
       $Folder = $env:TEMP              # This is the target folder that we need to access.  Did you use this one? 
       ###$Folder = "B:\temp1"          # This is the target folder that we need to access. 
       "Temp folder is {0}" -f $Folder  
       $Wait = $true
       $count = 0 
       $limit = 10                   # how many times should we retry (10 minutes) 
       $launch = $false
       $DriveLetter = $Folder.Split(":")[0]
       "{0} - I am going wait on the {1} drive." -f (get-date),   $DriveLetter
       "{0} - Here are the volumes that I see." -f (get-date)
       Get-Volume | Format-Table
       Try { 
           Get-Item "$($DriveLetter):\" -ErrorAction Stop
           "{0} - I see the {1} drive!" -f (get-date), $DriveLetter 
       } catch {
           "{0} - I don't see a {1} drive." -f (get-date), $DriveLetter 
       } 
    
       ""
       "{0} - Main loop." -f (get-date)
       while ($wait) {
           $Drive = Get-Item "$($DriveLetter):\" -ErrorAction SilentlyContinue
           if ($Drive) {        # do we see the drive letter 
               "{0} - I see the drive." -f (get-date) 
               New-Item -Path $Folder -ItemType Directory -ErrorAction SilentlyContinue         # Try to create the temp folder @ 19-Dec update   
               if (Test-Path $Folder) {
                   "{0} - I see the folder. Trying to write to a file." -f (get-date)
                   "Test" | Out-File "$Folder\Test.txt"                                  # verify that we can write to the folder 
                   if (Test-Path -Path "$Folder\Test.txt") {
                       "{0} - I see the file!. Ok to proceed. " -f (get-date)
                       remove-item -Path "$Folder\Test.txt"
                        $launch = $true                    # It's ok to run the program 
                   } Else {                  
                       "{0} - File not found. Something is wrong. " -f (get-date)
                   }  
                   $wait = $false
                   continue
               } else {
                   "{0} - I don't see the folder, testing the path." -f (get-date)
                   if (Test-Path $Folder) {
                       "{0} - I see the folder, but not the volume! Trying to write to a file." -f (get-date)
                       "Test" | Out-File "$Folder\Test.txt"                                  # verify that we can write to the folder 
                       if (Test-Path -Path "$Folder\Test.txt") {
                           "{0} - I see the file!. Ok to proceed. " -f (get-date)
                           remove-item -Path "$Folder\Test.txt"
                            $launch = $true                    # It's ok to run the program 
                       } Else {                  
                           "{0} - File not found. Something is wrong. " -f (get-date)
                       }  
                       $wait = $false
                       continue
                   }
               }
           }
           $count++
           if ($count -gt $limit) {
               "{0} - I give up. Here are the volumes that I saw." -f (get-date)
               Get-Volume | Format-Table
               $Wait = $false
               continue
           }
           "{0} - Sleeping, waiting for the {1} drive." -f (get-date), $DriveLetter
           start-sleep -Seconds 60                             # how long do we wait before retry 
       }
       if ($launch) {
           "{0} - Launching the program." -f (get-date)
    
           #------------------------------------------------------------------------------
           # Put your program and any arguments on the next line. 
           #------------------------------------------------------------------------------
           whoami.exe
    
       }
       "{0} - Terminating." -f (get-date)
       Stop-Transcript
    
    0 comments No comments

14 additional answers

Sort by: Most helpful
  1. MotoX80 31,556 Reputation points
    2021-12-09T15:11:50.113+00:00

    If the program works when you test it interactively against the C:\ drive, then it should work when it is run by the task scheduler.

    What account are you running the scheduled task with? A local account? SYSTEM? Your personal account? When you RDP to the server you need to log in with that account to simulate the environment that the task sees.

    In the task trigger settings, set the "Start In (optional)" field to be the current working directory from when you test. The default is system32 so if your program tries to open a file without specifying the directory name it won't find the file.

    When you test, do you open the command prompt with "Run as Administrator"? If you do then on the task settings, you need to check "Run with highest privileges".

    Here is a Powershell script that changes it's priority and then tries to read from C:\temp. Run that with the task scheduler and see if it works.

    Start-Transcript -Path "C:\temp\RamDriveTest.txt"         # This is your log file   
    $me = Get-WmiObject -Query "Select * from Win32_Process where ProcessId = '$pid'"  
    "WMI priority is {0}" -f $me.Priority  
    $rc = $me.SetPriority(32)  
    "Set to normal."  
    $me2 = Get-Process -Id $pid    
    "Get-Process priority is {0}" -f $me2.BasePriority  
    "C:\Temp items is {0}" -f (Get-ChildItem "C:\temp").count  
    start-sleep -Seconds 60     # give the user some time to check the process priority in task manager.   
    Stop-Transcript  
      
    

    If all else fails, trace the program with Process Monitor and verify that the drive/folder it tries to access are the ones that you expect it to.

    https://learn.microsoft.com/en-us/sysinternals/downloads/procmon

    0 comments No comments

  2. 2021-12-10T15:10:07.79+00:00

    I am running multiple of this program with different user account. All accounts are local account member of administrators group.
    I have tested running with different priorities, and write my observations in my first message. Task runs when priority is default but fails when priority is Normal.
    As far as I see, This problem is independent from my computer or my App. Did you test your poweshell script on your computer?


  3. MotoX80 31,556 Reputation points
    2021-12-11T15:53:02.843+00:00

    Let's pause for a moment and review your problem.

    If the task executes properly when you right click and select run, then, all things being equal, it should also work at startup. The priority should not be a factor. But I don't have your program to test with. I don't have the source code to look at. I don't know what that program is doing. I do have a VB.Net program that I wrote to test disk reads and it works fine at startup using the normal priority setting in the task XML definition.

    At startup time, services are initializing. Defender might be doing a scan. So my first reply was to set a delay time to give every service a chance to initialize. If 30 seconds didn't work, well, what about 1 minute? 2 minutes? 5 minutes? Did you try a different amount of time?

    Then you mentioned that you were using a RAM drive. I haven't seen those since the DOS days, but if it works for you, fine. Since you didn't mention how you were creating the RAM drive, the most obvious issue is that the RAM volume has not yet initialized. Or maybe that software is somehow tied to your account or only works when you are logged on. That was why I wrote that script to test for the existence of the drive before it continued. I even put a line for "call your program here".

    Then you replied that it also failed for the C:\ drive. Good. Test with the C:\ drive. That eliminates the RAM drive as being part of the problem.

    this task fails with an IOException, which I see in Event viewer.

    It might help if you share that event data. Did your application generate that event or did Windows? To what drive? To what file?

    Now I can see a new way to solve my problem: . . . programing

    What error handling do you have in the code? Is it failing on the first I/O or some subsequent I/O? Is it doing a read or a write? Does the code create a log file of it's activity? Does it do console.write to display what it's doing so that we can capture stdout and stderr? Does it have a Try/Catch structure to process errors? What error does the program see? What line in the code is getting the error? What does the primary developer say about that statement? Could you be getting a conflict with some other application that is trying to process the same file? Did you run the Process Monitor trace as I mentioned?

    Here is an example of how to capture stdout and stderr. Have the primary developer build you a debug version of the program that writes what it is doing to the console so that you can see where the error is occurring and the details of the error.

    https://learn.microsoft.com/en-us/answers/questions/651656/batch-file-does-delete-files-but-not-work-at-windo.html

    0 comments No comments

  4. 2021-12-12T12:13:30.42+00:00

    I do have a VB.Net program that I wrote to test disk reads and it works fine at startup using the normal priority setting in the task XML definition.

    Thank you, this was the test that I suppose to run in to IOException. I do more tests and I find out: there is another essential condition for happening this problem and that is file location on RAMDrive.
    But, as I has written in previous message:

    The problem I have described is a lab sample of the real problem on our server. On our server the exception rise not when triggers by startup but when executing this command:
    SCHTASKS /Run /TN "SDLAutomation2"
    The exceptions on the server and lab (my local computer) are similar. On the server exception happened even when the storage location was on hard disk.

    that was why I think RAMDrive is not related to this problem. Our real problem on the server is still unsolved and this is it`s log:

    Log Name: Application
    Source: .NET Runtime
    Date: 12/4/2021 3:00:04 AM
    Event ID: 1026
    Task Category: None
    Level: Error
    Keywords: Classic
    User: N/A
    Computer: WIN-HO3M809I83B
    Description:
    Application: SdlAutomation.Console.exe
    Framework Version: v4.0.30319
    Description: The process was terminated due to an unhandled exception.
    Exception Info: System.IO.IOException
    at System.IO.__Error.WinIOError(Int32, System.String)
    at System.IO.FileStream.Init(System.String, System.IO.FileMode, System.IO.FileAccess, Int32, Boolean, System.IO.FileShare, Int32, System.IO.FileOptions, SECURITY_ATTRIBUTES, System.String, Boolean, Boolean, Boolean)
    at System.IO.FileStream..ctor(System.String, System.IO.FileMode, System.IO.FileAccess, System.IO.FileShare, Int32, System.IO.FileOptions, System.String, Boolean, Boolean, Boolean)
    at System.IO.StreamWriter.CreateFile(System.String, Boolean, Boolean)
    at System.IO.StreamWriter..ctor(System.String, Boolean, System.Text.Encoding, Int32, Boolean)
    at System.IO.StreamWriter..ctor(System.String, Boolean)
    at System.IO.File.CreateText(System.String)
    at SdlAutomation.Dos.EnableLogCommand.RunCommand()
    at SdlAutomation.Dos.Program.Main(System.String[])

    0 comments No comments