你如何在代码中获得C#(VS 2008)中的解决方案目录?

时间:2010-06-16 22:56:46

标签: c# visual-studio winforms nhibernate

这里有一个恼人的问题。我有一个NHibernate / Forms应用程序,我正在通过SVN工作。我做了一些自己的控件,但当我拖放那些(或者查看我已经拖放过的一些表单编辑器)到我的其他控件上时,Visual Studio决定它需要执行我写的一些代码,包括查找hibernate.cfg.xml的部分。

我不知道为什么会这样,但是(有时!)当我在表单加载期间执行代码或拖放它时将当前目录切换到C:\ program files \ vs 9.0 \ common7 \ ide,然后nhibernate抛出一个异常,它无法找到hibernate.cfg.xml,因为我在相对路径中搜索它。

现在,我不想硬编码hibernate.cfg.xml的位置,或者只是将hibernate.cfg.xml复制到ide目录(这将起作用)。我想要一个获取解决方案目录的解决方案,而当前目录是common7 \ ide。可以让某人在设计器中查看我的表单,然后在任意机器上的任意目录中进行新的检查。不,我不打算在代码中加载控件。我在控件中有如此多的控件,如果没有它,将所有内容排成一行都是一场噩梦。

我尝试了一个预构建事件,它创建了一个包含解决方案目录的文件,但当然如何从common7 \ ide中找到它?由于svn。

,所有项目文件都需要位于解决方案目录中

感谢你的帮助,我已经花了几个小时摆弄这个徒劳。

更新:我将hibernate.cfg设置为嵌入式资源。对于每个配置,我只需简单地创建一个新的构建配置,调试,发布,XYZ。在大多数情况下,我建议嵌入您依赖的任何文件来运行程序。它使构建安装程序变得更加简单。

6 个答案:

答案 0 :(得分:18)

这可能有点晚了,但我在http://www.tek-tips.com/viewthread.cfm?qid=1226891&page=164找到了一个解决方案。由于我使用的是Visual Studio 2010,因此我进行了一些小的更改。你必须参考EnvDTE和EnvDTE100(EnvDTE90 for VS2008),

string solutionDirectory = ((EnvDTE.DTE)System.Runtime
                                              .InteropServices
                                              .Marshal
                                              .GetActiveObject("VisualStudio.DTE.10.0"))
                                   .Solution
                                   .FullName;
solutionDirectory = System.IO.Path.GetDirectoryName(solutionDirectory);

当然我使用的是VisualStudio.DTE.10.0,你应该使用VisualStudio.DTE.9.0。

祝你好运!

答案 1 :(得分:9)

我终于想出了这个。这适用于任何Visual Studio版本,不依赖于EnvDTE,并解决了此处提供的原始问题。

  1. 在项目设置中的“构建事件”下,添加以下“预构建事件命令行”:

    echo $(SolutionDir) > ..\..\solutionpath.txt
    
  2. 构建项目一次。该文件将在项目根目录中创建。

  3. 在解决方案资源管理器中,单击“显示所有文件”和“刷新”

  4. 将solutionpath.txt添加到您的解决方案

  5. 右键单击solutionpath.txt,单击属性。将构建操作更改为“嵌入式资源”

  6. 使用以下代码获取解决方案路径。

        string assemblyname = System.Reflection.Assembly.GetExecutingAssembly().GetName().Name;
        string path = "";
        using (var stream = System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream(assemblyname + ".solutionpath.txt"))
        {
            using (var sr = new StreamReader(stream))
            {
                path = sr.ReadToEnd().Trim();
            }
        }
    
  7. 因为这是一个预构建事件,所以在构建开始之前不需要存在该文件,因此它与源代码控制兼容,并且没有任何明显的问题。

答案 2 :(得分:3)

更新:不幸的是,我不知道如何在设计时获取解决方案文件夹。所以,从技术上讲,我没有回答你的问题,只提供一个潜在的解决方法。

您可以检查您的控件是否在DesignMode中,如果是,您可以使用Assembly.GetExecutingAssembly()获取控件的Assembly并确定其加载位置。< / p>

请注意,DesignTime属性值有一些注意事项,即如果您设计控件或者如果您正在设计包含控件的Form,那么它将正确返回,但如果您正在设计包含控件的窗体包含您的控件,它将返回false。

您可能希望跳过整个DesignTime检查,因为如果找到该配置文件的标准方法失败,请始终在程序集的基本路径中查找NHibernate配置。

答案 3 :(得分:2)

听起来你只需要为配置文件编写更好的路径。

如果您这样做:

configPath =  Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "\\PathToCFG");

当Windows更改您当前的目录时,不应该搞砸了。

编辑:您可能遇到了 Visual Studio托管流程的问题。你可以禁用它吗?项目属性\ debug下有一个复选框。

答案 4 :(得分:2)

我最终嵌入了配置文件。由于程序自动更新独立于配置文件,我可以放弃将其暴露给用户。

答案 5 :(得分:0)

我来晚了,我不知道这是否可以在VS2008中使用,但是对于VS2015,我想做的最简单的事情就是创建一个t4模板。这里是内容:

<#@ template debug="false" hostspecific="true" language="C#" #>
<#@ output extension=".generated.cs" #>
namespace MyNamespace
{
    public static class BuildVariables
    {
        public static readonly string SolutionDir = <#= QuotedString(Host.ResolveAssemblyReference(@"$(SolutionDir)")) #>;
    }
}
<#+
public string QuotedString(string value)
{
    if (value == null)
    {
        return "null";
    }

    return "@\"" + value.Replace("\"", "\"\"") + "\"";
}
#>

这将生成一个完全具有所需类的类。我对此有两个警告,请确保从版本控制中忽略它,并注意是否将解决方案复制到其他地方。不幸的是,在自动化构建过程中构建t4模板仍然是2018年的复杂问题。