【问题标题】:Find resources of Class Library from Main Project从主项目中查找类库的资源
【发布时间】:2020-02-09 00:32:26
【问题描述】:

问题

我的解决方案由几个项目组成。 UI 的主要部分我们称之为 Assistant,后端我们称之为 AssistantLib。

结构如下:

在 AssistantLib 中,我将 PDF 作为资源包含在 Resources 文件夹中,Build ActionContentCopy to Output DirectoryCopy Always。通过使用这些组合进行调试时,我可以找到它们:

    private string GetArtifactPath(string artifactName)
    {
        return Path.Combine(GetResourcePath(), artifactName);
    }

    public static string GetResourcePath()
    {
        return Path.Combine(Directory.GetCurrentDirectory(), "Resources");
    }

这行得通。从 GetArtifactPath 返回字符串后,我将使用 Process 对象和 AcroRd32.exe 打开文件。

请注意,我需要通过文件路径引用这些文件。它们不是阅读或流式传输的简单 txt。我还需要能够使用AcroRd32.exe 提供的某些标志打开它们。这意味着我必须有文件路径

我遇到的问题是,一旦我发布 ClickOnce 应用程序,我就会收到找不到文件的错误消息:

Error: Could not find a part of the path 'C:\Users\EL-C\AppData\Local\Apps\2.0\3JCPDD49.7G5\9122AMZE.NZL\azte..tion_edea8654ffceff97_0001.0000_447ed0da08290357\Resources\Guidelines\3.2'.. Stacktrace:    at System.IO.__Error.WinIOError(Int32 errorCode, String maybeFullPath)

当然,当我去那个位置时,资源并不存在。

我的尝试

  • 我已将 Build Action 更改为 Embedded Resource & None - 结果相同
  • 我已将 Copy Output Directory 更改为“请勿复制”
  • This 不适用,因为我无法流式传输这些资源,它们不是简单的文本文件。我也不是要阅读它们,而是要打开它们。
  • This 也不适用,因为在我的情况下引用 MyNamespace.Properties.Resources.My_Zip_File; 不起作用。我事先不知道资源的名称。

更新

我正在研究构建后的事件。在这样做的过程中,我发现这些资源已经在构建之后的输出目录中:

但由于某种原因,它们在我发布时没有出现:

更新 2

为了说明文件夹结构如何影响这一点,这里是之前和之后。

当资源位于 AssistantLib(例如 EVMSBP)时,结构如下:

这是使用 AssistantLib 中的资源安装后 ClickOnce 发布文件夹的样子:

或者,当资源位于 Assistant(同样是 EVMSBP)中时,结构如下:

这是使用Assistant 中的资源安装后 ClickOnce 发布文件夹的样子:

据我所知,资源必须是启动项目的一部分。这听起来很疯狂?

我错过了什么?

【问题讨论】:

  • 不要使用Directory.GetCurrentDirectory()。您不知道哪个目录将是当前。根据项目类型,可以使用AppDomain.CurrentDomain.BaseDirectoryApplication.StartupPathAppContext.BaseDirectoryPath.GetDirectoryName(Assembly.GetExecutingAssembly().Location)等(Environment.CurrentDirectory也不好)
  • 嗨,用户,我知道您的所有 pdf 文件都会在构建操作时被复制到输出目录,对吗?
  • @Clint - 我玩过一些设置。在当前的迭代中,他们这样做了。也许我不完全了解输出目录在哪里?
  • 你的exe所在的目录
  • 是的,看看我的编辑。在构建时,它们被放置在那里;不在 Publish 上,这非常令人沮丧。

标签: c# .net clickonce visual-studio-2019


【解决方案1】:

从编辑中获得更多细节,这就是我复制它的方式

  • AssistLib项目中

    • 资源中的文件 Build ActionEmbedded Resources
    • Output Type: Class Library (AssistLib.dll)

    • Solution Structure


  • AzTech 主项目中
    • 我引用了 AssistLib.dll
    • 检查我要加载的资源 (pdf) 是否存在于 AssistLib.dll 中
    • 加载资源
    • 启动 PDF
    • 到目前为止一切顺利
    • 我发布并安装了应用程序
    • 我从开始菜单上的图标启动了应用程序
    • 启动作为资源嵌入到 DLL 中的 PDF


AzTech.cs

var nameOfTheFile = "test.pdf";
ResourceManager.GetResourceInfo(nameOfTheFile);
if (ResourceManager.resourceExists == false)
{ Console.WriteLine("Specified PDF file not found"); return; }

Console.WriteLine("Resouce found in DLL");
ResourceManager.LoadResource(nameOfTheFile);//Will load the pdf in your main project

Process.Start(nameOfTheFile);

 class ResourceManager
 {
        public static bool resourceExists { get; set; } = false;
        private static Stream resourceStream { get; set; }
        public static void GetResourceInfo(string fileNameWithExtension)
        {
            const string pathToResource = "AssistantLib.Resources.Guidelines";

            var assembly = Assembly.Load("AssistantLib");
            //var names = assembly.GetManifestResourceNames();
            var stream = assembly.GetManifestResourceStream($"{pathToResource}.{fileNameWithExtension}");
            if (stream == null)
                return;

            resourceExists = true;

            resourceStream = stream;

        }

        public static void LoadResource(string newFileNameWithExtension)
        {
            if(File.Exists(newFileNameWithExtension))
            {
                Console.WriteLine("File already exists");
                return;
            }
            using (Stream s = File.Create(newFileNameWithExtension))
            {
                Console.WriteLine("Loading file");
                resourceStream.CopyTo(s);
            }
        }
 }

【讨论】:

  • 嘿@Clint,感谢这篇文章。我不相信路径会导致问题。在您发布的解决方案结构中,资源位于 Startup 项目中。我面临的问题是,当资源在解决方案中的另一个项目中时,AssistantLib 在这种情况下,资源在发布和安装后不会发布。查看我的第二次更新以查看比较图像。
  • @user,所以基本上你想引用 AssistantLib,它包含来自你的主 AssistantProject 的资源。这意味着 AssistantLib 项目会生成一个您将从 MainProject 使用的 DLL,对吗?然后你会发布主项目
  • 嘿,这行得通。使它们成为嵌入式资源,Assembly.Loadassembly.ManifestResourceStream 是关键。感谢您的帮助。
  • 我有一个问题 - 在 /Resources/Guidelines 和 /Resources 中管理资源的最佳方式是什么。或者这是不好的做法?
  • 管理是什么意思,目的是什么?您不想通过嵌入太多不必要的东西来增加资源。另一种嵌入方法是导航到 Visual Studio > Project > Properties > Resource 。您也可以通过这种方式添加资源。
【解决方案2】:

当我使用 Visual Studio 设置以 exe 格式构建项目时,我遇到了同样的问题,我在项目构建输出目录中简单地添加了 pdf 文件。您必须将您的 pdf 文件夹复制到 binrelease 文件夹并使用 ~ 根目录来获取文件

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-12
    • 2011-07-02
    • 2022-11-24
    • 1970-01-01
    相关资源
    最近更新 更多