问题
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