Silverlight中的EmbeddedResouce的MissingManifestResourceException

时间:2011-09-20 16:08:07

标签: silverlight exception embedded-resource

我使用基于XNA的Silverlight引擎编写Silverlight游戏。我之前的游戏中有Build Action设置为Embedded Resource的文件(MP3和文本文件),而我的解决方案中没有*.resx文件。

游戏运行良好;您可以看到生产版本here

另一方面,我目前的项目不允许这样做。当我尝试创建文件Embedded Resource时,我在启动我的应用程序的主UserControl实例的构造函数中抛出了 MissingManifestResourceException 。错误消息是:

  

无法找到适合指定文化或中性文化的任何资源。确保在编译时将“DeenGames.Colosseum.Content.Audio.2.mp3.resources”正确嵌入或链接到程序集“DeenGames.Colosseum”中,或者所有所需的附属程序集都是可加载和完全签名的。

我非常,非常非常感到困惑。将任何项目的Build Action设置为Embedded Resource,无论是MP3,文字还是图片,都会导致此异常。

我如何修复(或调试)这个?我99%确定需要.resx文件,因为我以前的项目没有。

this lovely MSDN page向全世界保证:

  

特别是,Silverlight嵌入式资源必须始终使用   资源构建操作,而不是嵌入式资源构建操作,   它使用Silverlight无法识别的格式。

但是使用Assembly.GetExecutingAssembly().GetManifestResourceNames()有一个众所周知的解决方案。在我的情况下,如果资源只是Resource,它不会向我显示资源;如果它是Embedded Resource,我可以看到带有点分隔命名空间的文件名(如预期的那样)。

下载并查看一个非常简单的工作示例here。它有两个嵌入文件(.2dg和.map)并编译/运行,没有任何例外或resx文件。

您还可以下载一个简短的示例here。用RadiantWrench.dll替换FlatRedBall.dll并观察工作示例中断。 (使用ScreenController.ShowScreen并删除所有FRB引用的代码。)

1 个答案:

答案 0 :(得分:0)

嵌入式资源是一种在Silverlight运行时中折旧的WinForms技术。相反,应该使用 Resource Content 的构建操作。

当您将项目设置为嵌入式资源时,Silverlight希望这是一个.resx文件,因为这是在创建.resx并添加资源时.csproj或.vbproj文件中发生的情况它(该文件被标记为嵌入式资源用于MSBuild,其资源只是None内部<ItemGroup/>,由ResXGenerator在运行时根据相对性发现“资源”的URI文件夹)。如果不是,则将其删除或将其设置为 Content 。您可以检查 Microsoft.Silverlight.Common.targets (通常位于您的C:\ Program Files(x86)\ MSBuild \ Microsoft \ Silverlight \ v4.0文件夹中)以查看它如何更改标记为<的项目em>嵌入式资源 - 设置为内容,设置为无或设置为.resx文件。

如果您只是想查询项目中的资源,可以尝试这种有点麻烦的方法:Enumerating embedded resources


更新:在查看您的项目时,根据WinForms使用此Build Action类型甚至.resx的方式,这并不是真正使用嵌入式资源。它使用名为EmbeddedResourceFileReader.ReadFile ToolsSilverlight.dll 中的函数。代码是:

    private static string ReadFile(string fileName, Assembly currentAssembly)
    {
        string text = EmbeddedResourceHelper.CheckAndSanitizePath(fileName);
        string result = "";
        using (Stream manifestResourceStream = currentAssembly.GetManifestResourceStream(text))
        {
            if (manifestResourceStream == null)
            {
                throw new ArgumentException("Couldn't open " + fileName + ". Make sure the file exists in that directory, and has Build Action set to Embedded Resource.");
            }
            using (StreamReader streamReader = new StreamReader(manifestResourceStream))
            {
                result = streamReader.ReadToEnd();
            }
        }
        return result;
    }

您的.csproject文件将您的文件列为:

<ItemGroup>
    <EmbeddedResource Include="Content\Qadar.2dg" />
    <EmbeddedResource Include="Content\Maps\main.map" />
    <None Include="Properties\AppManifest.xml" />
</ItemGroup>

所有这些都是嵌入的,如上面的 Microsoft.Silverlight.Common.targets 所提到的,您的文件作为公共资源(在顶级,而不是其他实际资源的列表)和找到一种方法来阅读它们。您可以使用ILSpy对DLL进行反编译,以检查这些资源确实是Resources文件夹下的常用资源。

那你怎么能在你的新项目中做到这一点?复制您在第一个方法中执行的确切方法 - 添加ToolsSilverlight.dll,将项目列为嵌入式资源,然后使用EmbeddedResourceFileReader.ReadFile进行调用。您可能还希望确保.csproj文件<ItemGroup/>结构与原始结构类似。不确定<None Include="Properties\AppManifest.xml"/>是否需要EmbeddedResourceFileReader,但可能是。{/ p>