如果我向Resources.resx添加资源,它们是否嵌入在可执行文件中?
我已经读过某个地方资源存储在程序集中,但项目中的所有文件(包括输出文件夹中的文件)都是程序集的一部分?
或者,汇编只是由编译器和资源生成的文件和模块不包含在程序集中吗?
有人可以澄清一下这是如何运作的吗?
答案 0 :(得分:2)
嵌入的资源存储在DLL或EXE文件中。
答案 1 :(得分:0)
添加到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);
}
}
但是等等...我"Charles is Cool"
在这里什么地方都看不到...去哪儿了? GetString()
从哪里得到它?
好吧,最终grovels for the resource(MSFT的术语,不是我的),我想我们应该将其视为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));
}
基本上可以找到PE标头的偏移量(请参见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
。