РЕДАКТИРОВАТЬ: прочитать номер ответа 1 от Тима Шмельтера, а затем использовать этот вопрос для примеров того, как внедрять ресурсы и получать доступ к ним во время выполнения.
Тема встроенных ресурсов очень много, особенно когда люди спрашивают, как получить доступ к встроенным файлам во время выполнения. Все становится более запутанным, потому что Visual Studio предоставляет вам два разных способа встраивания ресурса и различные способы доступа к этим ресурсам во время выполнения. Проблема в том, что в зависимости от того, какой метод вы использовали для встраивания ресурса, метод, который вы пытаетесь использовать для доступа к файлу во время выполнения, может не работать. Этот пост является попыткой прояснить все замешательство, которое я вижу там, но у меня также есть вопрос, на который никто не может ответить фактически: почему размер моей скомпилированной программы TWICE - размер встроенного ресурса (иногда)? Например, если я вставляю 20 МБ файл в свой проект, почему моя программа компилируется до 40 МБ? В прошлом я задавал этот вопрос, и никто не смог воспроизвести мои результаты. Я обнаружил, что причина, по которой они не могли воспроизвести, состояла в том, что они вставляли файл по-другому. См. Здесь:
Способ 1:
Дважды щелкните значок "Мой проект", чтобы открыть страницы свойств и перейдите на вкладку "Ресурсы" . Теперь нажмите "Добавить ресурс" > "Добавить существующий файл". Перейдите к файлу, который хотите вставить. Для этого примера я использую исполняемый файл. Теперь вы увидите свой файл на вкладке Ресурсы:
Вы также увидите, что в вашем проекте была создана папка "Ресурсы" , а встроенный файл был помещен в эту папку:
РЕДАКТИРОВАТЬ: ЭТО СЛЕДУЮЩИЙ ШАГ БЫЛ ПРОБЛЕМА. ВЫКЛЮЧАЕТ, ЧТО, КОГДА ВЫ ДОБАВЛЯТЬ ФАЙЛ В РЕЗУЛЬТАТЕ РЕСУРСОВ, ВЫ НЕ ДОЛЖНЫ УСТАНОВИТЬ СТРОИТЕЛЬНОЕ ДЕЙСТВИЕ В РЕЗУЛЬТАТИВНЫЙ РЕСУРС. Счетчик интуитивно понятен!
Теперь с выбранным файлом просмотрите окно свойств файла и измените действие сборки на Embedded Resource: (этот шаг должен выполняться ТОЛЬКО при добавлении файла с помощью метода 2).
Теперь скомпилируйте свою программу. Вы увидите, что размер вашей скомпилированной программы, по крайней мере, вдвое превышает размер встроенного ресурса. Это не происходит с методом 2. См. Здесь:
Способ 2:
Щелкните правой кнопкой мыши имя вашего проекта и выберите "Добавить" > "Существующий элемент". Перейдите к своему файлу, и на этот раз вы заметите, что, хотя он действительно был помещен в ваш проект, папка "Ресурсы" не была создана:
Теперь еще раз выберите файл и измените 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 вложения ресурса раздувает мою скомпилированную программу, чтобы удвоить ее размер, я бы очень признателен.