gpt4 book ai didi

.net - .NET 应用程序中的嵌入式资源存储在哪里?

转载 作者:行者123 更新时间:2023-12-02 20:53:33 26 4
gpt4 key购买 nike

如果我将资源添加到 Resources.resx,它们是否嵌入到可执行文件中?

我在某处读到资源存储在程序集中,但是项目中的所有文件(包括输出文件夹中的文件)都是程序集的一部分吗?

或者,程序集是否只是编译器生成的文件和模块,程序集中不包含资源?

有人可以准确地解释一下它是如何工作的吗?

最佳答案

快速回答

添加到 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() 从哪里获取它?

最终它 grovels for the resource (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 header 的偏移量(参见 IMAGE_COR20_HEADER )。查看Portable Executable article on Wikipedia ,您将看到 svg 图像有一个 ResourceTable 部分(RVA,又名 Relative Virtual Address )

我在这里想说的是,资源绝不是 C# 或 .NET 功能,它们只是 PE 二进制格式始终具有的托管 API。

对于任意二进制资源

请注意,我所说的一切都适用于任意数据,如果您要向资源中添加一些二进制文件,Resources 会将其作为 byte[] 呈现给您但实际上它会将其编码为其他内容。

虽然在 Visual Studio 中打开 resx 文件会为您提供一个相当无趣的导入二进制文件的路径,但请注意,如果您以类似 JetBrains DotPeek 的形式打开已编译的二进制文件,然后查看resx文件,文件的路径已被替换为字符串,

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

虽然我无法在 Visual Studio 端找到任何代码来证明这一点,但我猜测该字符串是(二进制)资源文件中字节的 Base64 编码版本,因为运行 Convert.ToBase64String( Resources.binary) 为我提供了在编译的二进制文件的 resx 文件中找到的相同字符串。对于那些想在家尝试的人,我的二进制文件仅包含 08 67 53 09 BE EF CA FE C0 0F FE AB CD EF

关于.net - .NET 应用程序中的嵌入式资源存储在哪里?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5692865/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com