在调试某些依赖于了解当前正在执行的程序集路径的行为时,我注意到如果我在C#VS 2010项目中执行以下行而不对构建输出路径进行调整,则Assembly.GetExecutingAssembly将返回一个案例 - 正确的道路。
例如,
string location = Assembly.GetExecutingAssembly().Location;
显示“C:\ src \ MyProject \ MyProject \ bin \ Debug \ MyProject.exe”
现在,如果我创建一个单独的目录来输出程序集,例如: C:\ src \ MyCamelCaseDir \,并更新Build - >输出到C:\ src \ mycamelcasedir的路径,上面的代码生成字符串“C:\ src \ mycamcelcasedir \ MyProject.exe”。
区别在于,显然
"..\\MyCamelCaseDir".equals("..\\mycamelcasedir")
为false,即使操作系统不将路径视为区分大小写。
我认为在Visual Studio中以调试模式运行是原因...但我仍然有点困惑 - 不应该让GetExecutingAssembly返回操作系统认为包含程序集,case和所有的目录路径吗?
修改: 我认为我的问题没有得到很好的表达。我的问题的正确答案是海报谁注意到VS只是连接Build Ouput Path中的文本框加上项目名称。
我想问的问题是:为什么没有Assembly.GetExecutingAssembly()。位置,以区分大小写的方式返回操作系统存储它的路径?
我知道Windows不区分大小写,因为您可以在浏览器窗口中键入C:\ foo \ bar,这会将您带到C:\ Foo \ Bar(如果有这样的目录)。
但我认为执行程序集的位置在所有情况下都是相同的,无论是否调试。
答案 0 :(得分:3)
虽然文档在这一点上未公开,但GetExecutingAssembly()。Location的路径似乎是操作系统在加载程序集时使用的路径(对于可执行文件,这似乎是传递给Process.Start()的路径操作系统按原样使用的等效操作,而不将其大小写等于文件系统中记录的版本。),文件名部分除外,它取自程序集的实际名称。
通过编译测试命令行应用程序并从命令提示符运行它,您可以轻松地看到这一点:
using System;
using System.Reflection;
namespace TestLocation
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("{0}", Assembly.GetExecutingAssembly().Location);
}
}
}
产生:
C:\ Users \用户化身GT; C:\工作\ TestLocation \ BIN \调试\ TestLocation.exe C:\工作\ TestLocation \ BIN \调试\ TestLocation.exe
C:\ Users \用户化身以及c:\工作\ testlocation \ BIN \调试\ testlocation.exe C:\工作\ testlocation \ BIN \调试\ TestLocation.exe
如果你输入一个简短的名字,即只是“testlocation”,你会得到正确套装的版本,但在上面的第二种情况下,它已经有一个规范的文件名,所以只是按原样传递它 - 因此名字不是套。
简而言之:非常明智的做法是不依赖于Windows下的filespecs中的case-preservation,即使NTFS文件系统确实在内部提供它,除非你自己手动查看文件系统中的所有内容。您从大多数API获得的所有内容都是可用于访问文件的文件规范,而不一定是文件系统文件中记录的文件。
答案 1 :(得分:0)
字符串比较不知道字符串的底层值是什么。正如您在Windows中默认路径所指出的那样,区分大小写不敏感,因此您在比较时必须以这种方式对待它们。
即。在你的情况下你应该使用
String.Equals("..\\MyCamelCaseDir", "..\\mycamelcasedir",
String.Comparison.OrdinalIgnoreCase)
比较文件路径字符串。 (或者您可以先将路径标准化 - Normalize directory names in C#)。
附注:不同外壳的最可能原因来自于完整的可执行文件名由VS构造,其中包含“输出路径”和“项目名称”的字符串连接。