我使用一个组件(System.ComponentModel.Component),我想获取我的项目的应用程序路径,以便在其中创建一个文件。
谢谢
弗洛里安
我使用一个组件(System.ComponentModel.Component),我想获取我的项目的应用程序路径,以便在其中创建一个文件。
谢谢
弗洛里安
对我来说似乎唯一有效(始终如一)的是获得 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 在设计时使用的临时路径。
只需调用 GetMyPath 定义为
string GetMyPath([CallerFilePath] string from = null)
{
return from;
}
我认为罗伯特几乎是对的。
这似乎有效:
Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location)
使用这种技术,您可以“构建”(一次),然后使用生成的文件在设计时获取项目位置。这将独立于工作空间。
string solutionpath = Directory.GetParent(Application.ExecutablePath).Parent.Parent.Parent.FullName;
我认为这是最好的解决方案,因为除了“使用 System.IO”之外,您无需添加任何库:)
使用 AppDomain.CurrentDomain.BaseDirectory。
这行得通吗?
New Uri(Assembly.GetCallingAssembly().CodeBase).AbsolutePath
(“CallingAssembly”是因为可以将检索执行路径的方法放到服务层(程序集)中)
如果您在谈论 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;
让我知道,如果它没有帮助你。
我做了一个简单的测试(只是作为一个临时设计,我添加了一个字符串属性来保存当前目录值)(我没有描述数据绑定的所有过程。请参阅我的一些关于设计时/运行时绑定的帖子)
在主窗口 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
添加对 .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;
}
}
}