dahall / TaskScheduler

Provides a .NET wrapper for the Windows Task Scheduler. It aggregates the multiple versions, provides an editor and allows for localization.
MIT License
1.22k stars 192 forks source link

Winform application closes when we edit task scheduler editor. #810

Closed AntoniPancras closed 5 years ago

AntoniPancras commented 5 years ago

Dear Team, We are using version 2.8.11 of task scheduler DLLS ( Microsoft.Win32.TaskScheduler.dll and Microsoft.Win32.TaskSchedulerEditor.dll ) in our product. Our application is Winform application targeted to .NET framework version 4.6.

Our application closes suddenly when we play ( i.e just clicking on different tabs multiple times. ) around with windows scheduler editor. This is happening in only windows 10 operating system.

Could you please advice us to fix this issue ?

Thanks Antoni

dahall commented 5 years ago

Can you provide more information about the Win10 version and maybe which tab click causes the exception? It would also help to know what settings the task has.

AntoniPancras commented 5 years ago

Hi . Thanks for the reply there is no particular fixed scenario or settings so that we can mention here . We get the exception after clicking on any tabs . But it happens within 2-3 minutes.

We have seen this issue in Windows 10 64 bit Enterprise Edition .

Thanks Antoni

Thanks Antoni

dahall commented 5 years ago

I have tested on WIn10 Build 1803 and cannot reproduce. A few questions:

  1. Does this happen with a particular task or will any task cause the problem? a. If with a particular path, please provide the extracted XML for the task.
  2. Does this happen on a single system or can you reproduce on multiple systems? a. Please provide the build (1803, 1809, etc.) for each non-functional system.
  3. Does this occur after clicking one tab in particular?
  4. How many tabs are clicked before the error?
  5. Does the application throw an exception? a. Please provide.
AntoniPancras commented 5 years ago

Hi , Please find our Reply below..

  1. Does this happen with a particular task or will any task cause the problem? a. If with a particular path, please provide the extracted XML for the task. [Antoni] issue occurs for all tasks

  2. Does this happen on a single system or can you reproduce on multiple systems? a. Please provide the build (1803, 1809, etc.) for each non-functional system. We have verified in Microsoft windows 10 Enterprise Build 17763

  3. Does this occur after clicking one tab in particular? Yes. We could see the issue with the change in "Edit Trigger" page in Trigger tab. a. Check/Uncheck "Synchronous across time zones" b. Check/Uncheck Expire checkbox and change the date When we click OK button the crash occurs.

How many tabs are clicked before the error? It is random behavior.

Does the application throw an exception? a. Please provide. In Event Viewer We could see " Faulting module name : User32.dll"

Thanks Antoni

dahall commented 5 years ago

I have run this on Win10 build 17764 with version 2.8.11 of the libraries. I built a task with every trigger type and displayed it in the editor. I then ran a test script that would cycle through the tabs 100 times and then open each time task and change the date and check the time zone sync box and then save the trigger. I have run the script 3 times without any error. Is this happening on a single system or multiple? I have seen instances where a library doesn't get updated during a Win10 upgrade and it causes random UI failures.

AntoniPancras commented 5 years ago

Hi ,

We have debugged the source code in Windows 10 and identified that the exception occurs in the code taskEditDialog.ShowDialog(); of showProperties() method.

We get below exception: System.AccessViolationException: 'Attempted to read or write protected memory. This is often a indication that other memory is corrupt'

Please le me know if you need any more details from me.

  private void showProperties()
  {
     //Open the properties of the currently selected task
     if (listBox1.SelectedItem != null)
     {            
         Microsoft.Win32.TaskScheduler.Task currentTask = GetSelectedTask();
            if (currentTask != null)
            {
                using (TaskService ts = new TaskService())
                {
                    string taskName = currentTask.Name;
                    var taskEditDialog = new TaskEditDialog(ts.GetTask(taskName)) { AvailableTabs = AvailableTaskTabs.General 
                        | AvailableTaskTabs.Triggers | AvailableTaskTabs.Actions | AvailableTaskTabs.Conditions 
                        | AvailableTaskTabs.Settings | AvailableTaskTabs.RunTimes };

                    taskEditDialog.ShowDialog();

                    currentTask.Dispose();

                }
            }          
     }
  }

The showProperties() method calls GetSelectedTask() method which returns the task object from the TaskCollection . Actually all tasks are listed in a Listbox . The GetSelectedTask() method return the task object of user selected task object from the Listbox .

Please note , our application is Winform application targeted to .NET framework 4.6.

Thanks Antoni

dahall commented 5 years ago

Unfortunately, your debugging didn't give me any further insight into what section of code is being called. There are almost 10,000 lines of code for the TaskEditDialog so I need to narrow it down. When you get the AccessViolationException, is there anyway to get the internal stack from its properties?

Two notes on your code: 1) You can pass currentTask directly as the first parameter of TaskEditDialog without calling GetTask. 2) Very important: You should not have instances of tasks outside of the TaskService instance. If this program only operates on the local machine in the user's context, then just use TaskService.Instance and don't construct new instances of TaskService. If you are connecting remotely, then store a singleton instance of TaskService as a global and use it each time. You use of the using keyword will dispose the TaskService instance which is needed for a number of aspects of the library.

AntoniPancras commented 5 years ago

Hi , We have done the code changes ..Still we see the issue..Please let me know if anything is wrong.

 private void showProperties()
 {
         //Open the properties of the currently selected task
         if (listBox1.SelectedItem != null)
         {
               Microsoft.Win32.TaskScheduler.Task currentTask = GetSelectedTask();
               taskEditDialog = new TaskEditDialog(currentTask) {
                      AvailableTabs = AvailableTaskTabs.General | AvailableTaskTabs.Triggers |
                      AvailableTaskTabs.Actions | AvailableTaskTabs.Conditions | AvailableTaskTabs.Settings | 
                      AvailableTaskTabs.RunTimes };
                taskEditDialog.ShowDialog();
                if (!disposed)
                      RefreshList();
        }
}

ThanksAntoni

AntoniPancras commented 5 years ago

Hi, Thank you very much for the support Please find the traces below. Hope this helps

Scenario 1: When we set the expiry date to previous date and click the OK button, the Edit Trigger page closes. Then if click OK button then we get below error message

Exception Message:
(12,52):EndBoundary:2019-05-07T16:06:38.008+05:30
Stack Trace:
at Microsoft.Win32.TaskScheduler.V2Interop.ITaskFolder.RegisterTaskDefinition(String Path, ITaskDefinition pDefinition, Int32 flags, Object UserId, Object password, TaskLogonType LogonType, Object sddl) at Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String Path, TaskDefinition definition, TaskCreation createType, String UserId, String password, TaskLogonType LogonType, String sddl) at Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String Path, TaskDefinition definition) at Microsoft.Win32.TaskScheduler.Task.RegisterChanges() at Microsoft.Win32.TaskScheduler.TaskEditDialog.okBtn_Click(Object sender, EventArgs e) at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Scenario 2: When we click OK button of "Conditions" tab then click OK button , we get below error message

Exception Message:
Task names ending with a period followed by three or fewer characters cannot be retrieved due to a bug in the native library. Parameter name: path
Stack Trace:
at Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String path, TaskDefinition definition, TaskCreation createType, String userId, String password, TaskLogonType logonType, String sddl) at Microsoft.Win32.TaskScheduler.Task.RegisterChanges() at Microsoft.Win32.TaskScheduler.TaskEditDialog.okBtn_Click(Object sender, EventArgs e) at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Thanks Antoni

dahall commented 5 years ago

First, do not use a using on TaskService.Instance. You also do not need to dispose currentTask. See corrected code above.

On Scenario 1, the problem is not random. It is that the user intentionally selected an expiration date that precedes today's date or the start time date for the trigger. This condition is not allowed by the native Task Scheduler.

On Scenario 2, your problem is in the exception. Task names ending with a period followed by three or fewer characters cannot be retrieved due to a bug in the native library.

dahall commented 5 years ago

However, on Scenario 1, I do believe I can prevent that condition in the UI. I'll make those changes.

dahall commented 5 years ago

Changes have been made, tested and pushed for Scenario 1.

AntoniPancras commented 5 years ago

Hi , Thanks for your quick reply on this. We have taken the latest source code and confirm that the Scenario 1 is resolved now. thank you.

Scenario 2: We are working on this issue. Actually our task names are OPC Data Logger Trigger_01.job, OPC Data Logger Trigger_02.job , OPC Data Logger Trigger_03.job etc... Do you see any problem in the task name? Please advice.

Thanks Antoni

dahall commented 5 years ago

Yes. The .job extension has a conflict with the way the WinXP version of Task Scheduler named files containing the job info. I would suggest omitting it or changing it to _Job.

AntoniPancras commented 5 years ago

Hi , We have changed the task name as per suggestion ( "." is replaced by "_" ) Now we get "Object reference not set to an instance of an object." error message . Please see the traces below and let us know if we are missing something

Object reference not set to an instance of an object.
Stack Trace:
at Microsoft.Win32.TaskScheduler.TaskFolder.RegisterTaskDefinition(String path, TaskDefinition definition, TaskCreation createType, String userId, String password, TaskLogonType logonType, String sddl) at Microsoft.Win32.TaskScheduler.Task.RegisterChanges() at Microsoft.Win32.TaskScheduler.TaskEditDialog.okBtn_Click(Object sender, EventArgs e) in E:\Antoni\DataLogger\Version 3.7.0.00\DownLoad_13June2019\TaskScheduler-master\TaskEditor\TaskEditDialog.cs:line 378 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.OnMessage(Message& m) at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m) at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

Thanks Antoni

dahall commented 5 years ago

Unfortunately this trace doesn't give me any information to diagnose the problem. Do you happen to have the original values of the task and know which were changed before pressing OK?

AntoniPancras commented 5 years ago

Hi, Thanks for the quick reply . I appreciate it. We have created a sample application which will demonstrate the issue. We herewith attach the solution Scheduler.zip.

This sample application was developed using Visual Studio 2017 .

Steps to reproduce the issue on Windows 10

  1. Click on 'Add task' button
  2. New Task will be created and displayed in the Listbox
  3. Double click on the task displayed in the listbox
  4. Task editor dialog opens
  5. Click on 'Run Times' tab . You will see "Object reference not set to an instance of an object"
  6. Click on "setting" tab, the application closes

Scheduler.zip

Please let me know if there is anything i can do to help on this.

Thanks Antoni

dahall commented 5 years ago

Do you run the sample "As Administrator"?

dahall commented 5 years ago

I've just run your compiled code in the sample under Win10 1903 (build 18362) and 1803 (build 17134) as Administrator and could not reproduce the error following the steps you outlined. Are you running this under a certain language?

AntoniPancras commented 5 years ago

Hi , Thanks for the mail. We herewith attach the sample application which refers the scheduler DLLs version 2.8.11 ( Downloaded from Nuget package ) . We have also attached the screen recording video which demonstrates the issue. We have tested in Windows 10 version 1803 build 17134 .

Scheduler_Sample.zip Screen Recording.zip

Thanks Antoni

dahall commented 5 years ago

The error at 0:22 in the video comes from the same problem I pointed out above: Once you create a task with TaskService instance, you cannot dispose that instance before disposing the task. Please go through all your code, checking for using statements that dispose a TaskService instance and remove them. Create a single TaskService instance and use it globally OR just always use the TaskService.Instance static property and NEVER put it in a using condition. Your sample Form1.cs code has it sprinkled everywhere, so I'm assuming your base code does as well.

dahall commented 5 years ago

I have pushed version 2.8.12 which includes in the EndBoundary checking and some code to ensure that even accidental disposal of TaskService.Instance doesn't break the code. Hopefully these two additions, along with the suggestions from my last post, will fix your problem.

I also went out and changed all the sample code in the Wiki to use TaskService.Instance so as to avoid confusion about its use.