开发者

How to get the project path at Design Time

开发者 https://www.devze.com 2022-12-22 10:46 出处:网络
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.

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


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.


Just call GetMyPath which is defined as

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


Use AppDomain.CurrentDomain.BaseDirectory.


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))


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.


I think Robert is almost right.

This seems to work:

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


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" :)


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

How to get the project path at Design Time


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.


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

精彩评论

暂无评论...
验证码 换一张
取 消