Created
October 1, 2015 12:15
-
-
Save stuartd/ca96771b6324ef172047 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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