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

5

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

谢谢

弗洛里安


你是在使用Windows Forms还是WPF工作? - Terry
10个回答

5

对于我来说唯一似乎起作用(始终如一)的是获取EnvDTE.DTE(从EditValue()中获取的IServiceProvider),即:

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

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

我相信你是对的。但是我只能在VB中让它工作。 - GameAlchemist

3
只需调用定义为 GetMyPath 的函数即可。
string GetMyPath([CallerFilePath] string from = null)
{
   return from;
}

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

我认为这是最好的解决方案,因为你不需要添加任何库,只需使用 "Using System.IO" :)


0
如果您正在谈论WPF设计师,请使用“Context”属性/类型。
详情: 在设计时,您拥有modelItem的实例(我假设您知道它),如果不知道,则可以在Activate方法的覆盖实现中进行实例化。
// 在DesignAdorner类中
public class DesignAdorner : PrimarySelectionAdornerProvider
{
      protected override void Activate(ModelItem item)
        {
                modelItem = item;
        }
}

现在,您可以使用以下单行代码访问当前应用程序路径。
string aplicationPathDir = System.IO.Directory.GetParent(modelItem.Context.ToString()).FullName;

如果这不能帮到你,请告诉我。


0

这个可以工作吗?

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

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


2
无法运行:这里是结果 C:/Windows/assembly/GAC_MSIL/System.Drawing/2.0.0.0__b03f5f7f11d50a3a/System.Drawing.dll - Florian

0

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

这似乎有效:

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

2
这将在设计时返回临时的VS路径。 - Alex Wiese

0

在.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: https://dev59.com/km445IYBdhLWcg3wucmo#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
使用 AppDomain.CurrentDomain.BaseDirectory。

2
它不起作用。当我拖动具有此方法的组件时:public override void InitializeNewComponent(IDictionary defaultValues) { MessageBox.Show(AppDomain.CurrentDomain.BaseDirectory); }显示消息框,其中包含:C:\Program Files (x86)\Microsoft Visual Studio 8\Common7\IDE\ - Florian
我建议您使用VS测试应用程序? - sashaeve

0

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

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


0

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

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

enter image description here


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接