c# 控制台应用程序 Microsoft.Win32.TaskScheduler.dll FileNotFoundException on Deployment

c# Console Application Microsoft.Win32.TaskScheduler.dll FileNotFoundException on Deployment

我有一个应用程序,由于其性质,需要在下班后运行,以免打断用户的工作流程。根据另一个问题的建议,我已经下载并添加了对 Microsoft.Win32.TaskScheduler.dll 的引用,该问题是关于当天晚些时候将任务安排到 运行 的最佳方式。

在调试中,程序按预期工作,但是在部署时,出现以下错误:

Unhandled Exception: System.IO.FileNotFoundException: Could not load file or assembly 'Microsoft.Win32.TaskScheduler, Version=2.5.16.0, Culture=neutral, PublicKeyToken=0d013ddd5178a2ae' or one of its dependencies.

这让我相信 dll 在构建时没有正确添加到可执行文件中。

我已采取的解决此问题的步骤:

  1. 在解决方案资源管理器中,确保 Microsoft.Win32.TaskScheduler 复制本地 属性 是 True
  2. 项目属性,发布,应用程序文件 - Microsoft.Win32.TaskScheduler.dll 包含在发布中,需要下载,包含哈希
  3. 移除依赖并重新添加
  4. 遵循了this answer
  5. 中的建议

在这一点上,所有人都失败了。我可以确认 .dll 位于 /bin/debug 文件夹中。此外,我以相同的方式手动添加了 System.Management.Automation,它似乎按预期运行。

如果有人有任何其他建议,我们将不胜感激。

我曾尝试使用derpirscher的解决方案,但我最终使用的解决方案是将dll部署到程序的运行ning目录。这不是最优雅的解决方案,但它满足 "single file deployment" 要求。但是,应该注意的是,在部署到的所有系统上,用户帐户都是管理员。如果程序 运行s 所在的用户不是管理员,则此解决方案可能不起作用,具体取决于可执行文件来自 运行 的位置(例如,另一个用户的帐户文件夹)。

class Program
{
    //Deploys the DLL to the location of the executable, as suggested by B. Clay Shannon
    //The Program() method runs before Main() and allows for regisration or placement
    //of files before the program "starts". Placing this line in Main()
    //causes a FileNotFound exception when it tries to register the assembly.
    static Program()
    {
        //The dll has been added as a resource, build action "Content".
        //Note the underscores in "Microsoft_Win32_TaskScheduler"
        //Adding the dll to the resource manager replaces '.' with '_' in the resource name
        File.WriteAllBytes(string.Format("{0}{1}", Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location), "\Microsoft.Win32.TaskScheduler.dll"), FindResourceByName("Microsoft_Win32_TaskScheduler"));
    }

    static void Main(string[] args)
    {
        ...
    }

    /// <summary>
    ///   Returns a byte array of the object searched for
    /// </summary>
    /// <param name="objectName">Name of the resource object</param>
    /// <returns>Byte array of the specified resource object</returns>
    private static byte[] FindResourceByName(string objectName)
    {
        object obj = Properties.Resources.ResourceManager.GetObject(objectName);
        return ((byte[])(obj));
    }
}