Разгадывание путаницы по поводу встроенных ресурсов - PullRequest
12 голосов
/ 13 января 2012

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

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

Метод 1:

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

enter image description here

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

enter image description here

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

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

enter image description here

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

Метод 2:

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

enter image description here

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

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

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

Где Path - это местоположение и имя файла, который вы хотите сохранить на жестком диске, ResourceName - это имя встроенного ресурса.который вы видите в окне проекта (за вычетом любого расширения), а «Добавить» означает, хотите ли вы создать новый файл или перезаписать существующий файл.Так, например, используя 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 встраивания ресурса увеличивает мою скомпилированную программу, удваивая ее размер, я был бы очень признателен.

Ответы [ 2 ]

9 голосов
/ 13 января 2012

Я предполагаю, что метод 1 добавляет файлы дважды.

По крайней мере, таков вывод выше .

Цитата :

Вы зашли на страницу ресурсов свойств проекта и добавили туда файлы, верно?Затем вы вошли в обозреватель решений и изменили действие по сборке файлов на Embedded Resource, верно?Вот почему вы удвоили размер файла: вы добавляли каждый файл дважды.

Существует два разных способа добавления ресурсов: на странице ресурсов в свойствах проекта и в обозревателе решений.Вы НЕ делаете оба.Если вы хотите использовать GetManifestResourcestream, тогда вы НЕ используете страницу ресурсов.Вы добавляете файлы в проект в обозревателе решений вручную, а затем задаете для параметра «Построить действие» значение «Встроенный ресурс».

В будущем выполняйте одно или другое, а не оба.

  1. Добавьте файл на страницу ресурсов в свойствах проекта, а затем получите к нему доступ через My.Resources.Это автоматически добавит файл в проект в обозревателе решений, но действие сборки будет Нет, и его следует оставить таким образом.

  2. Добавить файл в проект в обозревателе решенийс помощью Добавить новый элемент или Добавить существующий элемент.Установите для параметра «Действие сборки» файла значение «Встроенный ресурс», а затем получите доступ к ресурсу с помощью GetManifestResourceStream.

0 голосов
/ 19 сентября 2018

Просто обновление для всех, кто хочет использовать этот код. Код фактически записывает один дополнительный байт в файл из-за нулевого объявления массива байтов.

Чтобы получить точную копию исходного файла, измените код на:

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