【问题标题】:Environment.CurrentDirectory vs System.IO.Directory.GetCurrentDirectoryEnvironment.CurrentDirectory 与 System.IO.Directory.GetCurrentDirectory
【发布时间】:2013-11-14 15:22:12
【问题描述】:

我正在编写一个 .Net WinForms,并不断在 DEBUG 和 RELEASE 配置之间切换,并且有一些文件需要任一配置才能访问。

我想做的是将文件放在 BIN 文件夹中的一个公共目录中,因此它看起来像这样:

MyProject/Bin/CommonFiles
MyProject/Bin/Debug
MyProject/Bin/Release

我正在考虑使用以下方式访问文件:

System.IO.Directory.GetParent(System.IO.Directory.GetCurrentDirectory).FullName

我的问题是这是否危险,因为根据我的阅读,System.IO.Directory.GetCurrentDirectory 可能会由于用户在打开的文件对话框中选择新的当前目录而发生变化。

我是否应该使用类似以下内容的东西:

System.IO.Directory.GetParent(Environment.CurrentDirectory).FullName

OR 有没有更好的方法可以访问 /Bin 文件夹,这样我就可以从那里移动,或者以一种普遍接受的方式/位置来存储程序通常需要到达的文件和方法更容易引用(可能适用于任何类型的应用程序,而不仅仅是 WinForms)?

【问题讨论】:

  • bin目录是VS构建系统的一个实现细节。由于您不太可能将带有源代码的项目交付给客户,并且您将无法将文件保存到 c:\program files\bin,因此这不是一个好的做法。 %appdata% 用于可写文件,您的 EXE 目录或 %programdata% 用于只读文件。
  • 谢谢@HansPassant...正如我在下面告诉克里斯蒂安的那样,我有点犹豫是否要不断地将它们复制到每个用户计算机上的 appdata 文件夹,因为许多用户只需要使用这个程序一次,它就是此时在我组织的共享驱动器上...对此有什么想法吗??

标签: c# .net vb.net


【解决方案1】:

您可以使用System.Reflection.Assembly.GetExecutingAssembly().Location 获取应用的 .exe 位置。

string exePath = System.Reflection.Assembly.GetExecutingAssembly().Location;
string exeDir = System.IO.Path.GetDirectoryName(exePath);
DirectoryInfo binDir = System.IO.Directory.GetParent(exeDir);

【讨论】:

  • 如果程序集被卷影复制,Assembly.Location 包含被卷影复制后的位置。更好的解决方案是使用 AppDomain.BaseDirectory:stackoverflow.com/a/6041505/13087
【解决方案2】:

我会这样做:

  • 为项目中的文件创建一个子文件夹,例如“通用文件”。

  • 将配置文件放在此文件夹中。将它们的属性设置为:

    • 构建操作 = 内容

    • 复制到输出目录 = 始终复制(或者可能:如果较新则复制)

  • 每次构建应用程序时,这些文件将被复制到 bin\Debug\CommonFiles 或 bin\Release\CommonFiles。您可以将它们引用为:

    Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CommonFiles\MyFile.Dat");
    

【讨论】:

  • 这似乎是最聪明的主意...对于我们需要的所有这些文件以及所需的 .dll... 现在,我知道这可能看起来很奇怪,但大概有 50 个大约10个左右不同目录中的文件我需要这样做(根据用户输入,它会打开一个特定文件)......有没有办法一次更改整个目录的这些属性,或者我有逐个文件地执行此操作...或者,鉴于这些新数据,您会推荐其他方法吗?谢谢!!!
  • 我认为这种技术适用于相对少量的只读配置文件,所有文件在构建时都存在。如果它们是读/写文件和/或用户可以添加其他文件,那么我不会这样做。而是将文件放在 bin 文件夹之外的合适位置(如果它们是读/写文件,用户可以写入该位置),并将配置设置添加到包含文件的目录的 app.config 中。
  • 谢谢,乔 - 它们不可写,只是保存到用户机器的模板......只是有很多不同的模板和不同的目的,所以在子文件夹中......您仍然会说使用 app.config 来执行此操作??您如何建议最好的完成(也许@Tim 的解决方案与您添加的建议/编辑??? - 再次感谢您的持续帮助!
  • 乔,我找到了一个解决方案来完成你的工作......我将它作为一个单独的解决方案发布,以向人们展示我所做的,但我确实认为一旦我发现你就有了最好的解决方案如何完成必要的任务...谢谢!!!
【解决方案3】:

虽然大多数答案似乎确实有效,但the solution offered by Joe above 经过相当多的调整后,证明是适合我情况的最佳解决方案。


首先,我采用的最终解决方案:

  • 创建了一个Common Files 目录(在我的情况下,与我的Bin 目录处于同一级别,但这不是必需的,它只是解释我稍后将放置的代码如何工作)
  • 编辑了我的 .vbproj(或 `,csproj')文件,将该目录(包括子目录)中的所有文件设置为我的项目的额外资源文件
  • 对我的.vbproj 文件进行第二次编辑,以便在构建时将所有这些资源文件复制到我的 bin\Debug 或 bin\Release 目录。

其次,我是如何学会这样做的:

  • Joes solution above
  • This link 展示了如何将通配符添加到 .vbproj / .csproj 文件中,以便您可以一次添加完整目录。
  • This answer 显示如何将文件复制到我的 \Bin 目录

最后,我的解决方案:

  • 我打开了我的 project.vbproj 文件
  • <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />这一行上,我添加了一个新的ItemGroup,如下所示:

<ItemGroup> <CommonFiles Include="Common Files\**" /> </ItemGroup>

这会加载所有文件(包括所有子文件夹)并为我提供构建操作CommonFiles

  • <Import Project="$(MSBuildToolsPath)\Microsoft.VisualBasic.targets" />这一行下,我添加了以下几行:

    <PropertyGroup> <PrepareForRunDependsOn>$(PrepareForRunDependsOn);CopyCommonFiles</PrepareForRunDependsOn> </PropertyGroup>

<Target Name="CopyCommonFiles"> <Copy SourceFiles="@(CommonFiles)" DestinationFolder="$(OutDir)\%(RecursiveDir)" SkipUnchangedFiles="true"/> </Target>

这将在构建时将文件从CommonFiles 构建操作复制到您的 bin\Debug / bin\Release 目录中。

我就是这样做的......

非常感谢任何 cmets / 想法)如果您认为我应该使用其他方式或其他方式)....

这个

【讨论】:

    【解决方案4】:

    如果您有配置数据等,我会将它们存储在 %Appdata% 目录中。将可能更改的文件放入安装目录不是一个好主意,并且从 Windows Vista 开始被禁止。配置数据应该存储在 %Appdata% 文件夹中,这是一个特殊的文件夹。不要将其路径硬编码到您的程序中 - 来自国外或 32/64 位 Windows 的用户将遇到严重问题。

    您可以在这里看到如何访问 Appdata-Folder 的好主意: How to create appdata folder with C#

    【讨论】:

    • 这不是真正的配置数据 - 这是程序在运行时需要的更多文件......我有点犹豫是否不断地将它们复制到每个用户计算机上的 appdata 文件夹,因为许多用户只会需要使用此程序一次,并且此时它在我组织的共享驱动器上...对此有什么想法吗??
    • @JohnBus​​tos 这绝对是一个有效的观点。我在工作中有一个非常相似的配置,只是在程序的 Proerties 中存储了一个路径。由于它是作为设置存储的,因此很容易构建一个允许用户选择新文件位置的小屏幕。我对硬编码路径犹豫不决 - 它将来可能会改变。
    【解决方案5】:

    以下代码来自http://msdn.microsoft.com/en-us/library/ms229654(v=vs.90).aspx

        String strAppDir = Path.GetDirectoryName(
            Assembly.GetExecutingAssembly().GetName().CodeBase);
        String strFullPathToMyFile = Path.Combine(strAppDir, "fileName.txt");
    
        MessageBox.Show(String.Format("Path to the application is: '{0}'." +
            "Full path to the file in the application folder is: '{1}'",
            strAppDir, strFullPathToMyFile));
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多