C# – “The handle is invalid” exception in Visual Studio 2015 test runner

cnetunit testingvisual studiovisual-studio-2015

I found that one of my tests that passes in VS2013 is failing in VS2015, the test calls a service that includes among other things a call to Console.Clear();

to find out whats going on I made a simple unit test

   [TestMethod]
    public void ExampleTest()
    {
        Console.Clear();
    }

This test passes in visual studio 2013 but in 2015 I get the following error:

Test Name: ExampleTest
Test FullName: solution.Common.Test.CacheManagerTest.ExampleTest
Test Source: C:\solution.Common.Test\CacheManagerTest.cs : line 34
Test Outcome: Failed
Test Duration: 0:00:00.3015003

Result StackTrace: at System.IO.__Error.WinIOError(Int32 errorCode,
String maybeFullPath) at System.Console.GetBufferInfo(Boolean
throwOnNoConsole, Boolean& succeeded) at System.Console.Clear()
at sol.Common.Test.CacheManagerTest.ExampleTest() in
C:\solution.Common.Test\CacheManagerTest.cs:line 35 Result Message:
Test method Alexandria.Common.Test.CacheManagerTest.ExampleTest threw
exception: System.IO.IOException: The handle is invalid.

I do understand that it is bad design for my service to fail if it is not called by a console. The reason I am asking this question is to understand why this is failing in the new version of Visual Studio. Is this the intended behavior? What changed?

I did not see anything obvious in the change log that would seem related to this.

Edit: I am calling the Console.clear from the following dll

Microsoft\Framework.NETFramework\v4.5.1\mscorlib.dll

Edit 2:

picture of testproject properties in both visual studios
both visual studios

Best Answer

The changes in VS2015 are pretty visible, use the Test > Debug > All Tests to get insight. You can see that it now has a new test host process, its name is TE.ProcessHost.Managed.exe, stored in the C:\Program Files (x86)\Microsoft Visual Studio 14.0\Common7\IDE\CommonExtensions\Microsoft\TestWindow directory.

Previous versions of VS used a different host, vstest.executionengine.exe. One notable change in the new test host is that it is no longer a console mode program. Something you can see by running Dumpbin.exe /headers on the exe.

Another way to see the underlying problem is with Task Manager. Note how running a test in an older VS version causes a conhost.exe process to get added. This is the process that owns the console window for a console mode app. A problem I've seen before is that this process tends to leak, not terminating when the test completes. Adding ever more conhost.exe instances, at one point researching this problem I had 12 of them running. Presumably the changes in VS2015 were meant to address that problem.

Technically you can configure the unit test with a .runsettings file and use the <ForcedLegacyMode> element to force the old test host process to be used. This however has no effect on the outcome of this test, looks like they addressed this in multiple ways.

That's a fair amount of guessing, I recommend you use connect.microsoft.com to file a feedback report. You can quote this Q+A for reference.


Meanwhile, you can consider a workaround. Do note that Console.Clear() is in general a trouble-maker, it will also fail in normal usage when the output of a console mode app is redirected. Very easy to do from a command line prompt with the > operator. Which is the ultimate reason it fails in a unit test. You'll want to make the code resilient so it can work properly both in production and in a unit test. Like this:

    if (!Console.IsOutputRedirected) Console.Clear();

Which requires targeting .NET 4.5 or higher. You can use the code in this SO post if you need to target earlier versions.