gpt4 book ai didi

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

转载 作者:行者123 更新时间:2023-11-30 21:55:36 25 4
gpt4 key购买 nike

在 visual studio 中,我有一个构建操作设置为“嵌入式资源”的文件。我想在运行时提取此文件,但无法获取文件名:

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

最佳答案

请注意, list 资源名称​​确实包括原始文件名和项目相关子目录。

另一个答案中缺少的关键信息(使该答案用处不大)是项目名称和包含原始文件的任何文件夹/目录都表示为资源名称中的组件。整个 list 资源名称使用 '.' 字符分隔到这些组件中。

有了这些知识,您应该能够正确处理您的资源。特别是,您需要删除名称的第一个部分(它只是项目名称),然后将名称的最后一个部分以外的所有部分都视为目录名称。

这有点棘手,因为 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 (i.e. "dot"/"period" character). I.e. 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;
}
}

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

注意:您可能会发现过滤资源名称列表很有用。例如,如果您的项目具有您使用设计器添加的传统资源(即显示项目属性,然后单击“资源”选项卡并在那里添加资源,而不是明确地作为嵌入式资源)。否则,您将获得几乎所有的 list 资源。

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

关于c# - 如何获取exe的嵌入式资源的文件名?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32173741/

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