C# 无法注册COM对象以在计划任务中使用

C# 无法注册COM对象以在计划任务中使用,c#,windows,com,windows-10,registry,C#,Windows,Com,Windows 10,Registry,我正在尝试创建一组C#类,可以安排在将来运行。目的是通过我的代码的其他部分以编程方式安排这些 这是我试图通过COM调用的当前类 using System; using System.Linq; using System.Runtime.InteropServices; using Microsoft.Win32.TaskScheduler; namespace SchedulableTasks { [Guid("F5CAE94C-BCC7-4304-BEFB-FE1E5D56309A"

我正在尝试创建一组C#类,可以安排在将来运行。目的是通过我的代码的其他部分以编程方式安排这些

这是我试图通过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();
        }
    }
}
下面是我如何安排任务的

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
是的2.7.2版

我可以毫无问题地创建计划任务,但是当我尝试运行它时,我得到一个未注册的
类(0x80040154)

在my.csproj中,我将程序集注册为COM对象。 对于
PlatformTarget
属性,我使用相应的
regasm.exe
尝试了所有
AnyCPU
x86
x64

  <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>
据我所知,它是正确注册的。

Procmon.exe似乎也报告了同样的情况。我担心的是
\TreatAs
\InprocHandler
\InprocServer32\InprocServer32

我想我看到了你的问题:

尝试瞄准x86。请参阅此答案以了解详细说明:

编辑:

我无法重新编程,我添加了一些内容:

  • 属性
    [ComVisible(true)]
  • 无参数构造函数
  • 大会签字
  • 必须手动运行powershell命令一次

  • Nope,即使将
    AnyCPU
    更改为
    x86
    我仍然会收到相同的错误。我还希望将其注册为x64 DLL,因为我的其余代码是64位的。我如何重新编程?您错过了任务服务的定义。我是否只需要创建一个带有
    TaskRegistry
    的类库(Full.Net),然后引用并实例化它?
    TaskService
    来自。是的,我在他们自己的项目中有两个文件。我有
    TaskRegistry
    引用的单个任务定义,但是从
    ITaskHandler
    继承的任何东西都可以工作。我不在乎它是否在调用
    TaskRegistry.Start
    后立即崩溃。这两个项目都是根据4.6.2编写的。我参考了David Halls图书馆,目标是4.6.1,你否决了我吗?请提供一个?我仍然有一些问题与类没有注册。明天我将尝试提出更深入的MCVE。不,不是我。我不明白TaskRegistration类想做什么。它应该执行任务,而不是试图一意孤行。也许这是一个有意的额外间接操作,但诊断是任何“BillingQuery”都没有正确注册。尽管这不应引发此异常,因为它已由Activator.CreateInstance()创建。嗯,只要执行任务。@HansPassant的想法是允许我只注册一个类,但根据调用方将它分派到不同的类。所以,我可能有一个类调用我们API的一部分,或者另一个类启动服务器,或者发送电子邮件,等等。好吧,为什么要使用ITaskHandler呢??为什么“BillingQuery”还要实现它?您已经获得了.NET反射的好处,并且已经为它创建了对象。只需按原样使用它,而不要求它[ComVisible(true)],也不要求任务调度器知道它。当然不是,所以是例外。只需声明一个C#接口,给它一个Start(字符串数据)方法。实现暂停和恢复是可选的,在实践中肯定不容易实现。考虑一个CopyTaleToCuto停止。不幸的是,TaskSt调器库需要<代码> ITaskHunter-<代码>。我同意这似乎是一个奇怪的要求。它是必需的,这就是运行TaskRegistry.Start()方法的原因。它工作了,完成了任务,现在它需要实际执行任务。但事实并非如此,它再次尝试调用ITaskHandler::Start()。周围没人照顾那个。请注意,TaskRegistry类名错误,应为TaskHandler。它需要处理这个任务。
    powershell C:\Windows\Microsoft.Net\Framework64\v4*\RegAsm.exe /codebase '$(ProjectDir)$(OutDir)SchedulableTasks.dll'