Visual Studio T4 使用DTE 打开生成的文件时出现序列化错误
Visual Studio serialization error when T4 uses DTE to open generated file
我们有一个名为 GenerateProxies.tt 的 C# T4 文件,它调用了几个命令行代码生成实用程序。使用 System.Diagnostics 进程 class,我们将标准输出重定向到 T4 输出文本文件 (GenerateProxies.txt),以便我们可以检查命令行输出是否有错误。
我在 T4 的末尾添加了以下简单代码,以便 Visual Studio 将打开生成的文本文件作为该过程的最后一步(workingDirectory
变量已在前面声明和填充在模板中)。这确实有效,但会引发序列化错误。这个错误可以避免吗?
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#
IServiceProvider vssp = (IServiceProvider)this.Host;
DTE dte = vssp.GetService(typeof(DTE)) as DTE;
dte.ItemOperations.OpenFile(
string.Format(@"{0}\GenerateProxies.txt", workingDirectory),
Constants.vsViewKindTextView
);
#>
同样,这个 确实 工作,它打开了文本文件,但它生成了这个错误:
Running transformation: System.Runtime.Serialization.SerializationException:
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement'
is not marked as serializable.
这不是答案,但是 OP 无法提供评论中要求的堆栈跟踪。
当我尝试在我的 tt 文件中执行一个函数以写入输出时,我抛出了类似的异常 window(ST 太长,无法评论)
private void WriteToOutput(string output)
{
if (_host == null)
throw new Exception("Host property returned unexpected value (null)");
EnvDTE.DTE dte = (EnvDTE.DTE)_host.GetService(typeof(EnvDTE.DTE));
if (dte == null)
throw new Exception("Unable to retrieve DTE");
Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
window.Activate();
var outputWindow = (EnvDTE.OutputWindow) window.Object;
outputWindow.ActivePane.Activate();
outputWindow.ActivePane.OutputString(output);
outputWindow.ActivePane.OutputString("\n");
}
Severity Code Description Project File Line Suppression State
Error Running transformation:
System.Runtime.Serialization.SerializationException: Type
'Microsoft.VisualStudio.Platform.WindowManagement.DTE.Windows' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement,
Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is
not marked as serializable.
Server stack trace: at
System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType
type) at
System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type
type, StreamingContext context) at
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo()
at
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object
obj, ISurrogateSelector surrogateSelector, StreamingContext context,
SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter,
ObjectWriter objectWriter, SerializationBinder binder) at
System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object
obj, ISurrogateSelector surrogateSelector, StreamingContext context,
SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter,
ObjectWriter objectWriter, SerializationBinder binder) at
System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object
graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream
serializationStream, Object graph, Header[] headers, Boolean fCheck)
at
System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList
argsToSerialize) at
System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage..ctor(IMethodReturnMessage
mrm) at
System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage.SmuggleIfPossible(IMessage
msg) at
System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[]
reqStmBuff, SmuggledMethodCallMessage smuggledMcm,
SmuggledMethodReturnMessage& smuggledMrm) at
System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[]
args)
Exception rethrown at [0]: at
System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage
reqMsg, IMessage retMsg) at
System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData&
msgData, Int32 type) at EnvDTE._DTE.get_Windows() at
Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.WriteToOutput(String
output) in C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line 581
at
Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.GetItemsToGenerate[T](IEnumerable`1
itemCollection) in
C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line 566 at
Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TransformText()
in C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line
33 C:\ViewModels\BaseGridViewModels\BaseViewModels.tt 581
EnvDTE 程序集是 COM 互操作程序集。通过创建 Runtime Callable Wrapper 可以避免您的错误,它根据互操作程序集中的信息编组对 COM 对象的调用。微软在
Microsoft.VisualStudio.TextTemplating
命名空间:
<#@ template hostspecific="true" language="C#" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#>
T4 模板 运行 在一个单独的 AppDomain 中,我相信这就是您的代码尽管存在异常但仍能正常工作的原因。 IServiceProvider.GetService(typeof(DTE))
returns一个透明的Proxy Object。此异常是因为代理要求跨应用程序域的对象使用 Serializable
属性进行修饰。您可以确认代码中的 DTE 对象是 "transparent proxy",如下所示:
bool isProxy = RemotingServices.IsTransparentProxy(dte);
我们有一个名为 GenerateProxies.tt 的 C# T4 文件,它调用了几个命令行代码生成实用程序。使用 System.Diagnostics 进程 class,我们将标准输出重定向到 T4 输出文本文件 (GenerateProxies.txt),以便我们可以检查命令行输出是否有错误。
我在 T4 的末尾添加了以下简单代码,以便 Visual Studio 将打开生成的文本文件作为该过程的最后一步(workingDirectory
变量已在前面声明和填充在模板中)。这确实有效,但会引发序列化错误。这个错误可以避免吗?
<#@ assembly name="EnvDTE" #>
<#@ import namespace="EnvDTE" #>
<#
IServiceProvider vssp = (IServiceProvider)this.Host;
DTE dte = vssp.GetService(typeof(DTE)) as DTE;
dte.ItemOperations.OpenFile(
string.Format(@"{0}\GenerateProxies.txt", workingDirectory),
Constants.vsViewKindTextView
);
#>
同样,这个 确实 工作,它打开了文本文件,但它生成了这个错误:
Running transformation: System.Runtime.Serialization.SerializationException:
Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.WindowBase' in
Assembly 'Microsoft.VisualStudio.Platform.WindowManagement'
is not marked as serializable.
这不是答案,但是 OP 无法提供评论中要求的堆栈跟踪。
当我尝试在我的 tt 文件中执行一个函数以写入输出时,我抛出了类似的异常 window(ST 太长,无法评论)
private void WriteToOutput(string output)
{
if (_host == null)
throw new Exception("Host property returned unexpected value (null)");
EnvDTE.DTE dte = (EnvDTE.DTE)_host.GetService(typeof(EnvDTE.DTE));
if (dte == null)
throw new Exception("Unable to retrieve DTE");
Window window = dte.Windows.Item(EnvDTE.Constants.vsWindowKindOutput);
window.Activate();
var outputWindow = (EnvDTE.OutputWindow) window.Object;
outputWindow.ActivePane.Activate();
outputWindow.ActivePane.OutputString(output);
outputWindow.ActivePane.OutputString("\n");
}
Severity Code Description Project File Line Suppression State Error Running transformation: System.Runtime.Serialization.SerializationException: Type 'Microsoft.VisualStudio.Platform.WindowManagement.DTE.Windows' in Assembly 'Microsoft.VisualStudio.Platform.WindowManagement, Version=15.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a' is not marked as serializable.
Server stack trace: at System.Runtime.Serialization.FormatterServices.InternalGetSerializableMembers(RuntimeType type) at System.Runtime.Serialization.FormatterServices.GetSerializableMembers(Type type, StreamingContext context) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitMemberInfo() at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.InitSerialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) at System.Runtime.Serialization.Formatters.Binary.WriteObjectInfo.Serialize(Object obj, ISurrogateSelector surrogateSelector, StreamingContext context, SerObjectInfoInit serObjectInfoInit, IFormatterConverter converter, ObjectWriter objectWriter, SerializationBinder binder) at System.Runtime.Serialization.Formatters.Binary.ObjectWriter.Serialize(Object graph, Header[] inHeaders, __BinaryWriter serWriter, Boolean fCheck)
at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Serialize(Stream serializationStream, Object graph, Header[] headers, Boolean fCheck)
at System.Runtime.Remoting.Channels.CrossAppDomainSerializer.SerializeMessageParts(ArrayList argsToSerialize) at System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage..ctor(IMethodReturnMessage mrm) at System.Runtime.Remoting.Messaging.SmuggledMethodReturnMessage.SmuggleIfPossible(IMessage msg) at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoDispatch(Byte[] reqStmBuff, SmuggledMethodCallMessage smuggledMcm, SmuggledMethodReturnMessage& smuggledMrm) at System.Runtime.Remoting.Channels.CrossAppDomainSink.DoTransitionDispatchCallback(Object[] args)Exception rethrown at [0]: at System.Runtime.Remoting.Proxies.RealProxy.HandleReturnMessage(IMessage reqMsg, IMessage retMsg) at System.Runtime.Remoting.Proxies.RealProxy.PrivateInvoke(MessageData& msgData, Int32 type) at EnvDTE._DTE.get_Windows() at Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.WriteToOutput(String output) in C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line 581 at Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TypeMapper.GetItemsToGenerate[T](IEnumerable`1 itemCollection) in C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line 566 at Microsoft.VisualStudio.TextTemplating8CBB5A87F4A34D52835396F51C533E1D8E9F22BC6977A9510B46C012D01E08C8AD263AC5BA030600D92BC0F39E7F1C3B6AA67D8CE545627E10A7F993E06C0D02.GeneratedTextTransformation.TransformText() in C:\ViewModels\BaseGridViewModels\BaseViewModels.tt:line 33 C:\ViewModels\BaseGridViewModels\BaseViewModels.tt 581
EnvDTE 程序集是 COM 互操作程序集。通过创建 Runtime Callable Wrapper 可以避免您的错误,它根据互操作程序集中的信息编组对 COM 对象的调用。微软在
Microsoft.VisualStudio.TextTemplating
命名空间:
<#@ template hostspecific="true" language="C#" #>
<#@ assembly name="EnvDTE" #>
<#@ import namespace="Microsoft.VisualStudio.TextTemplating" #>
<#
IServiceProvider serviceProvider = (IServiceProvider)this.Host;
EnvDTE.DTE dte = (EnvDTE.DTE) serviceProvider.GetCOMService(typeof(EnvDTE.DTE));
#>
T4 模板 运行 在一个单独的 AppDomain 中,我相信这就是您的代码尽管存在异常但仍能正常工作的原因。 IServiceProvider.GetService(typeof(DTE))
returns一个透明的Proxy Object。此异常是因为代理要求跨应用程序域的对象使用 Serializable
属性进行修饰。您可以确认代码中的 DTE 对象是 "transparent proxy",如下所示:
bool isProxy = RemotingServices.IsTransparentProxy(dte);