94b2861243
Former-commit-id: 5f9c6ae75f295e057a7d2971f3a6df4656fa8850
1367 lines
52 KiB
C#
1367 lines
52 KiB
C#
namespace System.Workflow.ComponentModel.Compiler
|
|
{
|
|
using System;
|
|
using System.Resources;
|
|
using System.Reflection;
|
|
using System.Diagnostics;
|
|
using System.Globalization;
|
|
using System.IO;
|
|
using System.Xml;
|
|
using System.Text;
|
|
using System.Collections;
|
|
using System.Collections.Specialized;
|
|
using System.ComponentModel.Design;
|
|
using System.CodeDom;
|
|
using System.CodeDom.Compiler;
|
|
using Microsoft.Win32;
|
|
using Microsoft.CSharp;
|
|
using Microsoft.VisualBasic;
|
|
using System.Workflow.ComponentModel.Compiler;
|
|
using System.Workflow.ComponentModel;
|
|
using System.Workflow.ComponentModel.Design;
|
|
using System.Workflow.ComponentModel.Serialization;
|
|
using Microsoft.Build.Framework;
|
|
using Microsoft.Build.Utilities;
|
|
using System.Runtime.InteropServices;
|
|
using Microsoft.Build.Tasks;
|
|
using System.Collections.Generic;
|
|
using Microsoft.Workflow.Compiler;
|
|
using System.Runtime.Versioning;
|
|
using System.Security;
|
|
|
|
[Guid("59B2D1D0-5DB0-4F9F-9609-13F0168516D6")]
|
|
[ComImport]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IVsHierarchy
|
|
{
|
|
}
|
|
|
|
[Guid("6d5140c1-7436-11ce-8034-00aa006009fa")]
|
|
[ComImport]
|
|
[InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IOleServiceProvider
|
|
{
|
|
[PreserveSig]
|
|
int QueryService(ref Guid guidService, ref Guid riid, out IntPtr ppvObject);
|
|
}
|
|
|
|
[ComImport(), Guid("8AA9644E-1F6A-4F4C-83E3-D0BAD4B2BB21"), InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
|
|
internal interface IWorkflowBuildHostProperties
|
|
{
|
|
bool SkipWorkflowCompilation { get; set; }
|
|
}
|
|
|
|
internal class ServiceProvider : IServiceProvider
|
|
{
|
|
private static readonly Guid IID_IUnknown = new Guid("{00000000-0000-0000-C000-000000000046}");
|
|
private IOleServiceProvider serviceProvider;
|
|
public ServiceProvider(IOleServiceProvider sp)
|
|
{
|
|
this.serviceProvider = sp;
|
|
}
|
|
public object GetService(Type serviceType)
|
|
{
|
|
if (serviceType == null)
|
|
throw new ArgumentNullException("serviceType");
|
|
|
|
IntPtr pUnk = IntPtr.Zero;
|
|
Guid guidService = serviceType.GUID;
|
|
Guid guidUnk = IID_IUnknown;
|
|
int hr = this.serviceProvider.QueryService(ref guidService, ref guidUnk, out pUnk);
|
|
|
|
object service = null;
|
|
if (hr >= 0)
|
|
{
|
|
try
|
|
{
|
|
service = Marshal.GetObjectForIUnknown(pUnk);
|
|
}
|
|
finally
|
|
{
|
|
Marshal.Release(pUnk);
|
|
}
|
|
}
|
|
return service;
|
|
}
|
|
}
|
|
|
|
#region CompileWorkflowTask
|
|
/// <summary>
|
|
/// This class extends the Task class of MSBuild framework.
|
|
/// Methods of this class are invoked by the MSBuild framework to customize
|
|
/// the build process when compiling WinOE flavors of CSharp and VB.net projects.
|
|
/// It provides support for compiling .xoml files into intermediate
|
|
/// code files (either CSharp or VB). It calls into the WorkflowCompiler to do the
|
|
/// validations and code compile unit generation.
|
|
/// This component is used during the build process of WinOE flavor projects
|
|
/// both from within the Visual Studio IDE and the standalone MSBuild executable.
|
|
/// As such this component's assembly should not have direct or indirect dependencies
|
|
/// on the Visual Studio assemblies to work in the standalone scenario.
|
|
/// </summary>
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public sealed class CompileWorkflowTask : Microsoft.Build.Utilities.Task, ITask
|
|
{
|
|
|
|
#region Members and Constructors
|
|
|
|
private string projectExt = null;
|
|
private string projectDirectory = null;
|
|
private object hostObject = null;
|
|
private string rootNamespace = null;
|
|
private string imports = null;
|
|
private string assemblyName = null;
|
|
private ITaskItem[] xomlFiles = null;
|
|
private ITaskItem[] referenceFiles = null;
|
|
private ITaskItem[] sourceCodeFiles = null;
|
|
private ITaskItem[] resourceFiles = null;
|
|
private ITaskItem[] outputFiles = null; //new TaskItem[0]; // The outputs should be non-null if we bail out successfully or otherwise from the Execute method.
|
|
private ITaskItem[] compilationOptions = null;
|
|
private SupportedLanguages projectType;
|
|
private StringCollection temporaryFiles = new StringCollection();
|
|
private bool delaySign = false;
|
|
private string targetFramework = null;
|
|
private string keyContainer = null;
|
|
private string keyFile = null;
|
|
|
|
public CompileWorkflowTask()
|
|
: base(new ResourceManager("System.Workflow.ComponentModel.BuildTasksStrings", Assembly.GetExecutingAssembly()))
|
|
{
|
|
this.BuildingProject = true;
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Input parameters and property overrides
|
|
public string ProjectDirectory
|
|
{
|
|
get
|
|
{
|
|
return this.projectDirectory;
|
|
}
|
|
set
|
|
{
|
|
this.projectDirectory = value;
|
|
}
|
|
}
|
|
|
|
public string ProjectExtension
|
|
{
|
|
get
|
|
{
|
|
return this.projectExt;
|
|
}
|
|
set
|
|
{
|
|
this.projectExt = value;
|
|
if (String.Compare(this.projectExt, ".csproj", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
ProjectType = SupportedLanguages.CSharp;
|
|
}
|
|
else if (String.Compare(this.projectExt, ".vbproj", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
ProjectType = SupportedLanguages.VB;
|
|
}
|
|
}
|
|
}
|
|
|
|
public string RootNamespace
|
|
{
|
|
get
|
|
{
|
|
return this.rootNamespace;
|
|
}
|
|
set
|
|
{
|
|
this.rootNamespace = value;
|
|
}
|
|
}
|
|
|
|
public string AssemblyName
|
|
{
|
|
get
|
|
{
|
|
return this.assemblyName;
|
|
}
|
|
set
|
|
{
|
|
this.assemblyName = value;
|
|
}
|
|
}
|
|
|
|
public string Imports
|
|
{
|
|
get
|
|
{
|
|
return this.imports;
|
|
}
|
|
set
|
|
{
|
|
this.imports = value;
|
|
}
|
|
}
|
|
|
|
public ITaskItem[] WorkflowMarkupFiles
|
|
{
|
|
get
|
|
{
|
|
return xomlFiles;
|
|
}
|
|
set
|
|
{
|
|
if (value != null)
|
|
{
|
|
ArrayList xomlFilesOnly = new ArrayList();
|
|
foreach (ITaskItem inputFile in value)
|
|
{
|
|
if (inputFile != null)
|
|
{
|
|
string fileSpec = inputFile.ItemSpec;
|
|
if (fileSpec != null && fileSpec.EndsWith(".xoml", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
xomlFilesOnly.Add(inputFile);
|
|
}
|
|
}
|
|
}
|
|
|
|
if (xomlFilesOnly.Count > 0)
|
|
{
|
|
this.xomlFiles = xomlFilesOnly.ToArray(typeof(ITaskItem)) as ITaskItem[];
|
|
}
|
|
}
|
|
else
|
|
{
|
|
this.xomlFiles = value;
|
|
}
|
|
}
|
|
}
|
|
|
|
public ITaskItem[] ReferenceFiles
|
|
{
|
|
get
|
|
{
|
|
return this.referenceFiles;
|
|
}
|
|
set
|
|
{
|
|
this.referenceFiles = value;
|
|
}
|
|
}
|
|
|
|
public ITaskItem[] ResourceFiles
|
|
{
|
|
get
|
|
{
|
|
return this.resourceFiles;
|
|
}
|
|
set
|
|
{
|
|
this.resourceFiles = value;
|
|
}
|
|
}
|
|
|
|
public ITaskItem[] SourceCodeFiles
|
|
{
|
|
get
|
|
{
|
|
return this.sourceCodeFiles;
|
|
}
|
|
set
|
|
{
|
|
this.sourceCodeFiles = value;
|
|
}
|
|
}
|
|
|
|
public ITaskItem[] CompilationOptions
|
|
{
|
|
get
|
|
{
|
|
return this.compilationOptions;
|
|
}
|
|
set
|
|
{
|
|
this.compilationOptions = value;
|
|
}
|
|
}
|
|
|
|
public bool DelaySign
|
|
{
|
|
get
|
|
{
|
|
return this.delaySign;
|
|
}
|
|
set
|
|
{
|
|
this.delaySign = value;
|
|
}
|
|
}
|
|
|
|
public string TargetFramework
|
|
{
|
|
get
|
|
{
|
|
return this.targetFramework;
|
|
}
|
|
set
|
|
{
|
|
this.targetFramework = value;
|
|
}
|
|
}
|
|
|
|
public string KeyContainer
|
|
{
|
|
get
|
|
{
|
|
return this.keyContainer;
|
|
}
|
|
set
|
|
{
|
|
this.keyContainer = value;
|
|
}
|
|
}
|
|
|
|
public string KeyFile
|
|
{
|
|
get
|
|
{
|
|
return this.keyFile;
|
|
}
|
|
set
|
|
{
|
|
this.keyFile = value;
|
|
}
|
|
}
|
|
|
|
public new object HostObject
|
|
{
|
|
get
|
|
{
|
|
return this.hostObject;
|
|
}
|
|
}
|
|
|
|
ITaskHost ITask.HostObject
|
|
{
|
|
get
|
|
{
|
|
return (ITaskHost)this.hostObject;
|
|
}
|
|
set
|
|
{
|
|
this.hostObject = value;
|
|
}
|
|
}
|
|
|
|
public bool BuildingProject { get; set; }
|
|
#endregion
|
|
|
|
#region Output parameter properties
|
|
[OutputAttribute]
|
|
public ITaskItem[] OutputFiles
|
|
{
|
|
get
|
|
{
|
|
if (this.outputFiles == null)
|
|
{
|
|
if (this.ProjectType == SupportedLanguages.VB)
|
|
this.outputFiles = new ITaskItem[0];
|
|
else
|
|
{
|
|
ArrayList oFiles = new ArrayList();
|
|
if (this.WorkflowMarkupFiles != null)
|
|
oFiles.AddRange(this.WorkflowMarkupFiles);
|
|
this.outputFiles = oFiles.ToArray(typeof(ITaskItem)) as ITaskItem[];
|
|
}
|
|
}
|
|
return this.outputFiles;
|
|
}
|
|
}
|
|
|
|
[OutputAttribute]
|
|
public string KeepTemporaryFiles
|
|
{
|
|
get
|
|
{
|
|
return ShouldKeepTempFiles().ToString();
|
|
}
|
|
}
|
|
|
|
[OutputAttribute]
|
|
public string[] TemporaryFiles
|
|
{
|
|
get
|
|
{
|
|
string[] tempFiles = new string[this.temporaryFiles.Count];
|
|
|
|
this.temporaryFiles.CopyTo(tempFiles, 0);
|
|
return tempFiles;
|
|
}
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Public method overrides
|
|
|
|
public override bool Execute()
|
|
{
|
|
#if DEBUG
|
|
DumpInputParameters();
|
|
#endif
|
|
|
|
// Validate the input parameters for the task.
|
|
if (!this.ValidateParameters())
|
|
return false;
|
|
|
|
// If no .xoml files were specified, return success.
|
|
if (this.WorkflowMarkupFiles == null)
|
|
this.Log.LogMessageFromResources(MessageImportance.Normal, "NoXomlFiles");
|
|
|
|
// Check if there are any referenced assemblies.
|
|
if (this.ReferenceFiles == null || this.ReferenceFiles.Length == 0)
|
|
this.Log.LogMessageFromResources(MessageImportance.Normal, "NoReferenceFiles");
|
|
|
|
// Check if there are any souce code files (cs/vb).
|
|
if (this.SourceCodeFiles == null || this.SourceCodeFiles.Length == 0)
|
|
this.Log.LogMessageFromResources(MessageImportance.Normal, "NoSourceCodeFiles");
|
|
|
|
// we return early if this is not invoked during the build phase of the project (eg project load)
|
|
IWorkflowBuildHostProperties workflowBuildHostProperty = this.HostObject as IWorkflowBuildHostProperties;
|
|
if (!this.BuildingProject || (workflowBuildHostProperty != null && workflowBuildHostProperty.SkipWorkflowCompilation))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
// Create an instance of WorkflowCompilerParameters.
|
|
int errorCount = 0, warningCount = 0;
|
|
WorkflowCompilerParameters compilerParameters = new WorkflowCompilerParameters();
|
|
|
|
// set the service provider
|
|
IWorkflowCompilerErrorLogger workflowErrorLogger = null;
|
|
IServiceProvider externalServiceProvider = null;
|
|
if (this.HostObject is IOleServiceProvider)
|
|
{
|
|
externalServiceProvider = new ServiceProvider(this.HostObject as IOleServiceProvider);
|
|
workflowErrorLogger = externalServiceProvider.GetService(typeof(IWorkflowCompilerErrorLogger)) as IWorkflowCompilerErrorLogger;
|
|
}
|
|
|
|
string[] userCodeFiles = GetFiles(this.SourceCodeFiles, this.ProjectDirectory);
|
|
foreach (ITaskItem referenceFile in this.ReferenceFiles)
|
|
compilerParameters.ReferencedAssemblies.Add(referenceFile.ItemSpec);
|
|
|
|
if (string.IsNullOrEmpty(this.targetFramework))
|
|
{
|
|
string defaultFrameworkName = null;
|
|
|
|
const string NDPSetupRegistryBranch = "SOFTWARE\\Microsoft\\NET Framework Setup\\NDP";
|
|
const string NetFrameworkIdentifier = ".NETFramework";
|
|
|
|
RegistryKey ndpSetupKey = null;
|
|
try
|
|
{
|
|
ndpSetupKey = Registry.LocalMachine.OpenSubKey(NDPSetupRegistryBranch);
|
|
|
|
if (ndpSetupKey != null)
|
|
{
|
|
string[] installedNetFxs = ndpSetupKey.GetSubKeyNames();
|
|
|
|
if (installedNetFxs != null)
|
|
{
|
|
char[] splitChars = new char[] { '.' };
|
|
for (int i = 0; i < installedNetFxs.Length; i++)
|
|
{
|
|
string framework = installedNetFxs[i];
|
|
if (framework.Length > 0)
|
|
{
|
|
string frameworkVersion = framework.TrimStart('v', 'V');
|
|
if (!string.IsNullOrEmpty(frameworkVersion))
|
|
{
|
|
string[] parts = frameworkVersion.Split(splitChars);
|
|
|
|
string normalizedVersion = null;
|
|
if (parts.Length > 1)
|
|
{
|
|
normalizedVersion = string.Format(CultureInfo.InvariantCulture, "v{0}.{1}", parts[0], parts[1]);
|
|
}
|
|
else
|
|
{
|
|
normalizedVersion = string.Format(CultureInfo.InvariantCulture, "v{0}.0", parts[0]);
|
|
}
|
|
|
|
if (string.Compare(normalizedVersion, "v3.5", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
defaultFrameworkName = new FrameworkName(NetFrameworkIdentifier, new Version(3, 5)).ToString();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (SecurityException)
|
|
{
|
|
}
|
|
catch (UnauthorizedAccessException)
|
|
{
|
|
}
|
|
catch (IOException)
|
|
{
|
|
}
|
|
finally
|
|
{
|
|
if (ndpSetupKey != null)
|
|
{
|
|
ndpSetupKey.Close();
|
|
}
|
|
}
|
|
|
|
if (defaultFrameworkName == null)
|
|
{
|
|
defaultFrameworkName = new FrameworkName(NetFrameworkIdentifier, new Version(2, 0)).ToString();
|
|
}
|
|
|
|
compilerParameters.MultiTargetingInformation = new MultiTargetingInfo(defaultFrameworkName);
|
|
}
|
|
else
|
|
{
|
|
compilerParameters.MultiTargetingInformation = new MultiTargetingInfo(this.targetFramework);
|
|
}
|
|
|
|
CompilerOptionsBuilder optionsBuilder;
|
|
switch (this.ProjectType)
|
|
{
|
|
case SupportedLanguages.VB:
|
|
switch (compilerParameters.CompilerVersion)
|
|
{
|
|
case MultiTargetingInfo.TargetFramework30CompilerVersion:
|
|
optionsBuilder = new WhidbeyVBCompilerOptionsBuilder();
|
|
break;
|
|
case MultiTargetingInfo.TargetFramework35CompilerVersion:
|
|
optionsBuilder = new OrcasVBCompilerOptionsBuilder();
|
|
break;
|
|
default:
|
|
optionsBuilder = new CompilerOptionsBuilder();
|
|
break;
|
|
}
|
|
break;
|
|
default:
|
|
optionsBuilder = new CompilerOptionsBuilder();
|
|
break;
|
|
}
|
|
compilerParameters.CompilerOptions = this.PrepareCompilerOptions(optionsBuilder);
|
|
compilerParameters.GenerateCodeCompileUnitOnly = true;
|
|
compilerParameters.LanguageToUse = this.ProjectType.ToString();
|
|
compilerParameters.TempFiles.KeepFiles = ShouldKeepTempFiles();
|
|
|
|
compilerParameters.OutputAssembly = AssemblyName;
|
|
if (!string.IsNullOrEmpty(assemblyName))
|
|
{
|
|
// Normalizing the assembly name.
|
|
// The codeDomProvider expects the proper extension to be set.
|
|
string extension = (compilerParameters.GenerateExecutable) ? ".exe" : ".dll";
|
|
compilerParameters.OutputAssembly += extension;
|
|
}
|
|
|
|
CodeDomProvider codeProvider = null;
|
|
if (this.ProjectType == SupportedLanguages.VB)
|
|
codeProvider = CompilerHelpers.CreateCodeProviderInstance(typeof(VBCodeProvider), compilerParameters.CompilerVersion);
|
|
else
|
|
codeProvider = CompilerHelpers.CreateCodeProviderInstance(typeof(CSharpCodeProvider), compilerParameters.CompilerVersion);
|
|
|
|
using (TempFileCollection tempFileCollection = new TempFileCollection(Environment.GetEnvironmentVariable("temp", EnvironmentVariableTarget.User), true))
|
|
{
|
|
this.outputFiles = new TaskItem[1];
|
|
|
|
// Compile and generate a temporary code file for each xoml file.
|
|
string[] xomlFilesPaths;
|
|
if (this.WorkflowMarkupFiles != null)
|
|
{
|
|
xomlFilesPaths = new string[WorkflowMarkupFiles.GetLength(0) + userCodeFiles.Length];
|
|
int index = 0;
|
|
for (; index < this.WorkflowMarkupFiles.GetLength(0); index++)
|
|
xomlFilesPaths[index] = Path.Combine(ProjectDirectory, this.WorkflowMarkupFiles[index].ItemSpec);
|
|
|
|
userCodeFiles.CopyTo(xomlFilesPaths, index);
|
|
}
|
|
else
|
|
{
|
|
xomlFilesPaths = new string[userCodeFiles.Length];
|
|
userCodeFiles.CopyTo(xomlFilesPaths, 0);
|
|
}
|
|
|
|
WorkflowCompilerResults compilerResults = new CompilerWrapper().Compile(compilerParameters, xomlFilesPaths);
|
|
|
|
foreach (WorkflowCompilerError error in compilerResults.Errors)
|
|
{
|
|
if (error.IsWarning)
|
|
{
|
|
warningCount++;
|
|
if (workflowErrorLogger != null)
|
|
{
|
|
error.FileName = Path.Combine(this.ProjectDirectory, error.FileName);
|
|
workflowErrorLogger.LogError(error);
|
|
workflowErrorLogger.LogMessage(error.ToString() + "\n");
|
|
}
|
|
else
|
|
this.Log.LogWarning(error.ErrorText, error.ErrorNumber, error.FileName, error.Line, error.Column);
|
|
}
|
|
else
|
|
{
|
|
errorCount++;
|
|
if (workflowErrorLogger != null)
|
|
{
|
|
error.FileName = Path.Combine(this.ProjectDirectory, error.FileName);
|
|
workflowErrorLogger.LogError(error);
|
|
workflowErrorLogger.LogMessage(error.ToString() + "\n");
|
|
}
|
|
else
|
|
this.Log.LogError(error.ErrorText, error.ErrorNumber, error.FileName, error.Line, error.Column);
|
|
}
|
|
}
|
|
|
|
if (!compilerResults.Errors.HasErrors)
|
|
{
|
|
CodeCompileUnit ccu = compilerResults.CompiledUnit;
|
|
if (ccu != null)
|
|
{
|
|
// Fix standard namespaces and root namespace.
|
|
WorkflowMarkupSerializationHelpers.FixStandardNamespacesAndRootNamespace(ccu.Namespaces, this.RootNamespace, CompilerHelpers.GetSupportedLanguage(this.ProjectType.ToString())); //just add the standard namespaces
|
|
|
|
string tempFile = tempFileCollection.AddExtension(codeProvider.FileExtension);
|
|
using (StreamWriter fileStream = new StreamWriter(new FileStream(tempFile, FileMode.Create, FileAccess.Write), Encoding.UTF8))
|
|
{
|
|
CodeGeneratorOptions options = new CodeGeneratorOptions();
|
|
options.BracingStyle = "C";
|
|
codeProvider.GenerateCodeFromCompileUnit(ccu, fileStream, options);
|
|
}
|
|
|
|
this.outputFiles[0] = new TaskItem(tempFile);
|
|
this.temporaryFiles.Add(tempFile);
|
|
this.Log.LogMessageFromResources(MessageImportance.Normal, "TempCodeFile", tempFile);
|
|
}
|
|
}
|
|
}
|
|
if ((errorCount > 0 || warningCount > 0) && workflowErrorLogger != null)
|
|
workflowErrorLogger.LogMessage(string.Format(CultureInfo.CurrentCulture, "\nCompile complete -- {0} errors, {1} warnings \n", new object[] { errorCount, warningCount }));
|
|
|
|
#if DEBUG
|
|
DumpOutputParameters();
|
|
#endif
|
|
this.Log.LogMessageFromResources(MessageImportance.Normal, "XomlValidationCompleted", errorCount, warningCount);
|
|
return (errorCount == 0);
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Private properties and methods
|
|
private SupportedLanguages ProjectType
|
|
{
|
|
get
|
|
{
|
|
return this.projectType;
|
|
}
|
|
set
|
|
{
|
|
this.projectType = value;
|
|
}
|
|
}
|
|
|
|
/// <summary>
|
|
/// This method validates all the input parameters for the custom task.
|
|
/// </summary>
|
|
/// <returns>True if all parameters are valid, false otherwise</returns>
|
|
private bool ValidateParameters()
|
|
{
|
|
// If the project directory is not supplied then bail out with an error.
|
|
if (ProjectDirectory == null || ProjectDirectory.Trim().Length == 0)
|
|
{
|
|
this.Log.LogErrorFromResources("NoProjectType");
|
|
return false;
|
|
}
|
|
|
|
// If the project extension is not supplied then bail out with an error.
|
|
if (ProjectExtension == null || ProjectExtension.Trim().Length == 0)
|
|
{
|
|
this.Log.LogErrorFromResources("NoProjectType");
|
|
return false;
|
|
}
|
|
|
|
// If the project extension is not .csproj or .vbproj bail out with an error.
|
|
if (String.Compare(ProjectExtension, ".csproj", StringComparison.OrdinalIgnoreCase) != 0 && String.Compare(ProjectExtension, ".vbproj", StringComparison.OrdinalIgnoreCase) != 0)
|
|
{
|
|
this.Log.LogErrorFromResources("UnsupportedProjectType");
|
|
return false;
|
|
}
|
|
|
|
// All parameters are valid so return true.
|
|
return true;
|
|
}
|
|
|
|
#if DEBUG
|
|
void DumpInputParameters()
|
|
{
|
|
DumpParametersLine("CompileWorkflowTask - Input Parameters:");
|
|
DumpParametersLine(" projectExt={0}", this.projectExt);
|
|
DumpParametersLine(" projectDirectory='{0}'", this.projectDirectory);
|
|
DumpParametersLine(" rootNamespace={0}", this.rootNamespace);
|
|
DumpParametersLine(" imports='{0}'", this.imports);
|
|
DumpParametersLine(" assemblyName='{0}", this.assemblyName);
|
|
DumpParametersTaskItems("xomlFiles", this.xomlFiles);
|
|
DumpParametersTaskItems("sourceCodeFiles", this.sourceCodeFiles);
|
|
DumpParametersTaskItems("resourceFiles", this.resourceFiles);
|
|
DumpParametersTaskItems("referenceFiles", this.referenceFiles);
|
|
DumpParametersTaskItems("compilationOptions", this.compilationOptions);
|
|
DumpParametersLine(" delaySign={0},keyContainer='{1}',keyFile='{2}'", this.delaySign, this.keyContainer, this.keyFile);
|
|
DumpParametersLine(" targetFramework='{0}'", this.targetFramework);
|
|
}
|
|
void DumpOutputParameters()
|
|
{
|
|
DumpParametersLine("CompileWorkflowTask - Output Parameters:");
|
|
DumpParametersTaskItems("outputFiles", this.outputFiles);
|
|
DumpParametersLine(" KeepTemporaryFiles={0},temporaryFiles=[{1} items]", this.KeepTemporaryFiles, this.temporaryFiles.Count);
|
|
for (int i = 0; i < this.temporaryFiles.Count; i++)
|
|
{
|
|
DumpParametersLine(" '{0}' [{1}]", this.temporaryFiles[i], i);
|
|
}
|
|
}
|
|
void DumpParametersTaskItems(string name, ITaskItem[] items)
|
|
{
|
|
if (items == null)
|
|
{
|
|
DumpParametersLine(" {0}=<null>", name);
|
|
}
|
|
else
|
|
{
|
|
DumpParametersLine(" {0}=[{1} items]", name, items.Length);
|
|
for (int i = 0; i < items.Length; i++)
|
|
{
|
|
ITaskItem item = items[i];
|
|
if (item == null)
|
|
{
|
|
DumpParametersLine(" <null> [{0}]", i);
|
|
}
|
|
else
|
|
{
|
|
DumpParametersLine(" {0} [{1}]", item.ItemSpec, i);
|
|
foreach (string metadataName in item.MetadataNames)
|
|
{
|
|
DumpParametersLine(" {0}='{1}'", metadataName, item.GetMetadata(metadataName));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
void DumpParametersLine(string lineFormat, params object[] lineArguments)
|
|
{
|
|
if ((lineArguments != null) && (lineArguments.Length > 0))
|
|
{
|
|
for (int i = 0; i < lineArguments.Length; i++)
|
|
{
|
|
if (lineArguments[i] == null)
|
|
{
|
|
lineArguments[i] = "<null>";
|
|
}
|
|
}
|
|
}
|
|
this.Log.LogMessage(MessageImportance.Low, lineFormat, lineArguments);
|
|
}
|
|
#endif
|
|
|
|
/// <summary>
|
|
/// This method is used to get the absolute paths of the files
|
|
/// in a project.
|
|
/// </summary>
|
|
/// <param name="taskItems"></param>
|
|
/// <param name="projDir"></param>
|
|
/// <returns></returns>
|
|
private static string[] GetFiles(ITaskItem[] taskItems, string projDir)
|
|
{
|
|
if (taskItems == null)
|
|
return new string[0];
|
|
string[] itemSpecs = new string[taskItems.Length];
|
|
|
|
for (int i = 0; i < taskItems.Length; i++)
|
|
{
|
|
if (projDir != null)
|
|
{
|
|
itemSpecs[i] = Path.Combine(projDir, taskItems[i].ItemSpec);
|
|
}
|
|
else
|
|
{
|
|
itemSpecs[i] = taskItems[i].ItemSpec;
|
|
}
|
|
}
|
|
|
|
return itemSpecs;
|
|
}
|
|
|
|
private static bool HasManifestResourceName(ITaskItem resourceFile, out string manifestResourceName)
|
|
{
|
|
IEnumerator metadataNames = resourceFile.MetadataNames.GetEnumerator();
|
|
|
|
manifestResourceName = null;
|
|
bool hasName = false;
|
|
while (!hasName && metadataNames.MoveNext())
|
|
{
|
|
string metadataName = (string)metadataNames.Current;
|
|
if (metadataName == "ManifestResourceName")
|
|
{
|
|
hasName = true;
|
|
manifestResourceName = resourceFile.GetMetadata(metadataName);
|
|
}
|
|
}
|
|
|
|
return hasName;
|
|
}
|
|
|
|
//Note: Remember to prefix each option with a space. We don't want compiler options glued together.
|
|
private string PrepareCompilerOptions(CompilerOptionsBuilder optionsBuilder)
|
|
{
|
|
StringBuilder compilerOptions = new StringBuilder();
|
|
|
|
if (this.DelaySign == true)
|
|
compilerOptions.Append(" /delaysign+");
|
|
|
|
if (this.KeyContainer != null && this.KeyContainer.Trim().Length > 0)
|
|
compilerOptions.AppendFormat(" /keycontainer:{0}", this.KeyContainer);
|
|
|
|
if (this.KeyFile != null && this.KeyFile.Trim().Length > 0)
|
|
compilerOptions.AppendFormat(" /keyfile:\"{0}\"", Path.Combine(this.ProjectDirectory, this.KeyFile));
|
|
|
|
if (this.compilationOptions != null && this.compilationOptions.Length > 0)
|
|
{
|
|
foreach (ITaskItem option in this.compilationOptions)
|
|
{
|
|
optionsBuilder.AddCustomOption(compilerOptions, option);
|
|
}
|
|
}
|
|
|
|
if (this.resourceFiles != null && this.resourceFiles.Length > 0)
|
|
{
|
|
foreach (ITaskItem resourceFile in this.resourceFiles)
|
|
{
|
|
string manifestResourceName;
|
|
|
|
if (HasManifestResourceName(resourceFile, out manifestResourceName))
|
|
{
|
|
compilerOptions.AppendFormat(" /resource:\"{0}\",{1}",
|
|
Path.Combine(this.ProjectDirectory, resourceFile.ItemSpec), manifestResourceName);
|
|
}
|
|
else
|
|
{
|
|
compilerOptions.AppendFormat(" /resource:\"{0}\"",
|
|
Path.Combine(this.ProjectDirectory, resourceFile.ItemSpec));
|
|
}
|
|
}
|
|
}
|
|
|
|
if (this.ProjectType == SupportedLanguages.VB)
|
|
{
|
|
if (!string.IsNullOrEmpty(this.RootNamespace))
|
|
compilerOptions.AppendFormat(" /rootnamespace:{0}", this.RootNamespace);
|
|
compilerOptions.AppendFormat(" /imports:{0}", this.Imports.Replace(';', ','));
|
|
}
|
|
|
|
if (compilerOptions.Length > 0)
|
|
{
|
|
if (char.IsWhiteSpace(compilerOptions[0]))
|
|
{
|
|
compilerOptions.Remove(0, 0);
|
|
}
|
|
}
|
|
|
|
return compilerOptions.ToString();
|
|
}
|
|
|
|
private bool ShouldKeepTempFiles()
|
|
{
|
|
bool retVal = false;
|
|
|
|
// See comments for the CompileWorkflowCleanupTask class for reasons why we must keep the temp file for VB.
|
|
if (this.ProjectType == SupportedLanguages.VB)
|
|
retVal = true;
|
|
else
|
|
{
|
|
try
|
|
{
|
|
RegistryKey winoeKey = Registry.LocalMachine.OpenSubKey(Helpers.ProductRootRegKey);
|
|
if (winoeKey != null)
|
|
{
|
|
object obj = winoeKey.GetValue("KeepTempFiles");
|
|
retVal = (Convert.ToInt32(obj, CultureInfo.InvariantCulture) != 0);
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
}
|
|
}
|
|
|
|
return retVal;
|
|
}
|
|
|
|
#endregion
|
|
|
|
class CompilerOptionsBuilder
|
|
{
|
|
public CompilerOptionsBuilder()
|
|
{
|
|
}
|
|
|
|
public void AddCustomOption(StringBuilder options, ITaskItem option)
|
|
{
|
|
string optionName;
|
|
string optionValue;
|
|
string optionDelimiter;
|
|
GetOptionInfo(option, out optionName, out optionValue, out optionDelimiter);
|
|
if (!string.IsNullOrWhiteSpace(optionName))
|
|
{
|
|
if (string.IsNullOrEmpty(optionValue))
|
|
{
|
|
options.AppendFormat(" /{0}", optionName);
|
|
}
|
|
else if (string.IsNullOrEmpty(optionDelimiter))
|
|
{
|
|
options.AppendFormat(" /{0}{1}", optionName, optionValue);
|
|
}
|
|
else
|
|
{
|
|
options.AppendFormat(" /{0}{1}{2}", optionName, optionDelimiter, optionValue);
|
|
}
|
|
}
|
|
}
|
|
|
|
protected virtual void GetOptionInfo(ITaskItem option, out string optionName, out string optionValue, out string optionDelimiter)
|
|
{
|
|
optionName = option.ItemSpec;
|
|
optionValue = option.GetMetadata("value");
|
|
optionDelimiter = option.GetMetadata("delimiter");
|
|
}
|
|
}
|
|
abstract class VBCompilerOptionsBuilder : CompilerOptionsBuilder
|
|
{
|
|
const string SuppressWarningOption = "nowarn";
|
|
|
|
protected VBCompilerOptionsBuilder()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
sealed protected override void GetOptionInfo(ITaskItem option, out string optionName, out string optionValue, out string optionDelimiter)
|
|
{
|
|
base.GetOptionInfo(option, out optionName, out optionValue, out optionDelimiter);
|
|
if ((string.Compare(optionName, SuppressWarningOption, StringComparison.OrdinalIgnoreCase) == 0) &&
|
|
!string.IsNullOrWhiteSpace(optionValue))
|
|
{
|
|
string[] warnings = optionValue.Split(',');
|
|
StringBuilder validWarnings = new StringBuilder();
|
|
for (int i = 0; i < warnings.Length; i++)
|
|
{
|
|
string warning = warnings[i].Trim();
|
|
if (IsValidWarning(warning))
|
|
{
|
|
if (validWarnings.Length == 0)
|
|
{
|
|
validWarnings.Append(warning);
|
|
}
|
|
else
|
|
{
|
|
validWarnings.AppendFormat(",{0}", warning);
|
|
}
|
|
}
|
|
}
|
|
optionValue = validWarnings.ToString();
|
|
if (string.IsNullOrWhiteSpace(optionValue))
|
|
{
|
|
optionName = string.Empty;
|
|
}
|
|
}
|
|
}
|
|
|
|
protected abstract bool IsValidWarning(string warning);
|
|
}
|
|
class WhidbeyVBCompilerOptionsBuilder : VBCompilerOptionsBuilder
|
|
{
|
|
static HashSet<string> validWarnings = new HashSet<string>(StringComparer.Ordinal)
|
|
{ "40000", "40003", "40004", "40005", "40007", "40008", "40009", "40010", "40011", "40012", "40014", "40018", "40019",
|
|
"40020", "40021", "40022", "40023", "40024", "40025", "40026", "40027", "40028", "40029", "40030", "40031", "40032",
|
|
"40033", "40034", "40035", "40038", "40039", "40040", "40041", "40042", "40043", "40046", "40047", "40048", "40049",
|
|
"40050", "40051", "40052", "40053", "40054", "40055", "40056", "40057",
|
|
"41000", "41001", "41002", "41003", "41004", "41005", "41006", "41998", "41999",
|
|
"42000", "42001", "42002", "42003", "42004", "42014", "42015", "42016", "42017", "42018", "42019", "42020", "42021",
|
|
"42022", "42024", "42025", "42026", "42028", "42029", "42030", "42031", "42032", "42033", "42034", "42035", "42036",
|
|
"42101", "42102", "42104", "42105", "42106", "42107", "42108", "42109", "42200", "42203", "42204", "42205", "42206",
|
|
"42300", "42301", "42302", "42303", "42304", "42305", "42306", "42307", "42308", "42309", "42310", "42311", "42312",
|
|
"42313", "42314", "42315", "42316", "42317", "42318", "42319", "42320", "42321" };
|
|
|
|
public WhidbeyVBCompilerOptionsBuilder()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
protected override bool IsValidWarning(string warning)
|
|
{
|
|
return validWarnings.Contains(warning);
|
|
}
|
|
}
|
|
class OrcasVBCompilerOptionsBuilder : VBCompilerOptionsBuilder
|
|
{
|
|
static HashSet<string> validWarnings = new HashSet<string>(StringComparer.Ordinal)
|
|
{ "40000", "40003", "40004", "40005", "40007", "40008", "40009", "40010", "40011", "40012", "40014", "40018", "40019",
|
|
"40020", "40021", "40022", "40023", "40024", "40025", "40026", "40027", "40028", "40029", "40030", "40031", "40032",
|
|
"40033", "40034", "40035", "40038", "40039", "40040", "40041", "40042", "40043", "40046", "40047", "40048", "40049",
|
|
"40050", "40051", "40052", "40053", "40054", "40055", "40056", "40057",
|
|
"41000", "41001", "41002", "41003", "41004", "41005", "41006", "41007", "41008", "41998", "41999",
|
|
"42000", "42001", "42002", "42004", "42014", "42015", "42016", "42017", "42018", "42019", "42020", "42021", "42022",
|
|
"42024", "42025", "42026", "42028", "42029", "42030", "42031", "42032", "42033", "42034", "42035", "42036", "42099",
|
|
"42101", "42102", "42104", "42105", "42106", "42107", "42108", "42109", "42110", "42111", "42200", "42203", "42204",
|
|
"42205", "42206", "42207", "42300", "42301", "42302", "42303", "42304", "42305", "42306", "42307", "42308", "42309",
|
|
"42310", "42311", "42312", "42313", "42314", "42315", "42316", "42317", "42318", "42319", "42320", "42321", "42322",
|
|
"42324", "42326", "42327", "42328" };
|
|
|
|
public OrcasVBCompilerOptionsBuilder()
|
|
: base()
|
|
{
|
|
}
|
|
|
|
protected override bool IsValidWarning(string warning)
|
|
{
|
|
return validWarnings.Contains(warning);
|
|
}
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
internal sealed class CreateWorkflowManifestResourceNameForCSharp : CreateCSharpManifestResourceName
|
|
{
|
|
private bool lastAskedFileWasXoml = false;
|
|
|
|
[Output]
|
|
public new ITaskItem[] ResourceFilesWithManifestResourceNames
|
|
{
|
|
get
|
|
{
|
|
for (int i = 0; i < base.ResourceFilesWithManifestResourceNames.Length; i++)
|
|
{
|
|
ITaskItem item = base.ResourceFilesWithManifestResourceNames[i];
|
|
item.SetMetadata("LogicalName", item.GetMetadata("ManifestResourceName"));
|
|
}
|
|
|
|
return base.ResourceFilesWithManifestResourceNames;
|
|
}
|
|
set
|
|
{
|
|
base.ResourceFilesWithManifestResourceNames = value;
|
|
}
|
|
}
|
|
|
|
override protected string CreateManifestName(string fileName, string linkFileName, string rootNamespace, string dependentUponFileName, Stream binaryStream)
|
|
{
|
|
string manifestName = string.Empty;
|
|
if (!this.lastAskedFileWasXoml)
|
|
{
|
|
manifestName = base.CreateManifestName(fileName, linkFileName, rootNamespace, dependentUponFileName, binaryStream);
|
|
}
|
|
else
|
|
{
|
|
manifestName = TasksHelper.GetXomlManifestName(fileName, linkFileName, rootNamespace, binaryStream);
|
|
}
|
|
|
|
string extension = Path.GetExtension(fileName);
|
|
if (String.Compare(extension, ".rules", StringComparison.OrdinalIgnoreCase) == 0 ||
|
|
String.Compare(extension, WorkflowDesignerLoader.DesignerLayoutFileExtension, StringComparison.OrdinalIgnoreCase) == 0)
|
|
manifestName += extension;
|
|
|
|
this.lastAskedFileWasXoml = false;
|
|
return manifestName;
|
|
}
|
|
|
|
override protected bool IsSourceFile(string fileName)
|
|
{
|
|
string extension = Path.GetExtension(fileName);
|
|
if (String.Compare(extension, ".xoml", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
this.lastAskedFileWasXoml = true;
|
|
return true;
|
|
}
|
|
return base.IsSourceFile(fileName);
|
|
}
|
|
}
|
|
|
|
internal sealed class CreateWorkflowManifestResourceNameForVB : CreateVisualBasicManifestResourceName
|
|
{
|
|
private bool lastAskedFileWasXoml = false;
|
|
|
|
override protected string CreateManifestName(string fileName, string linkFileName, string rootNamespace, string dependentUponFileName, Stream binaryStream)
|
|
{
|
|
string manifestName = string.Empty;
|
|
if (!this.lastAskedFileWasXoml)
|
|
{
|
|
manifestName = base.CreateManifestName(fileName, linkFileName, rootNamespace, dependentUponFileName, binaryStream);
|
|
}
|
|
else
|
|
{
|
|
manifestName = TasksHelper.GetXomlManifestName(fileName, linkFileName, rootNamespace, binaryStream);
|
|
}
|
|
|
|
string extension = Path.GetExtension(fileName);
|
|
if (String.Compare(extension, ".rules", StringComparison.OrdinalIgnoreCase) == 0 ||
|
|
String.Compare(extension, WorkflowDesignerLoader.DesignerLayoutFileExtension, StringComparison.OrdinalIgnoreCase) == 0)
|
|
manifestName += extension;
|
|
|
|
this.lastAskedFileWasXoml = false;
|
|
return manifestName;
|
|
}
|
|
|
|
override protected bool IsSourceFile(string fileName)
|
|
{
|
|
string extension = Path.GetExtension(fileName);
|
|
if (String.Compare(extension, ".xoml", StringComparison.OrdinalIgnoreCase) == 0)
|
|
{
|
|
this.lastAskedFileWasXoml = true;
|
|
return true;
|
|
}
|
|
return base.IsSourceFile(fileName);
|
|
}
|
|
}
|
|
|
|
internal static class TasksHelper
|
|
{
|
|
internal static string GetXomlManifestName(string fileName, string linkFileName, string rootNamespace, Stream binaryStream)
|
|
{
|
|
string manifestName = string.Empty;
|
|
|
|
// Use the link file name if there is one, otherwise, fall back to file name.
|
|
string embeddedFileName = linkFileName;
|
|
if (embeddedFileName == null || embeddedFileName.Length == 0)
|
|
embeddedFileName = fileName;
|
|
|
|
Culture.ItemCultureInfo info = Culture.GetItemCultureInfo(embeddedFileName);
|
|
|
|
if (binaryStream != null)
|
|
{
|
|
// Resource depends on a form. Now, get the form's class name fully
|
|
// qualified with a namespace.
|
|
string name = null;
|
|
try
|
|
{
|
|
Xml.XmlTextReader reader = new Xml.XmlTextReader(binaryStream) { DtdProcessing = DtdProcessing.Prohibit };
|
|
if (reader.MoveToContent() == System.Xml.XmlNodeType.Element)
|
|
{
|
|
if (reader.MoveToAttribute("Class", StandardXomlKeys.Definitions_XmlNs))
|
|
name = reader.Value;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
// ignore it for now
|
|
}
|
|
|
|
if (name != null && name.Length > 0)
|
|
{
|
|
manifestName = name;
|
|
|
|
// Append the culture if there is one.
|
|
if (info.culture != null && info.culture.Length > 0)
|
|
{
|
|
manifestName = manifestName + "." + info.culture;
|
|
}
|
|
}
|
|
}
|
|
|
|
// If there's no manifest name at this point, then fall back to using the
|
|
// RootNamespace+Filename_with_slashes_converted_to_dots
|
|
if (manifestName.Length == 0)
|
|
{
|
|
// If Rootnamespace was null, then it wasn't set from the project resourceFile.
|
|
// Empty namespaces are allowed.
|
|
if (!string.IsNullOrEmpty(rootNamespace))
|
|
manifestName = rootNamespace + ".";
|
|
|
|
// Replace spaces in the directory name with underscores. Needed for compatibility with Everett.
|
|
// Note that spaces in the file name itself are preserved.
|
|
string everettCompatibleDirectoryName = CreateManifestResourceName.MakeValidEverettIdentifier(Path.GetDirectoryName(info.cultureNeutralFilename));
|
|
|
|
// only strip extension for .resx files
|
|
if (0 == String.Compare(Path.GetExtension(info.cultureNeutralFilename), ".resx", StringComparison.OrdinalIgnoreCase))
|
|
{
|
|
manifestName += Path.Combine(everettCompatibleDirectoryName, Path.GetFileNameWithoutExtension(info.cultureNeutralFilename));
|
|
|
|
// Replace all '\' with '.'
|
|
manifestName = manifestName.Replace(Path.DirectorySeparatorChar, '.');
|
|
manifestName = manifestName.Replace(Path.AltDirectorySeparatorChar, '.');
|
|
|
|
// Append the culture if there is one.
|
|
if (info.culture != null && info.culture.Length > 0)
|
|
{
|
|
manifestName = manifestName + "." + info.culture;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
manifestName += Path.Combine(everettCompatibleDirectoryName, Path.GetFileName(info.cultureNeutralFilename));
|
|
|
|
// Replace all '\' with '.'
|
|
manifestName = manifestName.Replace(Path.DirectorySeparatorChar, '.');
|
|
manifestName = manifestName.Replace(Path.AltDirectorySeparatorChar, '.');
|
|
|
|
// Prepend the culture as a subdirectory if there is one.
|
|
if (info.culture != null && info.culture.Length > 0)
|
|
{
|
|
manifestName = info.culture + Path.DirectorySeparatorChar + manifestName;
|
|
}
|
|
}
|
|
}
|
|
return manifestName;
|
|
}
|
|
|
|
}
|
|
|
|
internal static class Culture
|
|
{
|
|
static private string[] cultureInfoStrings;
|
|
|
|
internal struct ItemCultureInfo
|
|
{
|
|
internal string culture;
|
|
internal string cultureNeutralFilename;
|
|
};
|
|
|
|
internal static ItemCultureInfo GetItemCultureInfo(string name)
|
|
{
|
|
ItemCultureInfo info;
|
|
info.culture = null;
|
|
|
|
// If the item is defined as "Strings.en-US.resx", then ...
|
|
|
|
// ... base file name will be "Strings.en-US" ...
|
|
string baseFileNameWithCulture = Path.GetFileNameWithoutExtension(name);
|
|
|
|
// ... and cultureName will be ".en-US".
|
|
string cultureName = Path.GetExtension(baseFileNameWithCulture);
|
|
|
|
// See if this is a valid culture name.
|
|
bool validCulture = false;
|
|
if ((cultureName != null) && (cultureName.Length > 1))
|
|
{
|
|
// ... strip the "." to make "en-US"
|
|
cultureName = cultureName.Substring(1);
|
|
validCulture = IsValidCultureString(cultureName);
|
|
}
|
|
if (validCulture)
|
|
{
|
|
// A valid culture was found.
|
|
if (info.culture == null || info.culture.Length == 0)
|
|
{
|
|
info.culture = cultureName;
|
|
}
|
|
|
|
// Copy the assigned file and make it culture-neutral
|
|
string extension = Path.GetExtension(name);
|
|
string baseFileName = Path.GetFileNameWithoutExtension(baseFileNameWithCulture);
|
|
string baseFolder = Path.GetDirectoryName(name);
|
|
string fileName = baseFileName + extension;
|
|
info.cultureNeutralFilename = Path.Combine(baseFolder, fileName);
|
|
}
|
|
else
|
|
{
|
|
// No valid culture was found. In this case, the culture-neutral
|
|
// name is the just the original file name.
|
|
info.cultureNeutralFilename = name;
|
|
}
|
|
return info;
|
|
}
|
|
|
|
private static bool IsValidCultureString(string cultureString)
|
|
{
|
|
if (cultureInfoStrings == null)
|
|
{
|
|
CultureInfo[] cultureInfos = CultureInfo.GetCultures(CultureTypes.AllCultures);
|
|
|
|
cultureInfoStrings = new string[cultureInfos.Length];
|
|
for (int i = 0; i < cultureInfos.Length; i++)
|
|
{
|
|
cultureInfoStrings[i] = cultureInfos[i].ToString().ToLowerInvariant();
|
|
}
|
|
Array.Sort(cultureInfoStrings);
|
|
}
|
|
|
|
bool valid = true;
|
|
|
|
if (Array.BinarySearch(cultureInfoStrings, cultureString.ToLowerInvariant()) < 0)
|
|
{
|
|
valid = false;
|
|
}
|
|
|
|
return valid;
|
|
}
|
|
}
|
|
|
|
#region Class CompileWorkflowCleanupTask
|
|
// This cleanup task is a work-around for VB compilation only.
|
|
|
|
// Due to a limitation for VB.Net, we can not delete the temp file. VB does back-ground compilation for
|
|
// supporting intellisense. It re-compiles when there is a file change event that happens to each source
|
|
// file. The temp file must be added to the OutputFiles collection in order for the compiler to pick it up.
|
|
// This adds the temp file to the VB compiler project who would report an error if the file is deleted
|
|
// when re-compilation happens in the back-ground.
|
|
|
|
// However, if we don't delete the temp file, we have another problem. When we're in code-seperation mode,
|
|
// we compile our xoml files on the fly and add the buffer that contains
|
|
// the code generated based on the xoml to the project. This code conflicts with the code in the temp file,
|
|
// thus causing all sorts of type conflicting errors.
|
|
|
|
// Because the two reasons above, we wrote this cleanup task to keep the temp file but clear out the content
|
|
// of the file, thus make it work for both cases.
|
|
[Obsolete("The System.Workflow.* types are deprecated. Instead, please use the new types from System.Activities.*")]
|
|
public sealed class CompileWorkflowCleanupTask : Microsoft.Build.Utilities.Task, ITask
|
|
{
|
|
|
|
#region Members and Constructors
|
|
|
|
private ITaskItem[] temporaryFiles = null;
|
|
|
|
public CompileWorkflowCleanupTask()
|
|
:
|
|
base(new ResourceManager("System.Workflow.ComponentModel.BuildTasksStrings",
|
|
Assembly.GetExecutingAssembly()))
|
|
{
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Input parameters
|
|
public ITaskItem[] TemporaryFiles
|
|
{
|
|
get
|
|
{
|
|
return this.temporaryFiles;
|
|
}
|
|
set
|
|
{
|
|
this.temporaryFiles = value;
|
|
}
|
|
}
|
|
#endregion
|
|
|
|
#region Public method overrides
|
|
public override bool Execute()
|
|
{
|
|
if (this.temporaryFiles != null)
|
|
{
|
|
foreach (ITaskItem tempFileTask in this.temporaryFiles)
|
|
{
|
|
string tempFile = tempFileTask.ItemSpec;
|
|
if (File.Exists(tempFile))
|
|
{
|
|
FileStream fileStream = File.Open(tempFile, FileMode.Truncate);
|
|
fileStream.Close();
|
|
}
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
#endregion
|
|
}
|
|
#endregion
|
|
}
|