Skip to content

Instantly share code, notes, and snippets.

@stuartd
Created October 1, 2015 12:15
Show Gist options
  • Save stuartd/ca96771b6324ef172047 to your computer and use it in GitHub Desktop.
Save stuartd/ca96771b6324ef172047 to your computer and use it in GitHub Desktop.
using System;
using System.Runtime.InteropServices;
using System.Threading;
using EnvDTE;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace DteTestClassNamespace
{
[TestClass]
public class DteTestClass
{
// Adjust for version
private static readonly Type visualStudioDteType = Type.GetTypeFromProgID("VisualStudio.DTE.12.0", true);
private static DTE dte;
[ClassInitialize]
public static void Setup(TestContext context)
{
StartDTE();
/* other setup things */
}
[ClassCleanup]
public static void Teardown()
{
StopDTE();
}
[TestInitialize]
public void TestSetup()
{
// Force tests to run one at a time
Monitor.Enter(LockClass.LockObject);
}
[TestCleanup]
public void TestCleanup()
{
Monitor.Exit(LockClass.LockObject);
}
private static void StartDTE()
{
dte = (DTE) Activator.CreateInstance(visualStudioDteType, true);
dte.SuppressUI = true;
dte.UserControl = false;
OLEMessageFilter.Register();
try
{
dte.ExecuteCommand("ReSharper_Suspend");
}
catch
{
// ignored
}
}
private static void StopDTE()
{
OLEMessageFilter.Revoke();
try
{
try
{
dte.ExecuteCommand("ReSharper_Resume");
}
catch
{
// ignored
}
try
{
dte.Quit();
}
catch (Exception ex)
{
Console.WriteLine("Failed to quit: " + ex);
}
}
catch (Exception e)
{
Console.Error.WriteLine(e);
}
}
private static class LockClass
{
public static readonly object LockObject = new object();
}
/// <remarks>Stops OLE Errors and UI hanging when loading large solutions
///
/// https://msdn.microsoft.com/en-us/library/vstudio/ms228772%28v=vs.110%29.aspx
///
/// </remarks>
private class OLEMessageFilter : IOleMessageFilter
{
// Class containing the IOleMessageFilter
// thread error-handling functions.
// Start the filter.
public static void Register()
{
IOleMessageFilter newFilter = new OLEMessageFilter();
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(newFilter, out oldFilter);
}
// Done with the filter, close it.
public static void Revoke()
{
IOleMessageFilter oldFilter = null;
CoRegisterMessageFilter(null, out oldFilter);
}
// IOleMessageFilter functions.
// Handle incoming thread requests.
int IOleMessageFilter.HandleInComingCall(int dwCallType,
IntPtr hTaskCaller, int dwTickCount, IntPtr lpInterfaceInfo)
{
//Return the flag SERVERCALL_ISHANDLED.
return 0;
}
// Thread call was rejected, so try again.
int IOleMessageFilter.RetryRejectedCall(IntPtr
hTaskCallee, int dwTickCount, int dwRejectType)
{
if (dwRejectType == 2)
// flag = SERVERCALL_RETRYLATER.
{
// Retry the thread call immediately if return >=0 &
// <100.
return 99;
}
// Too busy; cancel call.
return -1;
}
int IOleMessageFilter.MessagePending(IntPtr hTaskCallee, int dwTickCount, int dwPendingType)
{
//Return the flag PENDINGMSG_WAITDEFPROCESS.
return 2;
}
// Implement the IOleMessageFilter interface.
[DllImport("Ole32.dll")]
private static extern int
CoRegisterMessageFilter(IOleMessageFilter newFilter, out IOleMessageFilter oldFilter);
}
[ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
InterfaceType(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);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment