提交 ffa8c0ca 编写于 作者: A Andy Gocke

Add host object back to the Roslyn MSBuild tasks

上级 8d85a879
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using Microsoft.Build.Tasks.Hosting;
namespace Microsoft.CodeAnalysis.BuildTasks
{
/*
* Interface: ICscHostObject5
* Owner:
*
* Defines an interface for the Csc task to communicate with the IDE. In particular,
* the Csc task will delegate the actual compilation to the IDE, rather than shelling
* out to the command-line compilers.
*
*/
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
[Guid("E113A674-3F6C-4514-B7AD-1E59226A1C50")]
public interface ICscHostObject5 : ICscHostObject4
{
bool SetErrorLog(string errorLogFile);
bool SetReportAnalyzer(bool reportAnalyzerInDiagnosticOutput);
}
}
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using Microsoft.Build.Tasks.Hosting;
namespace Microsoft.CodeAnalysis.BuildTasks
{
/// <summary>
/// Defines an interface that proffers a free threaded host object that
/// allows for background threads to call directly (avoids marshalling
/// to the UI thread.
/// </summary>
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
[ComVisible(true)]
[Guid("10617623-DD4E-4E81-B4C3-46F55DC76E52")]
public interface IVbcHostObject6 : IVbcHostObject5
{
bool SetErrorLog(string errorLogFile);
bool SetReportAnalyzer(bool reportAnalyzerInDiagnosticOutput);
}
}
......@@ -59,9 +59,12 @@
<DesignTime>True</DesignTime>
<DependentUpon>ErrorString.resx</DependentUpon>
</Compile>
<Compile Include="ICscHostObject5.cs" />
<Compile Include="IVbcHostObject6.cs" />
<Compile Include="ManagedCompiler.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="PropertyDictionary.cs" />
<Compile Include="RCWForCurrentContext.cs" />
<Compile Include="Utilities.cs" />
<Compile Include="Vbc.cs" />
</ItemGroup>
......
// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Runtime.InteropServices;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis.BuildTasks
{
/// <summary>
/// Create an RCW for the current context/apartment.
/// This improves performance of cross apartment calls as the CLR will only
/// cache marshalled pointers for an RCW created in the current context.
/// </summary>
/// <typeparam name="T">Type of the RCW object</typeparam>
internal class RCWForCurrentContext<T> : IDisposable where T : class
{
/// <summary>
/// The last RCW that was created for the current context.
/// </summary>
private T _rcwForCurrentCtx;
/// <summary>
/// Indicates if we created the RCW and therefore need to release it's com reference.
/// </summary>
private bool _shouldReleaseRCW;
/// <summary>
/// Constructor creates the new RCW in the current context.
/// </summary>
/// <param name="rcw">The RCW created in the original context.</param>
public RCWForCurrentContext(T rcw)
{
// To improve performance we create a new RCW for the current context so we get
// the caching behaviour of the marshaled pointer.
// See RCW::GetComIPForMethodTableFromCache in ndp\clr\src\VM\RuntimeCallableWrapper.cpp
IntPtr iunknownPtr = Marshal.GetIUnknownForObject(rcw);
Object objInCurrentCtx = null;
try
{
objInCurrentCtx = Marshal.GetObjectForIUnknown(iunknownPtr);
}
finally
{
Marshal.Release(iunknownPtr);
}
Debug.Assert(objInCurrentCtx != null, "Unable to marshal COM Object to the current context (apartment). This will hurt performance.");
// If we failed to create the new RCW we default to returning the original RCW.
if (objInCurrentCtx == null)
{
_shouldReleaseRCW = false;
_rcwForCurrentCtx = rcw;
}
else
{
_shouldReleaseRCW = true;
_rcwForCurrentCtx = objInCurrentCtx as T;
}
}
/// <summary>
/// Finalizer
/// </summary>
~RCWForCurrentContext()
{
Debug.Fail("This object requires explicit call to Dispose");
CleanupComObject();
}
/// <summary>
/// Call this helper if your managed object is really an RCW to a COM object
/// and that COM object was created in a different apartment from where it is being accessed
/// </summary>
/// <returns>A new RCW created in the current apartment context</returns>
public T RCW
{
get
{
if (null == _rcwForCurrentCtx)
{
throw new ObjectDisposedException("RCWForCurrentCtx");
}
return _rcwForCurrentCtx;
}
}
/// <summary>
/// Override for IDisposable::Dispose
/// </summary>
/// <remarks>
/// We created an RCW for the current apartment. When this object goes out of scope
/// we need to release the COM object before the apartment is released (via COUninitialize)
/// </remarks>
public void Dispose()
{
CleanupComObject();
GC.SuppressFinalize(this);
}
/// <summary>
/// Cleanup our RCW com object references if required.
/// </summary>
private void CleanupComObject()
{
try
{
if (null != _rcwForCurrentCtx &&
_shouldReleaseRCW &&
Marshal.IsComObject(_rcwForCurrentCtx))
{
Marshal.ReleaseComObject(_rcwForCurrentCtx);
}
}
finally
{
_rcwForCurrentCtx = null;
}
}
}
}
......@@ -13,6 +13,14 @@ namespace Microsoft.CodeAnalysis.BuildTasks
/// </summary>
internal static class Utilities
{
internal static bool IsCriticalException(Exception e)
{
return e is StackOverflowException
|| e is AccessViolationException
|| e is AppDomainUnloadedException
|| e is BadImageFormatException
|| e is DivideByZeroException;
}
/// <summary>
/// Convert a task item metadata to bool. Throw an exception if the string is badly formed and can't
/// be converted.
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册