public void GetBoolWithDefault() { Csc t = new Csc(); t.Bag["Key"] = true; Assert.AreEqual(true, t.GetBoolParameterWithDefault("Key", false)); }
public void TestResourceAccess() { Csc t = new Csc(); MockEngine engine = new MockEngine(); t.BuildEngine = engine; // No need to actually check the outputted strings. We only care that this doesn't throw, which means that // the resource strings were reachable. // Normal CSC messages first, from private XMakeTasks resources. They should be accessible with t.Log t.Log.LogErrorWithCodeFromResources("Csc.AssemblyAliasContainsIllegalCharacters", "PlanetSide", "Knights of the Old Republic"); t.Log.LogWarningWithCodeFromResources("Csc.InvalidParameter"); t.Log.LogMessageFromResources("Vbc.ParameterHasInvalidValue", "Rome Total War", "Need for Speed Underground"); // Now shared messages. Should be accessible with the private LogShared property PropertyInfo logShared = typeof(ToolTask).GetProperty("LogShared", BindingFlags.Instance | BindingFlags.NonPublic); TaskLoggingHelper log = (TaskLoggingHelper)logShared.GetValue(t, null); log.LogWarningWithCodeFromResources("Shared.FailedCreatingTempFile", "Gothic II"); log.LogMessageFromResources("Shared.CannotConvertStringToBool", "foo"); // Now private Utilities messages. Should be accessible with the private LogPrivate property PropertyInfo logPrivate = typeof(ToolTask).GetProperty("LogPrivate", BindingFlags.Instance | BindingFlags.NonPublic); log = (TaskLoggingHelper)logPrivate.GetValue(t, null); log.LogErrorWithCodeFromResources("ToolTask.CommandTooLong", "Painkiller"); log.LogWarningWithCodeFromResources("ToolTask.CouldNotStartToolExecutable", "Fallout Tactics", "Fallout 2"); log.LogMessageFromResources("ToolsLocationHelper.InvalidRedistFile", "Deus Ex", "Fallout"); }
public void ResourceAccessSanityCheck() { Csc t = new Csc(); MockEngine engine = new MockEngine(); t.BuildEngine = engine; t.Log.LogErrorFromResources("Beyond Good and Evil"); }
public void SingleAliasUnicodeOnAReference() { Csc t = new Csc(); TaskItem reference = new TaskItem("System.Xml.dll"); reference.SetMetadata("Aliases", "?"); t.References = new TaskItem[] { reference }; CommandLine.ValidateHasParameter(t, "/reference:?=System.Xml.dll"); }
public void MultipleAliasesOnAReference() { Csc t = new Csc(); TaskItem reference = new TaskItem("System.Xml.dll"); reference.SetMetadata("Aliases", "Foo, Bar"); t.References = new TaskItem[] { reference }; CommandLine.ValidateHasParameter(t, "/reference:Foo=System.Xml.dll"); CommandLine.ValidateHasParameter(t, "/reference:Bar=System.Xml.dll"); }
/// <summary> /// Old VS projects had some pretty messed-up looking values for the /// "DefineConstants" property. It worked fine in the IDE, because it /// effectively munged up the string so that it ended up being valid for /// the compiler. We do the equivalent munging here now. /// /// Basically, we take the incoming string, and split it on comma/semicolon/space. /// Then we look at the resulting list of strings, and remove any that are /// illegal identifiers, and pass the remaining ones through to the compiler. /// /// Note that CSharp does support assigning a value to the constants ... in /// other words, a constant is either defined or not defined ... it can't have /// an actual value. /// </summary> internal string GetDefineConstantsSwitch ( string originalDefineConstants ) { if (originalDefineConstants == null) { return(null); } StringBuilder finalDefineConstants = new StringBuilder(); // Split the incoming string on comma/semicolon/space. string[] allIdentifiers = originalDefineConstants.Split(new char[] { ',', ';', ' ' }); // Loop through all the parts, and for the ones that are legal C# identifiers, // add them to the outgoing string. foreach (string singleIdentifier in allIdentifiers) { if (Csc.IsLegalIdentifier(singleIdentifier)) { // Separate them with a semicolon if there's something already in // the outgoing string. if (finalDefineConstants.Length > 0) { finalDefineConstants.Append(";"); } finalDefineConstants.Append(singleIdentifier); } else if (singleIdentifier.Length > 0) { Log.LogWarningWithCodeFromResources("Csc.InvalidParameterWarning", "/define:", singleIdentifier); } } if (finalDefineConstants.Length > 0) { return(finalDefineConstants.ToString()); } else { // We wouldn't want to pass in an empty /define: switch on the csc.exe command-line. return(null); } }
internal string GetDefineConstantsSwitch(string originalDefineConstants) { if (originalDefineConstants == null) { return(null); } StringBuilder stringBuilder = new StringBuilder(); string[] array = originalDefineConstants.Split(new char[] { ',', ';', ' ' }); string[] array2 = array; for (int i = 0; i < array2.Length; i++) { string text = array2[i]; if (Csc.IsLegalIdentifier(text)) { if (stringBuilder.Length > 0) { stringBuilder.Append(";"); } stringBuilder.Append(text); } else { if (text.Length > 0) { base.Log.LogWarningWithCodeFromResources("Csc.InvalidParameterWarning", new object[] { "/define:", text }); } } } if (stringBuilder.Length > 0) { return(stringBuilder.ToString()); } return(null); }
/// <summary> /// Invokes CSC to build the given files against the given set of references /// </summary> /// <param name="files"></param> /// <param name="referenceAssemblies"></param> /// <param name="lang"></param> public static bool CompileCSharpSource(IEnumerable<string> files, IEnumerable<string> referenceAssemblies) { List<ITaskItem> sources = new List<ITaskItem>(); foreach (string f in files) sources.Add(new TaskItem(f)); List<ITaskItem> references = new List<ITaskItem>(); foreach (string s in referenceAssemblies) references.Add(new TaskItem(s)); Csc csc = new Csc(); MockBuildEngine buildEngine = new MockBuildEngine(); csc.BuildEngine = buildEngine; // needed before task can log csc.NoStandardLib = true; // don't include std lib stuff -- we're feeding it silverlight csc.NoConfig = true; // don't load the csc.rsp file to get references csc.TargetType = "library"; csc.Sources = sources.ToArray(); csc.References = references.ToArray(); bool result = false; try { result = csc.Execute(); } catch (Exception ex) { Assert.Fail("Exception occurred invoking CSC task on " + sources[0].ItemSpec + ":\r\n" + ex); } if (!result) { string sourceList = string.Empty; foreach (TaskItem t in sources) { sourceList += " " + t.ItemSpec + "\r\n"; } Assert.Fail("CSC failed to compile sources:\r\n" + sourceList + "\r\n" + buildEngine.ConsoleLogger.Errors + "\r\n\r\nReference assemblies were:\r\n" + ReferenceAssembliesAsString(referenceAssemblies)); } return result; }
/// <summary> /// Invokes CSC to build the given files against the given set of references /// </summary> /// <param name="files"></param> /// <param name="referenceAssemblies"></param> /// <param name="lang"></param> /// <param name="documentationFile">If nonblank, the documentation file to generate during the compile.</param> public static bool CompileCSharpSource(IEnumerable<string> files, IEnumerable<string> referenceAssemblies, string documentationFile) { List<ITaskItem> sources = new List<ITaskItem>(); foreach (string f in files) sources.Add(new TaskItem(f)); List<ITaskItem> references = new List<ITaskItem>(); foreach (string s in referenceAssemblies) references.Add(new TaskItem(s)); Csc csc = new Csc(); MockBuildEngine buildEngine = new MockBuildEngine(); csc.BuildEngine = buildEngine; // needed before task can log csc.NoStandardLib = true; // don't include std lib stuff -- we're feeding it silverlight csc.NoConfig = true; // don't load the csc.rsp file to get references csc.TargetType = "library"; csc.Sources = sources.ToArray(); csc.References = references.ToArray(); csc.DefineConstants += "SILVERLIGHT"; if (!string.IsNullOrEmpty(documentationFile)) { csc.DocumentationFile = documentationFile; } bool result = false; try { result = csc.Execute(); } catch (Exception ex) { Assert.Fail("Exception occurred invoking CSC task on " + sources[0].ItemSpec + ":\r\n" + ex); } Assert.IsTrue(result, "CSC failed to compile " + sources[0].ItemSpec + ":\r\n" + buildEngine.ConsoleLogger.Errors); return result; }
public void TestAssignment () { Csc csc = new Csc (); csc.AllowUnsafeBlocks = true; csc.BaseAddress = "1"; csc.CheckForOverflowUnderflow = true; csc.DisabledWarnings = "2"; csc.DocumentationFile = "3"; csc.ErrorReport = "4"; csc.GenerateFullPaths = true; csc.LangVersion = "5"; csc.ModuleAssemblyName = "6"; csc.NoStandardLib = true; csc.PdbFile = "7"; csc.Platform = "8"; csc.UseHostCompilerIfAvailable = true; csc.WarningLevel = 9; csc.WarningsAsErrors = "10"; csc.WarningsNotAsErrors = "11"; Assert.AreEqual (true, csc.AllowUnsafeBlocks, "A1"); Assert.AreEqual ("1", csc.BaseAddress, "A2"); Assert.AreEqual (true, csc.CheckForOverflowUnderflow, "A3"); Assert.AreEqual ("2", csc.DisabledWarnings, "A4"); Assert.AreEqual ("3", csc.DocumentationFile, "A5"); Assert.AreEqual ("4", csc.ErrorReport, "A6"); Assert.AreEqual (true, csc.GenerateFullPaths, "A7"); Assert.AreEqual ("5", csc.LangVersion, "A8"); Assert.AreEqual ("6", csc.ModuleAssemblyName, "A9"); Assert.AreEqual ("7", csc.PdbFile, "A10"); Assert.AreEqual ("8", csc.Platform, "A11"); Assert.AreEqual (true, csc.UseHostCompilerIfAvailable, "A12"); Assert.AreEqual (9, csc.WarningLevel, "A13"); Assert.AreEqual ("10", csc.WarningsAsErrors, "A14"); Assert.AreEqual ("11", csc.WarningsNotAsErrors, "A15"); }
/// <summary> /// When overridden in a derived class, executes the task. /// </summary> /// <returns> /// true if the task successfully executed; otherwise, false. /// </returns> public override bool Execute() { if (!File.Exists(ProtocExe)) { Log.LogError(string.Format("Could not find protoc.exe at path '{0}'", ProtocExe)); } if (!Directory.Exists(tempDir)) { Log.LogError(string.Format("Temporary directory does not exist '{0}'", TempDir)); return false; } Directory.CreateDirectory(GetTempDir()); if (!Directory.Exists(Output)) { Log.LogError(string.Format("Output directory does not exist '{0}'", Output)); return false; } if (Protos.Length < 1) { Log.LogError(string.Format("No input files where specified")); return false; } var files = Protos.Select(i => new FileInfo(i.ItemSpec)).ToArray(); foreach (var file in files.Where(file => !file.Exists)) { Log.LogError(string.Format("Could not find input file '{0}'", file.Name)); return false; } if (!ExecuteProtoc(files) && GenerateProtos()) return false; if (OutputAssembly != null) { var compile = new Csc { BuildEngine = BuildEngine, OutputAssembly = OutputAssembly, References = AssemblyReferences, Sources = Directory.GetFiles(Output, "*.cs").Select(f => new TaskItem(f)).ToArray(), DebugType = "pdbonly", WarningLevel = 1, TargetType = "library", KeyFile = KeyFile }; return compile.Execute(); } return true; }
public void MultipleAdditionalFiles_CommandLine() { Csc csc = new Csc(); csc.AdditionalFiles = new TaskItem[] { new TaskItem("app.config"), new TaskItem("web.config") }; CommandLine.ValidateHasParameter(csc, "/additionalfile:app.config"); CommandLine.ValidateHasParameter(csc, "/additionalfile:web.config"); }
public void NoAdditionalFiles_CommandLine() { Csc csc = new Csc(); CommandLine.ValidateNoParameterStartsWith(csc, "/additionalfile"); }
public void RuleSet_HostObject() { IBuildEngine2 mockEngine = new MockEngine(); Csc csc = new Csc(); csc.BuildEngine = mockEngine; MockCscAnalyzerHostObject cscHostObject = new MockCscAnalyzerHostObject(); cscHostObject.SetDesignTime(true); csc.HostObject = cscHostObject; csc.UseHostCompilerIfAvailable = true; Assert.IsNull(cscHostObject.RuleSet); csc.CodeAnalysisRuleSet = "Bar.ruleset"; csc.Sources = new TaskItem[] { new TaskItem("a.cs") }; bool cscSuccess = csc.Execute(); Assert.IsTrue(cscSuccess, "Csc task failed."); Assert.AreEqual("Bar.ruleset", cscHostObject.RuleSet); }
public void RuleSet_CommandLine() { Csc csc = new Csc(); csc.CodeAnalysisRuleSet = "Bar.ruleset"; CommandLine.ValidateHasParameter(csc, "/ruleset:Bar.ruleset"); }
public void WarningsAsErrors() { Csc t = new Csc(); t.WarningsAsErrors = @"parm1 /out:c:\windows\system32\notepad.exe"; CommandLine.ValidateNoParameterStartsWith(t, "/out"); }
public void MainEntryPoint() { Csc t = new Csc(); t.MainEntryPoint = @"parm1 /out:c:\windows\system32\notepad.exe"; CommandLine.ValidateNoParameterStartsWith(t, "/out"); }
public void OutputAssembly() { Csc t = new Csc(); t.OutputAssembly = new TaskItem(@"parm1 /out:c:\windows\system32\notepad.exe"); CommandLine.ValidateHasParameter(t, @"/out:parm1 /out:c:\windows\system32\notepad.exe"); }
public void ResponseFiles() { Csc t = new Csc(); t.ResponseFiles = new TaskItem[] { new TaskItem(@"parm1 /out:c:\windows\system32\notepad.exe") }; CommandLine.ValidateNoParameterStartsWith(t, "/out"); }
public void NoAnalyzers_CommandLine() { Csc csc = new Csc(); CommandLine.ValidateNoParameterStartsWith(csc, "/analyzer"); }
public void SingleResponseFile() { Csc t = new Csc(); t.ResponseFiles = new TaskItem[] { new TaskItem(@"1.rsp") }; CommandLine.ValidateHasParameter(t, "@1.rsp"); }
public void MultipleResponseFiles() { Csc t = new Csc(); t.ResponseFiles = new TaskItem[] { new TaskItem(@"1.rsp"), new TaskItem(@"2.rsp"), new TaskItem(@"3.rsp"), new TaskItem(@"4.rsp") }; CommandLine.ValidateContains(t, "@1.rsp @2.rsp @3.rsp @4.rsp", true); }
public void Win32Resource() { Csc t = new Csc(); t.Win32Resource = @"parm1 /out:c:\windows\system32\notepad.exe"; CommandLine.ValidateNoParameterStartsWith(t, "/out"); }
/// <summary> /// Executes a task. /// </summary> /// <returns> /// true if the task executed successfully; otherwise, false. /// </returns> public override bool Execute() { if (POFiles != null) { foreach (ITaskItem item in POFiles) { // Verify that POFile exists. if (!File.Exists(item.ItemSpec)) { _LogMessage(string.Format(CultureInfo.InvariantCulture, "File {0} does not exists.", item.ItemSpec)); return false; } // Get file info from file. FileInfo fileInfo = new FileInfo(item.ItemSpec); // Assume that FileName is in the format: locale.extension // Get locale from FileName. string locale = fileInfo.Name.Replace(fileInfo.Extension, string.Empty); string outputPath = OutputPath + "\\" + locale; // If OutputPath directory does not exist, create it. if (!Directory.Exists(outputPath)) Directory.CreateDirectory(outputPath); // Create the output assembly name. string assemblyFileName = Path.Combine(outputPath, AssemblyName + ".resources.dll"); // Verify if assemblyFile exists if (File.Exists(assemblyFileName)) { //FileInfo dllInfo = new FileInfo(assemblyFileName); //if (dllInfo.LastWriteTime.CompareTo(fileInfo.LastWriteTime) > 0) // continue; // Continue to next item cause Assembly is newer than current po file. //else File.Delete(assemblyFileName); } //Get the temporary path to store the C# classes. string csOutputPath = System.IO.Path.GetTempPath(); // Get the C# file template from embedded resources. string template = Resource.template; // Get the file name for the C# class string csFileName = Path.Combine(csOutputPath, string.Format(CultureInfo.InvariantCulture, "{0}.{1}", AssemblyName, "cs")); // Get the class name for the C# class string className = string.Format(CultureInfo.InvariantCulture, "{0}_{1}", ConstructClassName(AssemblyName), locale.Replace("-", "_")); // String builder to hold the key value pairs retrieved from the po file. StringBuilder s = new StringBuilder(); using (FileStream fileStream = new FileStream(item.ItemSpec, FileMode.Open)) { // Read the po file. _ReadPOFile(s, new StreamReader(fileStream, Encoding.UTF8)); } // Get bytes for the new C# class byte[] bytes = Encoding.UTF8.GetBytes(template.Replace("{0}", className).Replace("{1}", s.ToString())); // Write the C# class to disk. using (FileStream csStream = new FileStream(csFileName, FileMode.Create)) { csStream.Write(bytes, 0, bytes.Length); } _LogMessage(string.Format(CultureInfo.InvariantCulture, "Created file {0}", csFileName)); // Log if GNU.Gettext.dll not found. if (!File.Exists(GNUGetTextAssemblyPath)) { _LogMessage(string.Format(CultureInfo.InvariantCulture, "Unable to find dependency file: {0}", GNUGetTextAssemblyPath)); return false; } var fileinfo = new FileInfo(GNUGetTextAssemblyPath); // Compile c# class. Csc csc = new Csc(); csc.HostObject = this.HostObject; csc.BuildEngine = this.BuildEngine; csc.AdditionalLibPaths = new string[] { fileinfo.Directory.FullName }; csc.TargetType = "library"; csc.References = new TaskItem[] { new TaskItem(fileinfo.Name) }; csc.OutputAssembly = new TaskItem(assemblyFileName); csc.Sources = new TaskItem[] { new TaskItem(csFileName) }; csc.Execute(); _LogMessage(string.Format(CultureInfo.InvariantCulture, "Created assembly {0}", assemblyFileName)); } return true; } return true; }
public void NonAliasedReference1() { Csc t = new Csc(); TaskItem reference = new TaskItem("System.Xml.dll"); reference.SetMetadata("Aliases", "global"); t.References = new TaskItem[] { reference }; CommandLine.ValidateHasParameter(t, "/reference:System.Xml.dll"); }
public void NoRuleSet_CommandLine() { Csc csc = new Csc(); CommandLine.ValidateNoParameterStartsWith(csc, "/ruleset"); }
public void MultipleAnalyzers_CommandLine() { Csc csc = new Csc(); csc.Analyzers = new TaskItem[] { new TaskItem("Foo.dll"), new TaskItem("Bar.dll") }; CommandLine.ValidateHasParameter(csc, "/analyzer:Foo.dll"); CommandLine.ValidateHasParameter(csc, "/analyzer:Bar.dll"); }
public void ToolPath() { Csc t = new Csc(); t.ToolPath = @"parm1 /out:c:\windows\system32\notepad.exe"; CommandLine.ValidateNoParameterStartsWith(t, "/out"); }
public void TestDefaultValues () { Csc csc = new Csc (); Assert.IsFalse (csc.AllowUnsafeBlocks, "A1"); Assert.IsNull (csc.BaseAddress, "A2"); Assert.IsFalse (csc.CheckForOverflowUnderflow, "A3"); Assert.IsNull (csc.DisabledWarnings, "A4"); Assert.IsNull (csc.DocumentationFile, "A5"); Assert.IsNull (csc.ErrorReport, "A6"); Assert.IsFalse (csc.GenerateFullPaths, "A7"); Assert.IsNull (csc.LangVersion, "A8"); Assert.IsNull (csc.ModuleAssemblyName, "A9"); Assert.IsNull (csc.PdbFile, "A10"); Assert.IsNull (csc.Platform, "A11"); Assert.IsFalse (csc.UseHostCompilerIfAvailable, "A12"); Assert.AreEqual (4, csc.WarningLevel, "A13"); Assert.IsNull (csc.WarningsAsErrors, "A14"); Assert.IsNull (csc.WarningsNotAsErrors, "A15"); }
public void NoAnalyzer_HostObject() { IBuildEngine2 mockEngine = new MockEngine(); Csc csc = new Csc(); csc.BuildEngine = mockEngine; MockCscAnalyzerHostObject cscHostObject = new MockCscAnalyzerHostObject(); cscHostObject.SetDesignTime(true); csc.HostObject = cscHostObject; csc.UseHostCompilerIfAvailable = true; Assert.IsNull(cscHostObject.Analyzers); csc.Sources = new TaskItem[] { new TaskItem("a.cs") }; bool cscSuccess = csc.Execute(); Assert.IsTrue(cscSuccess, "Csc task failed."); Assert.IsNull(cscHostObject.Analyzers); }
public override bool Execute() { string defDir = SafePath(ThriftDefinitionDir.ItemSpec); //look for last compilation timestamp string lastBuildPath = Path.Combine(defDir, lastCompilationName); DirectoryInfo defDirInfo = new DirectoryInfo(defDir); string lastWrite = LastWriteTime(defDir); if (File.Exists(lastBuildPath)) { string lastComp = File.ReadAllText(lastBuildPath); //don't recompile if the thrift library has been updated since lastComp FileInfo f = new FileInfo(ThriftLibrary.ItemSpec); string thriftLibTime = f.LastWriteTimeUtc.ToFileTimeUtc().ToString(); if (lastComp.CompareTo(thriftLibTime) < 0) { //new thrift library, do a compile lastWrite = thriftLibTime; } else if (lastComp == lastWrite || (lastComp == thriftLibTime && lastComp.CompareTo(lastWrite) > 0)) { //the .thrift dir hasn't been written to since last compilation, don't need to do anything LogMessage("ThriftImpl up-to-date", MessageImportance.High); return true; } } //find the directory of the thriftlibrary (that's where output will go) FileInfo thriftLibInfo = new FileInfo(SafePath(ThriftLibrary.ItemSpec)); string thriftDir = thriftLibInfo.Directory.FullName; string genDir = Path.Combine(thriftDir, "gen-csharp"); if (Directory.Exists(genDir)) { try { Directory.Delete(genDir, true); } catch { /*eh i tried, just over-write now*/} } //run the thrift executable to generate C# foreach (string thriftFile in Directory.GetFiles(defDir, "*.thrift")) { LogMessage("Generating code for: " + thriftFile, MessageImportance.Normal); Process p = new Process(); p.StartInfo.FileName = SafePath(ThriftExecutable.ItemSpec); p.StartInfo.Arguments = "-csharp -o " + SafePath(thriftDir) + " -r " + thriftFile; p.StartInfo.UseShellExecute = false; p.StartInfo.CreateNoWindow = true; p.StartInfo.RedirectStandardOutput = false; p.Start(); p.WaitForExit(); if (p.ExitCode != 0) { LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); return false; } if (p.ExitCode != 0) { LogMessage("thrift.exe failed to compile " + thriftFile, MessageImportance.High); return false; } } Csc csc = new Csc(); csc.TargetType = "library"; csc.References = new ITaskItem[] { new TaskItem(ThriftLibrary.ItemSpec) }; csc.EmitDebugInformation = true; string outputPath = Path.Combine(thriftDir, OutputName.ItemSpec); csc.OutputAssembly = new TaskItem(outputPath); csc.Sources = FindSources(Path.Combine(thriftDir, "gen-csharp")); csc.BuildEngine = this.BuildEngine; LogMessage("Compiling generated cs...", MessageImportance.Normal); if (!csc.Execute()) { return false; } //write file to defDir to indicate a build was successfully completed File.WriteAllText(lastBuildPath, lastWrite); thriftImpl = new TaskItem(outputPath); return true; }
public void MultipleAnalyzers_HostObject() { IBuildEngine2 mockEngine = new MockEngine(); Csc csc = new Csc(); csc.BuildEngine = mockEngine; MockCscAnalyzerHostObject cscHostObject = new MockCscAnalyzerHostObject(); cscHostObject.SetDesignTime(true); csc.HostObject = cscHostObject; csc.UseHostCompilerIfAvailable = true; Assert.IsNull(cscHostObject.Analyzers); csc.Analyzers = new TaskItem[] { new TaskItem("Foo.dll"), new TaskItem("Bar.dll") }; csc.Sources = new TaskItem[] { new TaskItem("a.cs") }; bool cscSuccess = csc.Execute(); Assert.IsTrue(cscSuccess, "Csc task failed."); Assert.AreEqual(2, cscHostObject.Analyzers.Length); Assert.AreEqual("Foo.dll", cscHostObject.Analyzers[0].ItemSpec); Assert.AreEqual("Bar.dll", cscHostObject.Analyzers[1].ItemSpec); }