Unable to register a COM object for usage in a scheduled task

4

I'm trying to create a set of C# classes that I can schedule to run at a future time. The intention is to programmatically schedule these via other parts of my code.

This is the current class I'm trying to call via COM.

using System;
using System.Linq;
using System.Runtime.InteropServices;
using Microsoft.Win32.TaskScheduler;

namespace SchedulableTasks
{
    [Guid("F5CAE94C-BCC7-4304-BEFB-FE1E5D56309A")]
    public class TaskRegistry : ITaskHandler
    {
        private ITaskHandler _taskHandler;
        public void Start(object pHandlerServices, string data)
        {
            var arguments = data.Split('|');
            var taskTypeName = arguments.FirstOrDefault();
            var taskArguments = arguments.Skip(1).FirstOrDefault();
            var taskType = Type.GetType(taskTypeName);
            _taskHandler = (ITaskHandler) Activator.CreateInstance(taskType);
            _taskHandler.Start(pHandlerServices, taskArguments);
        }

        public void Stop(out int pRetCode)
        {
            var retCode = 1;
            _taskHandler?.Stop(out retCode);
            pRetCode = retCode;
        }

        public void Pause()
        {
            _taskHandler.Pause();
        }

        public void Resume()
        {
            _taskHandler.Resume();
        }
    }
}

Here's how I'm attempting to schedule the task

using System;
using Microsoft.Win32.TaskScheduler;
using Newtonsoft.Json;
using Action = Microsoft.Win32.TaskScheduler.Action;

namespace MyProject.Service
{
    public static class SchedulingService
    {
        public enum ScheduledTask
        {
            BillingQuery
        }
        private static readonly Guid RegistryGUI = new Guid("F5CAE94C-BCC7-4304-BEFB-FE1E5D56309A");
        public static void ScheduleAction(string name, string description, Trigger trigger, Action action)
        {
            using (var taskService = new TaskService())
            {
                var task = taskService.NewTask();
                task.RegistrationInfo.Description = description;
                task.Triggers.Add(trigger);
                task.Actions.Add(action);
                taskService.RootFolder.RegisterTaskDefinition(name, task);
            }
        }

        public static Action CreateCSharpAction(ScheduledTask task, object data)
        {
            var taskData = $"{task.ToString()}|{JsonConvert.SerializeObject(data)}";
            return new ComHandlerAction(RegistryGUI, taskData);
        }
    }
}

Microsoft.Win32.TaskScheduler is version 2.7.2 of this library

I can create the scheduled task no problem, but when I attempt to run it, I get a Class not registered (0x80040154).

In my .csproj I'm registering the assembly as a COM object. For the PlatformTarget attribute, I've tried all of AnyCPU, x86, and x64 with the corresponding regasm.exe.

  <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
    <DebugSymbols>true</DebugSymbols>
    <DebugType>full</DebugType>
    <Optimize>false</Optimize>
    <OutputPath>bin\Debug\</OutputPath>
    <DefineConstants>DEBUG;TRACE</DefineConstants>
    <ErrorReport>prompt</ErrorReport>
    <WarningLevel>4</WarningLevel>
    <RegisterForComInterop>true</RegisterForComInterop>
    <PlatformTarget>x86</PlatformTarget>
  </PropertyGroup>

I'm using the following post-build event to register the .dll.

powershell C:\Windows\Microsoft.Net\Framework64\v4*\RegAsm.exe /codebase '$(ProjectDir)$(OutDir)SchedulableTasks.dll'

As near as I can tell, it's properly registered. Registry Screenshot

Procmon.exe seems to report the same. The thing I'm worried about is the "NAME NOT FOUND" for \TreatAs, \InprocHandler and \InprocServer32\InprocServer32 Procmon Screenshot

c#
windows
com
windows-10
registry
asked on Stack Overflow Nov 30, 2017 by Morgan Thrapp • edited Dec 4, 2017 by Morgan Thrapp

1 Answer

1

I think I see your problem:

<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">

Try targeting x86. Please see this answer for an in depth description: How to solve COM Exception Class not registered (Exception from HRESULT: 0x80040154 (REGDB_E_CLASSNOTREG))?

Edit:

I couldn't repro it, I added a few things:

  1. The Attribute [ComVisible(true)]
  2. A Parameterless Constructor
  3. Signed the Assembly
  4. Had to run the powershell command once manually.

enter image description here

answered on Stack Overflow Dec 4, 2017 by Jeremy Thompson • edited Dec 4, 2017 by Jeremy Thompson

User contributions licensed under CC BY-SA 3.0