【问题标题】:How to get the project path at Design Time如何在设计时获取项目路径
【发布时间】:2011-01-26 10:12:02
【问题描述】:

我使用一个组件 (System.ComponentModel.Component),我想获取我的项目的应用程序路径,以便在其中创建一个文件。

谢谢

弗洛里安

【问题讨论】:

  • 您是在 windows 窗体还是 wpf 中工作?

标签: c# path components design-time


【解决方案1】:

对我来说,唯一似乎(始终如一)有效的是获取 EnvDTE.DTE(从您从 EditValue() 获得的 IServiceProvider),即:

EnvDTE.DTE dte = envProvider.GetService(typeof(EnvDTE.DTE)) as EnvDTE.DTE;
string dir = Path.GetDirectoryName(dte.Solution.FullName);

当我尝试使用 Assembly.GetXAssembly 时,我得到了 VS 在设计时使用的临时路径。

【讨论】:

  • 我相信你是对的。但可以让它在 VB 中工作。
【解决方案2】:

只需调用 GetMyPath 定义为

string GetMyPath([CallerFilePath] string from = null)
{
   return from;
}

【讨论】:

    【解决方案3】:

    使用 AppDomain.CurrentDomain.BaseDirectory。

    【讨论】:

    • 它不起作用。当我拖动具有此方法的组件时: public override void InitializeNewComponent(IDictionary defaultValues) { MessageBox.Show(AppDomain.CurrentDomain.BaseDirectory);消息框出现:C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\
    • 我建议你用VS测试应用程序?
    【解决方案4】:

    这行得通吗?

     New Uri(Assembly.GetCallingAssembly().CodeBase).AbsolutePath
    

    ("CallingAssembly" 因为你可以把检索执行路径的方法放到服务层(程序集))

    【讨论】:

    • 它不起作用:这里的结果 C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll
    【解决方案5】:

    看看:Project (bin) folder path at compile time?

    使用这种技术,您可以“构建”(一次),然后使用生成的文件在设计时获取项目位置。这将独立于工作空间。

    【讨论】:

      【解决方案6】:

      我认为罗伯特几乎是对的。

      这似乎有效:

      Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
      

      【讨论】:

      • 这会在设计时返回临时 VS 路径
      【解决方案7】:
      string solutionpath = Directory.GetParent(Application.ExecutablePath).Parent.Parent.Parent.FullName;
      

      我认为这是最好的解决方案,因为除了“Using System.IO”之外,您无需添加任何库:)

      【讨论】:

        【解决方案8】:

        我做了一个简单的测试(只是作为一个临时设计,我添加了一个字符串属性来保存当前目录值)(我没有描述数据绑定的所有过程。看看我的一些关于设计时/运行时绑定的帖子)

        在主窗口ViewModel类的空构造函数中(专用于设计时绑定)

        public MainWindow_ViewModel():this(null)
        {
            dtpath = Directory.GetCurrentDirectory();
            Console.WriteLine("CTor finished");
        }
        

        在 mainwindow.xaml 文件中,我添加了一个文本框来显示结果(不要介意网格行值)

        <TextBox Text="{Binding dtpath}" Grid.Row="3"/>
        

        我进入了 VS 的设计视图(就像 Florian 的评论所述,但 4 年后具有更新的值): C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE

        【讨论】:

          【解决方案9】:

          如果您在谈论 WPF 设计器,请使用“上下文”属性/类型

          详情:- 在设计时你有 modelItem 的实例(我假设它,你知道的)如果没有,那么你可以在 Activate 方法的 Override 实现中实例化它

          //在DesignAdorner类中

          public class DesignAdorner : PrimarySelectionAdornerProvider
          {
                protected override void Activate(ModelItem item)
                  {
                          modelItem = item;
                  }
          }
          

          现在您可以使用以下单行代码访问当前应用程序路径

          string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName;
          

          如果对您没有帮助,请告诉我。

          【讨论】:

            【解决方案10】:

            添加对 .NetFrameWork 4.5 组件中的 envdte80 的引用。

            DTE2 dte = DesignTimeProjectPath.Processes.GetDTE();
                if (dte != null)
                 {
                    var solution = dte.Solution;
                    if (solution != null)
                     {
                         string baseDir = Path.GetDirectoryName(solution.FullName);
                         MessageBox.Show(baseDir);
                     }
                 }
            
              namespace DesignTimeProjectPath
                {
                    /// <summary>
                    /// This class takes care of fetching the correct DTE instance for the current process
                    /// The current implementation works it way down from Visual Studio version 20 to 10 so
                    /// it should be farely version independent
                    /// </summary>
                    public static class Processes
                    {
                        [DllImport("ole32.dll")]
                        private static extern void CreateBindCtx(int reserved, out IBindCtx ppbc);
                        [DllImport("ole32.dll")]
                        private static extern void GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
            
                        private const int m_MaxVersion = 20;
                        private const int m_MinVersion = 10;
            
                        internal static DTE2 GetDTE()
                        {
                            DTE2 dte = null;
            
                            for (int version = m_MaxVersion; version >= m_MinVersion; version--)
                            {
                                string versionString = string.Format("VisualStudio.DTE.{0}.0", version);
            
                                dte = Processes.GetCurrent(versionString);
            
                                if (dte != null)
                                {
                                    return dte;
                                }
                            }
            
                            throw new Exception(string.Format("Can not get DTE object tried versions {0} through {1}", m_MaxVersion, m_MinVersion));
                        }
            
                        /// <summary>
                        /// When multiple instances of Visual Studio are running there also multiple DTE available
                        /// The method below takes care of selecting the right DTE for the current process
                        /// </summary>
                        /// <remarks>
                        /// Found this at: http://stackoverflow.com/questions/4724381/get-the-reference-of-the-dte2-object-in-visual-c-sharp-2010/27057854#27057854
                        /// </remarks>
                        private static DTE2 GetCurrent(string versionString)
                        {
                            Process parentProc = GetParent(Process.GetCurrentProcess());
                            int parentProcId = parentProc.Id;
                            string rotEntry = String.Format("!{0}:{1}", versionString, parentProcId);
            
                            IRunningObjectTable rot;
                            GetRunningObjectTable(0, out rot);
            
                            IEnumMoniker enumMoniker;
                            rot.EnumRunning(out enumMoniker);
                            enumMoniker.Reset();
            
                            IntPtr fetched = IntPtr.Zero;
                            IMoniker[] moniker = new IMoniker[1];
            
                            while (enumMoniker.Next(1, moniker, fetched) == 0)
                            {
                                IBindCtx bindCtx;
                                CreateBindCtx(0, out bindCtx);
                                string displayName;
                                moniker[0].GetDisplayName(bindCtx, null, out displayName);
            
                                if (displayName == rotEntry)
                                {
                                    object comObject;
            
                                    rot.GetObject(moniker[0], out comObject);
            
                                   return (EnvDTE80.DTE2)comObject;
                                }
                            }
            
                            return null;
                        }
            
                        private static Process GetParent(Process process)
                        {
                            var processName = process.ProcessName;
                            var nbrOfProcessWithThisName = Process.GetProcessesByName(processName).Length;
                            for (var index = 0; index < nbrOfProcessWithThisName; index++)
                            {
                                var processIndexdName = index == 0 ? processName : processName + "#" + index;
                                var processId = new PerformanceCounter("Process", "ID Process", processIndexdName);
                                if ((int)processId.NextValue() == process.Id)
                                {
                                    var parentId = new PerformanceCounter("Process", "Creating Process ID", processIndexdName);
                                    return Process.GetProcessById((int)parentId.NextValue());
                                }
                            }
                            return null;
                        }
                    }
                }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2014-11-20
              • 2016-08-24
              • 1970-01-01
              • 1970-01-01
              • 1970-01-01
              • 2017-04-07
              • 2019-05-15
              相关资源
              最近更新 更多