如何从资源文件中获取流对象(控制台应用程序/ Windows服务项目)

我正在创建一个Windows服务,我正在尝试访问我添加到资源文件中的一些文件,但我被卡住了,因为我不知道如何访问单个文件。 仅仅为了一些背景信息,这是我到目前为止所做的:

  • 这是一个在调试模式下作为控制台应用程序运行的C#Windows服务应用程序,它可以帮助我进入代码。

  • 我在根目录中添加了一个名为“Resources.resx”的资源文件。

  • 在我的资源文件中,我使用可视化设计器/编辑器添加了一些jpg图像和html文件。

  • 在我将图像和html文件添加到资源文件后,我项目中的一个新文件夹显示为“Resources”,其中包含我添加的所有文件。

  • 在这个新文件夹中,我转到了每个文件的属性,并将Build Action更改为Embedded Resource。 (我不知道这是否有必要。我搜索的一些博客说要试试。)

  • 项目的名称空间称为“MicroSecurity.EmailService”。

  • 为了获取资源文件的名称,我使用了

    的GetType()。Assembly.GetManifestResourceNames()

我得到以下内容

GetType()。Assembly.GetManifestResourceNames(){string [2]} string [] [0]“MicroSecurity.EmailService.Services.EmailService.resources”string [1]“MicroSecurity.EmailService.Resources.resources”string

从此我发现“MicroSecurity.EmailService.Resources.resources”是我想要使用的字符串(索引1)。

  • 我使用此代码来获取流对象。

    var stream = Assembly.GetExecutingAssembly()。GetManifestResourceStream(“MicroSecurity.EmailService.Resources.resources”);

当我在调试期间向此变量添加监视时,我可以看到诸如图像的元数据之类的内容等。

这是我被困的地方。 我想访问名为“logo.jpg”的图像。 这是我正在做的图像,但它不起作用。

var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MicroSecurity.EmailService.Resources.resources.logo.jpg"); 

如何从logo.jpg文件中获取流?

更新:

感谢安德鲁,我能够弄清楚。 下面是我为演示项目编写的一些代码,以便研究资源文件如何工作而不是直接嵌入文件。 我希望这有助于其他人澄清差异。

 using System; using System.Drawing; using System.IO; using System.Reflection; namespace UsingResourceFiles { public class Program { ///  /// Enum to indicate what type of file a resource is. ///  public enum FileType { ///  /// The resource is an image. ///  Image, ///  /// The resource is something other than an image or text file. ///  Other, ///  /// The resource is a text file. ///  Text, } public static void Main(string[] args) { // There are two ways to reference resource files: // 1. Use embedded objects. // 2. Use a resource file. // Get the embedded resource files in the Images and Text folders. UseEmbeddedObjects(); // Get the embedded resource files in the Images and Text folders. This allows for dynamic typing // so the resource file can be returned either as a stream or an object in its native format. UseEmbeddedObjectsViaGetResource(); // Use the zombie.gif and TextFile.txt in the Resources.resx file. UseResourceFile(); } public static void UseEmbeddedObjects() { // ============================================================================================================================= // // -=[ Embedded Objects ]=- // // This way is the easiest to accomplish. You simply add a file to your project in the directory of your choice and then // right-click the file and change the "Build Action" to "Embedded Resource". When you reference the file, it will be as an // unmanaged stream. In order to access the stream, you'll need to use the GetManifestResourceStream() method. This method needs // the name of the file in order to open it. The name is in the following format: // // Namespace + Folder Path + File Name // // For example, in this project the namespace is "UsingResourceFiles", the folder path is "Images" and the file name is // "zombie.gif". The string is "UsingResourceFiles.Images.zombie.gif". // // For images, once the image is in a stream, you'll have to convert it into a Bitmap object in order to use it as an Image // object. For text, you'll need to use a StreamReader to get the text file's text. // ============================================================================================================================= var imageStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("UsingResourceFiles.Images.zombie.gif"); var image = new Bitmap(imageStream); var textStream = Assembly.GetExecutingAssembly().GetManifestResourceStream("UsingResourceFiles.Text.TextFile.txt"); var text = new StreamReader(textStream).ReadToEnd(); } public static void UseEmbeddedObjectsViaGetResource() { // ============================================================================================================================= // // -=[ Embedded Objects Using GetResource() ]=- // // Using the overloaded GetResource() method, you can easily obtain an embedded resource file by specifying the dot file path // and type. If you need the stream version of the file, pass in false to the useNativeFormat argument. If you use the // GetResource() method outside of this file and are getting a null value back, make sure you set the resource's "Build Action" // to "Embedded Resource". // ============================================================================================================================= // Use the GetResource() methods to obtain the Images\zombie.gif file and the text from the Text\TextFile.txt file. Bitmap image = GetResource("Images.zombie.gif", FileType.Image); Stream imageStream = GetResource("Images.zombie.gif", FileType.Image, false); string text = GetResource("Text.TextFile.txt", FileType.Text); Stream textStream = GetResource("Text.TextFile.txt", FileType.Text, false); } public static void UseResourceFile() { // ============================================================================================================================= // // -=[ Resource File ]=- // // This way takes more upfront work, but referencing the files is easier in the code-behind. One drawback to this approach is // that there is no way to organize your files in a folder structure; everything is stuffed into a single resource blob. // Another drawback is that once you create the resource file and add any files to it, a folder with the same name as your // resource file is created, creating clutter in your project. A final drawback is that the properties of the Resources object // may not follow proper C# naming conventions (eg "Resources.funny_man" instead of "Resources.FunnyMan"). A plus for using // resource files is that they allow for localization. However, if you're only going to use the resource file for storing files, // using the files as embedded objects is a better approach in my opinion. // ============================================================================================================================= // The Resources object references the resource file called "Resources.resx". // Images come back as Bitmap objects and text files come back as string objects. var image = Resources.zombie; var text = Resources.TextFile; } ///  /// This method allows you to specify the dot file path and type of the resource file and return it in its native format. ///  /// The file path with dots instead of backslashes. eg Images.zombie.gif instead of Images\zombie.gif /// The type of file the resource is. /// Returns the resource in its native format. public static dynamic GetResource(string dotFilePath, FileType fileType) { try { var assembly = Assembly.GetExecutingAssembly(); var assemblyName = assembly.GetName().Name; var stream = assembly.GetManifestResourceStream(assemblyName + "." + dotFilePath); switch (fileType) { case FileType.Image: return new Bitmap(stream); case FileType.Text: return new StreamReader(stream).ReadToEnd(); default: return stream; } } catch (Exception e) { Console.WriteLine(e); return null; } } ///  /// This method allows you to specify the dot file path and type of the resource file and return it in its native format. ///  /// The file path with dots instead of backslashes. eg Images.zombie.gif instead of Images\zombie.gif /// The type of file the resource is. /// Indicates that the resource is to be returned as resource's native format or as a stream. /// When "useNativeFormat" is true, returns the resource in its native format. Otherwise it returns the resource as a stream. public static dynamic GetResource(string dotFilePath, FileType fileType, bool useNativeFormat) { try { if (useNativeFormat) { return GetResource(dotFilePath, fileType); } var assembly = Assembly.GetExecutingAssembly(); var assemblyName = assembly.GetName().Name; return assembly.GetManifestResourceStream(assemblyName + "." + dotFilePath); } catch (Exception e) { Console.WriteLine(e); return null; } } } } 

如果将Resources文件夹中的文件设置为Embedded Resource,那么您应该已经在GetManifestResourceNames()调用中看到它。 你可以试试

 var stream = Assembly.GetExecutingAssembly().GetManifestResourceStream("MicroSecurity.EmailService.Resources.logo.jpg"); 

如果名称在Resources文件夹中,则名称应为“MicroSecurity.EmailService.Resources.logo.jpg”。 但是,将文件本身标记为嵌入式资源会破坏资源文件的目的(图像本身将嵌入两次)。

您可以完全删除资源文件,并将每个文件设置为嵌入式资源。 此时,每个文件应该有单独的清单资源。 在C#项目中,每个文件名都将以项目命名空间+子文件夹为前缀。 例如。 如果在Resources / Embedded文件夹中添加“logo.jpg”文件,则资源名称为“MicroSecurity.EmailService.Resources.Embedded.logo.jpg”。

或者,从Resources文件中获取位图并将其转换为流。 您可以在如何将位图转换为byte []中找到将Bitmap转换为MemoryStream的示例?

你能用:

 System.Drawing.Bitmap myLogo = MicroSecurity.Properties.Resources.logo; 
 public static readonly Func GetDataByType = (path) => { var fromStream = Assembly.GetExecutingAssembly().GetManifestResourceStream(path); var formatter = new BinaryFormatter(); if (fromStream != null) { var obj = formatter.Deserialize(fromStream); fromStream.Close(); return obj; } return null; }; var test GetDataByType("Resources.logo");