Где хранятся встроенные ресурсы в приложении .NET? - PullRequest
5 голосов
/ 17 апреля 2011

Если я добавлю ресурсы в Resources.resx, будут ли они встроены в исполняемый файл?

Я где-то читал, что ресурсы хранятся в сборке, но являются ли все файлы в проекте (включая файлы в выходной папке) частью сборки?

Или сборка - это просто файлы и модули, созданные компилятором, а ресурсы не включены в сборку?

Может кто-нибудь уточнить, как именно это работает?

Ответы [ 2 ]

2 голосов
/ 17 апреля 2011

Встроенные ресурсы хранятся в файлах DLL или EXE.

0 голосов
/ 30 октября 2018

Быстрый ответ

Ресурсы, которые вы добавляете в программу на C #, хранятся в разделе ресурсов двоичного файла PE.

Например, если я добавлю строку, MyTestString, со значением "Charles is Cool"

A screenshot of the resource editor with the string added to it

Если я откроюСкомпилированный двоичный файл в шестнадцатеричном редакторе, я вижу свою строку:

A screenshot from a hex editor

Круто, но как это здесь получилось?

Сторона C #

Редактор ресурсов генерирует Resources.Designer.cs, вот что он сгенерировал

/// <summary>
///   Looks up a localized string similar to Charles is Cool.
/// </summary>
internal static string MyTestString {
    get {
        return ResourceManager.GetString("MyTestString", resourceCulture);
    }
}

Но подождите ... Я не вижу "Charles is Cool" где-нибудь здесь ..Куда это делось?Откуда GetString() получает его?

Ну, в конце концов, он унижает ресурс (терминология MSFT, а не моя), я полагаю, нам следует рассмотреть это ManifestBasedResourceGroveler, которое в конечном итоге получитнам extern GetResource(), верный признак того, что мы упали с края вселенной .NET ... вы знаете, что это означает ...

Сторона CoreCLR

Мы можем посмотреть в репозитории coreclr пример того, как это реализовано,

Если вы проследите код здесь, вы в конечном итоге получите PEDecoder::GetResource()

const void *PEDecoder::GetResource(COUNT_T offset, COUNT_T *pSize) const
{
    CONTRACT(const void *)
    {
        INSTANCE_CHECK;
        PRECONDITION(CheckCorHeader());
        PRECONDITION(CheckPointer(pSize, NULL_OK));
        NOTHROW;
        GC_NOTRIGGER;
    }
    CONTRACT_END;

    IMAGE_DATA_DIRECTORY *pDir = &GetCorHeader()->Resources;

    // 403571: Prefix complained correctly about need to always perform rva check
    if (CheckResource(offset) == FALSE)
        return NULL;

    void * resourceBlob = (void *)GetRvaData(VAL32(pDir->VirtualAddress) + offset);
    // Holds if CheckResource(offset) == TRUE
    PREFIX_ASSUME(resourceBlob != NULL);

     if (pSize != NULL)
        *pSize = GET_UNALIGNED_VAL32(resourceBlob);

    RETURN (const void *) ((BYTE*)resourceBlob+sizeof(DWORD));
}

Который в основном находит смещение от заголовка PE (см. IMAGE_COR20_HEADER).Прочтите статью Portable Executable в Википедии , вы увидите, что в образе svg есть раздел для ResourceTable (RVA, он же Относительный виртуальный адрес )

What I 'Суть в том, что Ресурсы ни в коем случае не являются функцией C # или .NET, это всего лишь управляемый API, который всегда был в двоичном формате PE.

Для произвольных бинарных ресурсов

Обратите внимание, что все, что я сказал, работает для произвольных данных, если вы добавите какой-нибудь двоичный файл в ваши ресурсы, Resources представит его вам как byte[] но на самом деле это закодировало бы его как-то еще.

Открывая файл resx в Visual Studio, вы получаете довольно неинтересный путь к импортированному вами двоичному файлу, обратите внимание, что если вы откроете скомпилированный двоичный файл вчто-то вроде JetBrains DotPeek и посмотрите на файл resx, путь к файлу был заменен строкой,

<data name="binary" type="System.Byte[], mscorlib">
    <value>CGdTCb7vyv7AD/6rze8=</value>
</data>

Хотя я не смог найти никакого кода на VisualСтудия, чтобы доказать это, я бы предположил, что эта строка представляет собой версию байтов в (двоичном) файле ресурсов в кодировке base64, потому что запуск Convert.ToBase64String(Resources.binary) дает мне ту же строку, что и в файле resx скомпилированного двоичного файла.Для тех из вас, кто хочет попробовать это дома, мой бинарный файл содержит 08 67 53 09 BE EF CA FE C0 0F FE AB CD EF.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...