Mir*_*ria 6 .net resources visual-studio
如果我向Resources.resx添加资源,它们是否嵌入在可执行文件中?
我已经读过资源存储在程序集中的某个地方,但项目中的所有文件(包括输出文件夹中的文件)都是程序集的一部分?
或者,汇编只是由编译器和资源生成的文件和模块不包含在程序集中?
有人可以澄清这是如何工作的吗?
添加到 C# 程序的资源存储在 PE 二进制文件的资源部分中。
例如,如果我添加一个字符串 ,MyTestString其值为"Charles is Cool"
如果我在十六进制编辑器中打开编译的二进制文件,我可以看到我的字符串:
很酷,但是它是怎么到这里的?
资源编辑器生成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);
}
}
Run Code Online (Sandbox Code Playgroud)
但是等等...我没有看到"Charles is Cool"这里的任何地方...它去了哪里?从哪里GetString()得到它?
好吧,最终它会屈服于资源(MSFT 的术语,不是我的),我想我们应该将其视为 a ManifestBasedResourceGroveler,这最终让我们成为extern GetResource(),这是我们已经脱离 .NET 宇宙边缘的明确信号......你知道这意味着...
我们可以查看 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));
}
Run Code Online (Sandbox Code Playgroud)
它基本上找到了相对于 PE 标头的偏移量(参见 参考资料IMAGE_COR20_HEADER)。查看Wikipedia 上的 Portable Executable 文章,您将看到 svg 图像有一个 ResourceTable 部分(RVA,又名相对虚拟地址)
我在这里得到的是,资源绝不是 C# 或 .NET 功能,它们只是 PE 二进制格式始终具有的托管 API。
请注意,我所说的所有内容都适用于任意数据,如果您要向资源中添加一些二进制文件,Resources则会将其作为 a 呈现给您byte[],但实际上它会将其编码为其他内容。
虽然在 Visual Studio 中打开 resx 文件会为您提供导入的二进制文件的相当无趣的路径,但请注意,如果您在JetBrains DotPeek之类的工具中打开已编译的二进制文件并查看 resx 文件,则该文件的路径具有被替换为字符串,
<data name="binary" type="System.Byte[], mscorlib">
<value>CGdTCb7vyv7AD/6rze8=</value>
</data>
Run Code Online (Sandbox Code Playgroud)
虽然我无法在 Visual Studio 端找到任何代码来证明这一点,但我猜测这个字符串是(二进制)资源文件中字节的 base64 编码版本,因为运行给Convert.ToBase64String(Resources.binary)我提供了与编译后的字符串相同的字符串二进制的 resx 文件。对于那些想在家尝试这个的人,我的二进制文件刚刚包含08 67 53 09 BE EF CA FE C0 0F FE AB CD EF.