如何在设计时获取项目路径

发布于 2024-08-25 03:50:05 字数 101 浏览 5 评论 0原文

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

谢谢弗洛里安

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(10

无风消散 2024-09-01 03:50:05

唯一对我来说(一致)有效的事情是获取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在设计时使用的临时路径。

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.

写下不归期 2024-09-01 03:50:05

只需调用 GetMyPath 即可,其定义为

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

Just call GetMyPath which is defined as

string GetMyPath([CallerFilePath] string from = null)
{
   return from;
}
や莫失莫忘 2024-09-01 03:50:05

使用AppDomain.CurrentDomain.BaseDirectory。

Use AppDomain.CurrentDomain.BaseDirectory.

流心雨 2024-09-01 03:50:05

这有效吗?

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

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

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

莳間冲淡了誓言ζ 2024-09-01 03:50:05

看一下:编译时的项目(bin)文件夹路径?

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

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.

爱格式化 2024-09-01 03:50:05

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

这似乎有效:

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

I think Robert is almost right.

This seems to work:

Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
如梦初醒的夏天 2024-09-01 03:50:05
string solutionpath = Directory.GetParent(Application.ExecutablePath).Parent.Parent.Parent.FullName;

我认为这是最好的解决方案,因为您不必添加任何比“Using System.IO”更多的库:)

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

野味少女 2024-09-01 03:50:05

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

在主窗口 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

在此处输入图像描述

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

enter image description here

讽刺将军 2024-09-01 03:50:05

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

详细信息:-
在设计时,您有 modelItem 的实例(我假设它,您知道)如果没有,那么您可以在

DesignAdorner 类中的Activate 方法的 Override 实现 //

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

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

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

让我知道,如果这对你没有帮助。

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.

成熟稳重的好男人 2024-09-01 03:50:05

添加对 .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;
            }
        }
    }

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;
            }
        }
    }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文