How to get the project path at Design Time

强颜欢笑 提交于 2020-01-14 09:07:30

问题


I use a component (System.ComponentModel.Component) and I want to get the application path of my project in order to create a file within it.

Thx

Florian


回答1:


The only thing that seemed to work (consistently) for me was obtaining EnvDTE.DTE (from the IServiceProvider you get from EditValue()), i.e.:

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

When I tried using Assembly.GetXAssembly, I got the temporary path VS uses in design-time.




回答2:


Just call GetMyPath which is defined as

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



回答3:


Use AppDomain.CurrentDomain.BaseDirectory.




回答4:


Does this work?

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

("CallingAssembly" because you can put the method to retrieve the execution path into the service layer (assembly))




回答5:


Take a look at: Project (bin) folder path at compile time?

With this technique you could "Build" (once) and after that use the generated file to get the project location at DesignTime. This would work workspace independent.




回答6:


I think Robert is almost right.

This seems to work:

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



回答7:


string solutionpath = Directory.GetParent(Application.ExecutablePath).Parent.Parent.Parent.FullName;

I think this is the best solution, because you dont have to add any library more than "Using System.IO" :)




回答8:


I did a simple test ( just as a temporary design, I added a string property to hold the current directory value ) ( I do not describe the all process of data binding. See some of my post about design time / run-time binding )

In the empty constructor of the main window ViewModel class ( dedicated to design time binding )

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

In the mainwindow.xaml file I added a textbox to display the result ( don't mind the grid row value )

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

And I got in the design view of VS ( like Florian's comment stated , but with a newer value 4 years after): C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE




回答9:


If you are talking about WPF designer, please use "Context" property/type

Details:- In Design time you have instance of modelItem (I assume it, you know it) if not then you can instantiate it in Override implementation of Activate method

// in DesignAdorner class

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

Now you can access the current application path using following single line code

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

Let me know, if it does not help you.




回答10:


Add a reference to envdte80 which is in .NetFrameWork 4.5 Assemblies.

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;
            }
        }
    }


来源:https://stackoverflow.com/questions/2425944/how-to-get-the-project-path-at-design-time

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!