Подтвердить что ты не робот

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

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

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

Способ 1:

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

enter image description here

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

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 - это имя встроенного ресурса, который вы видите в окне проекта (за вычетом любого расширения), а Append - это то, хотите ли вы создать новый файл или перезаписать существующий файл. Так, например, используя test.exe из приведенных выше изображений, я мог бы сохранить этот файл на диске C следующим образом:

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

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

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

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 вложения ресурса раздувает мою скомпилированную программу, чтобы удвоить ее размер, я бы очень признателен.

4b9b3361

Ответ 1

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

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

Цитата

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

Существует два способа добавления ресурсов: на странице "Ресурсы" свойств проекта и в обозревателе решений. Вы НЕ МОЖЕТЕ делать то и другое. Если вы хотите использовать GetManifestResourcestream, то вы НЕ используете страницу "Ресурсы". Вы добавляете файлы в проект в обозревателе решений вручную, затем вы устанавливаете действие Build Action в Embedded Resource.

В будущем сделайте одно или другое, а не оба.

  • Добавить файл на страницу "Ресурсы" свойств проекта, а затем получить доступ к нему через My.Resources. Это автоматически добавит файл в проект в Обозреватель решений, но действие сборки будет None, и оно должно быть оставлено таким образом.

  • Добавьте файл в проект в Обозреватель решений через Добавить новый элемент или Добавить существующий элемент. Задайте действие сборки файла для встроенного ресурса, а затем получите доступ к ресурсу с помощью GetManifestResourceStream.