可能有更好的方法,但我简单尝试了一下,发现这个方法可行(它假设您知道解决方案名称)。根据这篇文章,GetActiveObject
不能保证获取当前实例的VS,所以你得到的结果是来自另一个实例。相反,您可以使用那里显示的GetDTE
方法:
[DllImport("ole32.dll")]
private static extern int CreateBindCtx(uint reserved, out IBindCtx ppbc);
public static DTE GetDTE(int processId)
}
catch (UnauthorizedAccessException)
if (!string.IsNullOrEmpty(name) && string.Equals(name, progId, StringComparison.Ordinal))
}
}
finally
if (rot != null)
if (bindCtx != null)
}
return (DTE)runningObject;
}
如果您事先知道解决方案名称,则可以在进程
的MainWindowTitle
属性中找到它,并将ProcessID
传递给上面的方法。
var dte = GetDTE(System.Diagnostics.Process.GetProcesses().Where(x => x.MainWindowTitle.StartsWith("SolutionName") && x.ProcessName.Contains("devenv")).FirstOrDefault().Id);
虽然上面的代码可以工作,但我遇到了一个COM错误,通过使用这里显示的MessageFilter
类进行修复。
从那篇文章中,这就是MessageFilter
类的样子。
public class MessageFilter : IOleMessageFilter
{
public static void Register()
{
IOleMessageFilter newFilter = new MessageFilter();
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}
int IOleMessageFilter.HandleInComingCall(int dwCallType,
System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr lpInterfaceInfo)
{
return 0;
}
int IOleMessageFilter.RetryRejectedCall(System.IntPtr
hTaskCallee, int dwTickCount, int dwRejectType)
{
if (dwRejectType == 2)
{
return 99;
}
return -1;
}
int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
int dwTickCount, int dwPendingType)
{
return 2;
}
[DllImport("Ole32.dll")]
private static extern int
CoRegisterMessageFilter(IOleMessageFilter newFilter, out
IOleMessageFilter oldFilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
interface IOleMessageFilter
{
[PreserveSig]
int HandleInComingCall(
int dwCallType,
IntPtr hTaskCaller,
int dwTickCount,
IntPtr lpInterfaceInfo);
[PreserveSig]
int RetryRejectedCall(
IntPtr hTaskCallee,
int dwTickCount,
int dwRejectType);
[PreserveSig]
int MessagePending(
IntPtr hTaskCallee,
int dwTickCount,
int dwPendingType);
}
然后您可以像这样访问项目名称。
var dte = GetDTE(System.Diagnostics.Process.GetProcesses().Where(x => x.MainWindowTitle.StartsWith("SolutionName") && x.ProcessName.Contains("devenv")).FirstOrDefault().Id);
MessageFilter.Register();
var projects = dte.Solution.OfType<Project>().ToList();
MessageFilter.Revoke();
foreach (var proj in projects)
Marshal.ReleaseComObject(dte);