Assembly.GetExecutingAssembly().Location 返回程序集在磁盘上的绝对路径(含文件名),是定位同目录文件的可靠起点,但SingleFile发布时需改用AppContext.BaseDirectory,且须用Path.Combine拼接路径并检查文件存在性。

用 Assembly.GetExecutingAssembly().Location 获取当前程序集路径
很多开发者误以为 Assembly.GetExecutingAssembly().Location 返回的是“当前运行目录”,其实它返回的是该程序集(.dll 或 .exe)**在磁盘上的绝对路径**,包括文件名。这是定位同目录文件最可靠起点。
注意:Location 在某些场景下可能为空(比如动态生成的程序集、部分 .NET Core/.NET 5+ 的 AOT 编译或反射加载的内存程序集),此时应改用 CodeBase 或 GetAssembly(typeof(...)).Location 配合已知类型。
示例:
string assemblyPath = Assembly.GetExecutingAssembly().Location; string assemblyDir = Path.GetDirectoryName(assemblyPath); // 得到目录,不含文件名 string configPath = Path.Combine(assemblyDir, "config.json");
别用 Environment.CurrentDirectory 找同目录文件
Environment.CurrentDirectory 是进程当前工作目录,它可能被用户双击启动、命令行 cd 后执行、IDE 调试配置、甚至其他 DLL 显式调用 Directory.SetCurrentDirectory 修改 —— 完全不可控。
常见错误现象:调试时正常,发布后读不到文件;或者 Windows 服务中始终报 FileNotFoundException。
除非你明确需要“工作目录语义”(如命令行工具处理相对路径参数),否则一律避免用它定位程序集关联文件。
处理 .NET Core / .NET 5+ 中的 PublishSingleFile 场景
启用 PublishSingleFile=true 后,Location 指向的是临时解压目录(如 C:\Users\...\AppData\Local\Temp\.net\MyApp\...),而非原始部署目录。此时同目录文件(如 readme.txt)根本不在 Location 所指位置。
解决方案取决于你的部署方式:
- 若文件是必需资源,改用嵌入式资源(
EmbeddedResource)并用Assembly.GetManifestResourceStream读取 - 若必须保留外部文件,发布时禁用
IncludeNativeLibrariesForSelfExtract,或改用CopyToPublishDirectory并配合AppContext.BaseDirectory -
AppContext.BaseDirectory在 SingleFile 下指向实际发布根目录(即包含 .exe 的那个文件夹),比Location更适合找“部署同级文件”
路径拼接务必用 Path.Combine,别字符串拼接
手动拼接路径(如 dir + "\\" + "file.txt")在 Linux/macOS 上直接失败,且易引入双反斜杠、末尾多余分隔符等错误。
正确做法永远是:
string dir = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); string filePath = Path.Combine(dir, "data", "cache.bin"); // 自动适配路径分隔符
另外,检查文件是否存在再读取,避免静默失败:
if (File.Exists(filePath))
{
var content = File.ReadAllText(filePath);
}
else
{
// 记录警告或抛出有意义异常,而不是让后续逻辑空引用
}
真正容易被忽略的是:同一个程序集在不同加载上下文(如 AssemblyLoadContext)中,Location 可能不同;而插件式架构里,你拿到的“执行程序集”未必是你以为的那个 DLL —— 此时得用 typeof(YourKnownType).Assembly.Location 锁定目标。










