如何获取exe的嵌入式资源的文件名?

在visual studio中,我有一个文件,其构建操作设置为’Embedded Resource’。 我想在运行时提取此文件,但我无法获取文件名:

// returns null Assembly.GetExecutingAssembly().GetManifestResourceInfo(resourceName).FileName 

请注意,清单资源名称包括原始文件名和项目相关子目录。

另一个答案中缺少的关键信息(使答案远不如有用)是项目名称和包含原始文件的任何文件夹/目录在资源名称中表示为组件。 整个清单资源名称使用'.'分隔成那些组件'.' 字符。

有了这些知识,您应该能够正确处理您的资源。 特别是,您将要删除名称的第一个组件(只是项目名称),然后将名称的最后一个组件除了作为目录名称。

这有点棘手,因为a)你的文件名可能有一个扩展名(因此已经有一个'.'字符),以及b)编译器将以任何方式逃逸(以一种基本的方式) '.' 在文件夹/子目录名称中找到的字符。

这是一个代码示例,显示了基本方法:

 class Program { static void Main(string[] args) { Console.WriteLine(string.Join(Environment.NewLine, Assembly.GetEntryAssembly().GetManifestResourceNames())); Assembly assembly = Assembly.GetEntryAssembly(); string exeDirectory = Path.GetDirectoryName(assembly.Location); foreach (string resourceName in assembly.GetManifestResourceNames()) { string fileName = _GetFileNameFromResourceName(resourceName), directory = Path.GetDirectoryName(fileName); if (!string.IsNullOrEmpty(directory)) { Directory.CreateDirectory(directory); } using (Stream outputStream = File.OpenWrite(Path.Combine(exeDirectory, fileName))) { assembly.GetManifestResourceStream(resourceName).CopyTo(outputStream); } } } private static string _GetFileNameFromResourceName(string resourceName) { // NOTE: this code assumes that all of the file names have exactly one // extension separator (ie "dot"/"period" character). Ie all file names // do have an extension, and no file name has more than one extension. // Directory names may have periods in them, as the compiler will escape these // by putting an underscore character after them (a single character // after any contiguous sequence of dots). IMPORTANT: the escaping // is not very sophisticated; do not create folder names with leading // underscores, otherwise the dot separating that folder from the previous // one will appear to be just an escaped dot! StringBuilder sb = new StringBuilder(); bool escapeDot = false, haveExtension = false; for (int i = resourceName.Length - 1; i >= 0 ; i--) { if (resourceName[i] == '_') { escapeDot = true; continue; } if (resourceName[i] == '.') { if (!escapeDot) { if (haveExtension) { sb.Append('\\'); continue; } haveExtension = true; } } else { escapeDot = false; } sb.Append(resourceName[i]); } string fileName = Path.GetDirectoryName(sb.ToString()); fileName = new string(fileName.Reverse().ToArray()); return fileName; } } 

使用上面的代码创建一个新项目,然后将项目文件夹中的嵌入资源添加到项目文件夹中,或者根据需要添加,以查看结果。

注意:您可能会发现过滤资源名称列表很有用。 例如,如果您的项目具有使用Designer添加的传统资源(即显示项目属性,然后单击“资源”选项卡并在其中添加资源),您将获得名为MyProjectName.Resources.resources资源。而不是明确地作为嵌入资源)。 否则,您将获得每个清单资源。

注意:请记住,要写入运行可执行文件的目录,您可能需要比当前进程更高级别的权限。 例如,如果用户将EXE复制到“Program Files”目录中的目录作为admin,但随后尝试以受限用户身份运行该程序。 正如评论者Luaan在你的问题上暗示的那样,看起来你最好只是实现某种安装程序。 (Visual Studio提供对基本Install Shield产品的免费访问,或者您可以使用例如WiX ……实际上不需要从头开始编写安装程序来实现安装程序)。

请注意GetManifestResourceInfo(resourceName).FileName仅获取包含清单资源的文件的名称(如果它与清单文件不同)。 关于清单请看这里: http : //www.dotnetspark.com/kb/682-what-is-manifest.aspx

您可以使用Assembly.GetManifestResourceNames方法获取程序集中所有资源的名称列表。

喜欢:

// str包含所有嵌入的资源名称

  string[] str = assembly.GetManifestResourceNames();