Как получить потоковый объект из файла ресурсов (Консольное приложение / Проект службы Windows) - PullRequest
9 голосов
/ 13 октября 2011

Я создаю службу Windows и пытаюсь получить доступ к некоторым файлам, добавленным в файл ресурсов, но застрял, потому что не знаю, как получить доступ к отдельным файлам. Просто для справки, вот что я сделал до сих пор:

  • Это приложение службы Windows C #, работающее в режиме отладки как консольное приложение, которое помогает мне войти в код.

  • Я добавил файл ресурсов в корень с именем «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» [1] Строка "MicroSecurity.EmailService.Resources.resources"

Из этого я определил, что «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?

UPDATE:

Благодаря Андрею я смог понять это. Ниже приведен код, который я написал для демонстрационного проекта, чтобы изучить, как работает файл ресурсов, а не встраивать файлы напрямую. Я надеюсь, что это поможет другим прояснить различия.

using System;
using System.Drawing;
using System.IO;
using System.Reflection;

namespace UsingResourceFiles
{
    public class Program
    {
        /// <summary>
        /// Enum to indicate what type of file a resource is.
        /// </summary>
        public enum FileType
        {
            /// <summary>
            /// The resource is an image.
            /// </summary>
            Image,

            /// <summary>
            /// The resource is something other than an image or text file.
            /// </summary>
            Other,

            /// <summary>
            /// The resource is a text file.
            /// </summary>
            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 (e.g. "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;
        }

        /// <summary>
        /// This method allows you to specify the dot file path and type of the resource file and return it in its native format.
        /// </summary>
        /// <param name="dotFilePath">The file path with dots instead of backslashes. e.g. Images.zombie.gif instead of Images\zombie.gif</param>
        /// <param name="fileType">The type of file the resource is.</param>
        /// <returns>Returns the resource in its native format.</returns>
        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;
            }
        }

        /// <summary>
        /// This method allows you to specify the dot file path and type of the resource file and return it in its native format.
        /// </summary>
        /// <param name="dotFilePath">The file path with dots instead of backslashes. e.g. Images.zombie.gif instead of Images\zombie.gif</param>
        /// <param name="fileType">The type of file the resource is.</param>
        /// <param name="useNativeFormat">Indicates that the resource is to be returned as resource's native format or as a stream.</param>
        /// <returns>When "useNativeFormat" is true, returns the resource in its native format. Otherwise it returns the resource as a stream.</returns>
        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;
            }
        }
    }
}

Ответы [ 3 ]

10 голосов
/ 14 октября 2011

Если вы установите для файлов в папке «Ресурсы» значение «Встроенный ресурс», то вы должны были увидеть его в списке в вызове GetManifestResourceNames ().Вы можете попробовать

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

Имя должно быть «MicroSecurity.EmailService.Resources.logo.jpg», если оно находится в папке «Ресурсы».Однако пометка самого файла как встроенного ресурса отрицательно сказывается на назначении файла ресурсов (само изображение будет встроено дважды).

Вы можете полностью удалить файл ресурсов и установить каждый файл как встроенный ресурс.На этом этапе должны быть отдельные ресурсы манифеста для каждого файла.В проекте C # каждому имени файла будет предшествовать пространство имен проекта + подпапка.Например.если вы добавите файл «logo.jpg» в папку Resources / Embedded, именем ресурса будет «MicroSecurity.EmailService.Resources.Embedded.logo.jpg».

В качестве альтернативы получите растровое изображение из ресурсовфайл и преобразовать его в поток.Вы можете найти пример преобразования Bitmap в MemoryStream в Как преобразовать растровое изображение в байт []?

1 голос
/ 13 октября 2011

Можете ли вы использовать:

System.Drawing.Bitmap myLogo = MicroSecurity.Properties.Resources.logo;
0 голосов
/ 07 июня 2018
public static readonly Func<string, object> 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");
...