我有一个自定义的msbuild任务,这个命令:
var workspace = Workspace.LoadStandAloneProject(csprojPath);
当我运行它时,会抛出以下错误:
System.InvalidCastException由用户代码未处理 消息=无法转换透明代理键入“Roslyn.Utilities.SerializableDataStorage”。 来源= Roslyn.Services 堆栈跟踪: 在Roslyn.Utilities.RemoteServices.CreateInstance [T]() 在Roslyn.Services.Host.TemporaryStorageServiceFactory.CreateService(IWorkspaceServiceProvider workspaceServices) 在Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.c__DisplayClass7.b__4() 在Roslyn.Utilities.NonReentrantLazy`1.get_Value() 在Roslyn.Services.Host.WorkspaceServiceProviderFactory.Provider.GetService [TWorkspaceService]() 在Roslyn.Services.SolutionServices..ctor(IWorkspaceServiceProvider workspaceServices,ILanguageServiceProviderFactory languageServicesFactory) (SolutionId id,String filePath,VersionStamp版本,VersionStamp latestProjectVersion,ILanguageServiceProviderFactory languageServiceProviderFactory,IWorkspaceServiceProvider workspaceServices) 在Roslyn.Services.Host.SolutionFactoryServiceFactory.SolutionFactoryService.CreateSolution(SolutionId id) 在Roslyn.Services.Host.TrackingWorkspace.CreateNewSolution(ISolutionFactoryService solutionFactory,SolutionId id) 在Roslyn.Services.Host.TrackingWorkspace..ctor(IWorkspaceServiceProvider workspaceServiceProvider,布尔enableBackgroundCompilation,布尔enableInProgressSolutions) (IWorkspaceServiceProvider workspaceServiceProvider,布尔enableBackgroundCompilation,布尔enableInProgressSolutions,布尔enableFileTracking)在Roslyn.Services.Host.HostWorkspace..ctor (ILanguageServiceProviderFactory languageServiceProviderFactory,IWorkspaceServiceProvider workspaceServiceProvider,IProjectFileService projectFileFactsService,IDictionary`2 globalProperties,Boolean enableBackgroundCompilation,Boolean enableFileTracking) 在Roslyn.Services.Host.LoadedWorkspace..ctor(ExportProvider exportProvider,Boolean solutionLoadOnly,Boolean enableFileTracking) 在Roslyn.Services.Host.LoadedWorkspace..ctor(布尔enableFileTracking) 在Roslyn.Services.Host.LoadedWorkspace.LoadStandAloneProject(stringprojectFileName,stringconfiguration,string平台,string语言,布尔enableFileTracking) 在Roslyn.Services.Workspace.LoadStandAloneProject(stringprojectFileName,stringconfiguration,string平台,string语言,布尔enableFileTracking) ...
在控制台应用程序中运行相同的代码,使用相同的项目运行良好。
有任何想法吗? 谷歌search没有帮助!
以下是Roslyn的示例MsBuild任务。
为了重建Workspace.LoadProjectFromCommandLineArguments方法所需的命令行,我们必须从msbuild文件中传递一些信息到我们的任务中。
Roslyn需要解析你的源文件。 (请参阅本文最后的注释。)
所以创建一个C#类库项目。 这些是您需要的项目引用:
Microsoft.Build.Framework Microsoft.Build.Utilities.v4.0 Roslyn.Compilers Roslyn.Services
自定义的MsBuild任务的代码:
using Microsoft.Build.Framework; using Microsoft.Build.Utilities; using Roslyn.Services; using System.Collections.Generic; using System.Linq; using System.Text; namespace RoslynMsBuildTask { public class RoslynTask : Task { [Required] public ITaskItem[] ReferencePath { get; set; } [Required] public ITaskItem[] Compile { get; set; } [Required] public ITaskItem BaseDirectory { get; set; } public override bool Execute() { Log.LogMessage(MessageImportance.High, "RoslynTask.Execute called...\n"); // Format the command line with the minimal info needed for Roslyn to create a workspace. var commandLineForProject = string.Format("/reference:{0} {1}", ReferencePath.Select(i => i.ItemSpec).ToSingleString(",", "\"", "\""), Compile.Select(i => i.ItemSpec).ToSingleString(" ", "\"", "\"")); // Create the Roslyn workspace. var workspace = Workspace.LoadProjectFromCommandLineArguments("MyProject", "C#", commandLineForProject, BaseDirectory.ItemSpec); // Make sure that Roslyn actually parsed the project: dump the source from a syntax tree to the build log. Log.LogMessage(MessageImportance.High, workspace.CurrentSolution.Projects.First() .Documents.First(i => i.FilePath.EndsWith(".cs")).GetSyntaxRoot().GetText().ToString()); return true; } } public static class IEnumerableExtension { public static string ToSingleString<T>(this IEnumerable<T> collection, string separator, string leftWrapper, string rightWrapper) { var stringBuilder = new StringBuilder(); foreach (var item in collection) { if (stringBuilder.Length > 0) { if (!string.IsNullOrEmpty(separator)) stringBuilder.Append(separator); } if (!string.IsNullOrEmpty(leftWrapper)) stringBuilder.Append(leftWrapper); stringBuilder.Append(item.ToString()); if (!string.IsNullOrEmpty(rightWrapper)) stringBuilder.Append(rightWrapper); } return stringBuilder.ToString(); } } }
为了证明它实际上可行,请在csproj文件的末尾添加以下行(就在关闭Project标签之前)。 但只有当项目已经成功建立,它可以在输出文件夹中找到你的任务DLL。
<Target Name="AfterBuild" DependsOnTargets="RoslynTask"/> <UsingTask AssemblyFile="$(OutputPath)\RoslynMsBuildTask.dll" TaskName="RoslynMsBuildTask.RoslynTask" /> <Target Name="RoslynTask"> <RoslynTask ReferencePath="@(ReferencePath)" Compile="@(Compile)" BaseDirectory="$(MSBuildProjectDirectory)" /> </Target>
它会将你的第一个cs文件的源代码转储到编译输出。
请注意,其他csc.exe开关(如ConditionalDirectives,输出类型等)也可能很重要,具体取决于您尝试执行的分析类型。 您也可以使用这种模式将它们传递给您的任务。 有关MsBuild传递给csc.exe的完整属性列表,请参阅$(MSBuildToolsPath)\ Microsoft.CSharp.targets文件,CoreCompile目标,Csc任务。
这是MSBuild的限制。 Roslyn不能在构建过程中递归调用MSBuild来确定项目属性/文件/引用。 为了在构建任务期间创建Roslyn IProject
,请尝试使用LoadFromCommandLineArgs()
方法。 您需要构建您的任务,以获取与CscTask最终传递给编译器相同的参数。
希望这可以帮助!