Распутывание путаницы со встроенными ресурсами

РЕДАКТИРОВАТЬ: Прочтите ответ номер 1 от Тима Шмелтера, а затем используйте этот вопрос для примеров того, как встраивать ресурсы и получать к ним доступ во время выполнения.

Тема встроенных ресурсов поднимается часто, особенно когда люди спрашивают, как получить доступ к встроенным файлам во время выполнения. Ситуация становится еще более запутанной, потому что Visual Studio дает вам два разных способа встраивания ресурса и разные способы доступа к этим ресурсам во время выполнения. Проблема в том, что в зависимости от того, какой метод вы использовали для встраивания ресурса, метод, который вы пытаетесь использовать для доступа к файлу во время выполнения, может не работать.Этот пост представляет собой попытку прояснить всю путаницу, которую я вижу, но у меня также есть вопрос, на который никто не может ответить фактически: почему размер моей скомпилированной программы В ДВАЖДЫ больше размера встроенного ресурса (иногда)? Например, если я встраиваю в свой проект файл размером 20 МБ, почему моя программа компилируется до 40 МБ? Я задавал этот вопрос раньше, и никто не смог воспроизвести мои результаты. Я обнаружил, что причина, по которой они не смогли воспроизвести, заключалась в том, что они встраивали файл другим способом. См. Здесь:

Метод 1:

Дважды щелкните «Мой проект», чтобы открыть страницы свойств и перейти на вкладку «Ресурсы». Теперь нажмите Добавить ресурс> Добавить существующий файл. Найдите файл, который хотите встроить. В этом примере я использую исполняемый файл. Теперь вы увидите свой файл на вкладке «Ресурсы»:

enter image description here

Вы также увидите, что папка с именем «Ресурсы» была создана в рамках вашего проекта, а встроенный файл был помещен в эту папку:

enter image description here

РЕДАКТИРОВАТЬ: ЭТОТ СЛЕДУЮЩИЙ ШАГ БЫЛ ПРОБЛЕМОЙ . ВЫКЛЮЧАЕТСЯ, ЧТО ПРИ ДОБАВЛЕНИИ ФАЙЛА ЧЕРЕЗ ВКЛАДКУ РЕСУРСОВ ВЫ ДОЛЖНЫ НЕ УСТАНОВИТЬ ДЕЙСТВИЕ НА ВСТРОЕННЫЙ РЕСУРС. Счетчик интуитивно мягко говоря!

Теперь, когда файл выбран, посмотрите на окно свойств файла и измените действие сборки на Embedded Resource: (этот шаг должен выполняться ТОЛЬКО при добавлении файла с помощью метода 2).

enter image description here

Теперь скомпилируйте вашу программу. Вы увидите, что размер вашей скомпилированной программы как минимум вдвое превышает размер вашего встроенного ресурса. Этого не происходит с методом 2.См. Здесь:

Метод 2:

Щелкните правой кнопкой мыши имя проекта и выберите «Добавить»> «Существующий элемент». Перейдите к своему файлу, и на этот раз вы заметите, что, хотя он действительно был помещен в ваш проект, папка ресурсов не была создана:

enter image description here

Теперь еще раз выберите файл и измените действие сборки на встроенный ресурс и скомпилируйте. На этот раз размер скомпилированной программы будет таким, как вы ожидали - примерно размером встроенного файла, а не вдвое больше, чем в случае метода 1.

Какой метод вы используете для встраивания файла, определит, какой метод вы можете использовать для этого. получить доступ к файлу во время выполнения. Для метода 1 это очень просто, все, что вам нужно сделать, это:

My.Computer.FileSystem.WriteAllBytes(Path, My.Resources.ResourceName, Append)

Где Path - это расположение и имя файла, который вы хотите сохранить на жестком диске, ResourceName - это имя встроенного ресурса, который вы видите в проекте. window (без расширения), а Append - хотите ли вы создать новый файл или перезаписать существующий файл. Так, например, используя test.exe из приведенных выше изображений, я мог бы сохранить этот файл на диск C следующим образом:

My.Computer.FileSystem.WriteAllBytes(“C:\test.exe”, My.Resources.test, False)

Что может быть проще.

Метод 2, однако, не дает вам доступа к My.Resources, поэтому он становится немного сложнее. Вы должны создать поток для хранения ресурса, поместить поток в массив байтов, а затем записать байты в файловую систему. Самый простой способ, который я нашел для этого, выглядит следующим образом:

Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(Project.ResourceName)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(OutputFile, bytes)
End Using

В этом методе ResourceName должен содержать расширение файла И имя проекта, поэтому, используя наш пример, приведенный выше, мы можем просто сделать:

Using s As Stream = Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.exe)
Dim bytes(s.Length) As Byte
s.Read(bytes, 0, bytes.Length)
File.WriteAllBytes(“C:\test.exe”, bytes)
End Using

Текстовые файлы немного отличаются :

Dim output As String
Using sr As StreamReader = New StreamReader(Assembly.GetExecutingAssembly().GetManifestResourceStream(WindowsApplication1.test.txt))
output = sr.ReadToEnd()
End Using

Using sw As StreamWriter = New StreamWriter(“C:\test.txt”)
sw.Write(output)
End Using

Я боролся с этим в прошлом, надеюсь, это кому-то поможет.И если вы думаете, что можете фактически объяснить, почему метод 1 встраивания ресурса увеличивает мою скомпилированную программу вдвое, я был бы очень признателен.

12
задан Jimmy D 13 January 2012 в 15:07
поделиться