c# - C# 应用程序搜索 System32 而不是本地文件
问题描述
我开发了一个 C# winforms 应用程序。该应用程序需要另一个文件才能运行,该文件与可执行文件位于同一目录中。让我们调用这个文件a.abc
。当我使用命令提示符时,导航到程序目录,然后键入以下内容以使用我的程序打开文件,它工作正常:
my-prog.exe "path-to-file\file-name"
但是,当我在资源管理器中右键单击文件,打开方式并选择我的程序时,由于某种原因,程序会尝试a.abc
在System32
目录中而不是在应用程序目录中搜索文件。
我知道如果我使用完整的文件路径而不是使用相对路径,它会正常工作,但我想知道为什么会这样?
更新#1
我有一个reqdFileName
以值命名的字符串资源toolset.f
我正在使用
using (StreamReader sr = File.OpenText(@Properties.Resources.reqdFileName))
// read lines and use it here
}
解决方案
这都是关于绝对和相对路径的。由于您的路径是相对的,因此它与您的进程工作目录“前置” 。
因此,当您在应用程序目录(例如C:\MyProgram\
)中运行程序时 - 路径a.abc
等于C:\MyProgram\a.abc
. 如果你C:\
像这样从不同的目录(比如 )运行它:.\MyProgram\my-prog.exe
,那么 patha.abc
等于C:\a.abc
. 您可以通过自行检查的System.IO.Directory.GetCurrentDirectory()
方法获取当前工作目录。
当您使用“打开方式”菜单时 - 您的当前目录将是%windir%\system32
并且这是“按设计”,您不应该尝试更改它。
您可以通过将相对路径转换为绝对路径来解决您的问题,如下所示:
using System.Reflection;
using System.IO;
var appLocation = Assembly.GetEntryAssembly().Location;
var appPath = Path.GetDirectoryName(appLocation);
var reqdFilePath = Path.Combine(appPath, @Properties.Resources.reqdFileName);
using (StreamReader sr = File.OpenText(reqdFilePath))
// read lines and use it here
}
另一种选择是在程序开头的某处更改工作目录:
using System.Reflection;
var appLocation = Assembly.GetEntryAssembly().Location;
var appPath = Path.GetDirectoryName(appLocation);
Directory.SetCurrentDirectory(appPath);
// we are in your app directory now for sure
// ... Later in your code ...
using (StreamReader sr = File.OpenText(@Properties.Resources.reqdFileName))
// read lines and use it here
}
但是,在这种情况下,您应该在程序结束时以某种方式恢复您的工作目录,因为如果您的用户在最后强行移动到某个路径,这会让他们感到沮丧(如果您问我,我会讨厌这样的程序)。
在一些评论中还建议将您的应用程序目录添加到%PATH%
evironment 变量。这可以解决问题,但是如果您显然不需要它,请不要污染您的。不是无限的——这是一个很好的解释。%PATH%
%PATH%
只是一个旁注。没有真正需要处理流和流读取器来逐行读取文件。有一个File.ReadAllLines()
方法:
using System.Reflection;
using System.IO;
var appLocation = Assembly.GetEntryAssembly().Location;
var appPath = Path.GetDirectoryName(appLocation);
var reqdFilePath = Path.Combine(appPath, @Properties.Resources.reqdFileName);
foreach (var line in File.ReadAllLines(reqdFilePath))
{
// use your line here
}
正如我所说,它将逐行读取,因此可以读取一个大文件(它不会将整个文件加载到您的内存中,一次只加载一行)。如果您的文件不是那么大,您也可以一次性将其全部读取为单个string
withFile.ReadAllText()
方法。
推荐阅读
- powershell - 如何为 powershell tee 命令指定文件格式?
- google-apps-script - 谷歌表格:允许编辑任何人,但不允许脚本
- java - 从亚马逊 jdk 更改为 openjdk
- java - JavaFx TextArea 中的改写模式:如何启用
- python - 如何使用 Paramiko 或其他库通过 Python 将整个文件夹传输到 SFTP 服务器?
- raku - Raku:将字符串发送到子进程的标准输入
- android - 很想获得可组合组件的 MeasuredWitdh 和 MeasuredHeight?
- php - Ubuntu - WordPress 安装错误 - 新版本 2020 - 您的 PHP 安装似乎缺少 MySQL
- python - 如何在 django 中使用日期时间过滤日期时间?
- ios - iOS VoIP 推送通知有时会为空