/// <summary> /// Reads the specified file from disk into a StateFileBase derived object. /// </summary> internal static StateFileBase DeserializeCache(string stateFile, TaskLoggingHelper log, Type requiredReturnType) { StateFileBase retVal = null; // First, we read the cache from disk if one exists, or if one does not exist // then we create one. try { if (!string.IsNullOrEmpty(stateFile) && FileSystems.Default.FileExists(stateFile)) { using (FileStream s = new FileStream(stateFile, FileMode.Open)) { var formatter = new BinaryFormatter(); object deserializedObject = formatter.Deserialize(s); retVal = deserializedObject as StateFileBase; // If the deserialized object is null then there would be no cast error but retVal would still be null // only log the message if there would have been a cast error if (retVal == null && deserializedObject != null) { // When upgrading to Visual Studio 2008 and running the build for the first time the resource cache files are replaced which causes a cast error due // to a new version number on the tasks class. "Unable to cast object of type 'net.r_eg.IeXod.Tasks.SystemState' to type 'net.r_eg.IeXod.Tasks.StateFileBase". // If there is an invalid cast, a message rather than a warning should be emitted. log.LogMessageFromResources("General.CouldNotReadStateFileMessage", stateFile, log.FormatResourceString("General.IncompatibleStateFileType")); } if ((retVal != null) && (!requiredReturnType.IsInstanceOfType(retVal))) { log.LogWarningWithCodeFromResources("General.CouldNotReadStateFile", stateFile, log.FormatResourceString("General.IncompatibleStateFileType")); retVal = null; } // If we get back a valid object and internals were changed, things are likely to be null. Check the version before we use it. if (retVal != null && retVal._serializedVersion != CurrentSerializationVersion) { log.LogMessageFromResources("General.CouldNotReadStateFileMessage", stateFile, log.FormatResourceString("General.IncompatibleStateFileType")); retVal = null; } } } } catch (Exception e) { if (ExceptionHandling.IsCriticalException(e)) { throw; } // The deserialization process seems like it can throw just about // any exception imaginable. Catch them all here. // Not being able to deserialize the cache is not an error, but we let the user know anyway. // Don't want to hold up processing just because we couldn't read the file. log.LogWarningWithCodeFromResources("General.CouldNotReadStateFile", stateFile, e.Message); } return(retVal); }
/// <summary> /// Task entry point /// </summary> /// <returns></returns> public override bool Execute() { AssemblyRegistrationCache cacheFile; if (AssemblyListFile != null) { cacheFile = (AssemblyRegistrationCache)StateFileBase.DeserializeCache(AssemblyListFile.ItemSpec, Log, typeof(AssemblyRegistrationCache)); // no cache file, nothing to do. In case there was a problem reading the cache file, we can't do anything anyway. if (cacheFile == null) { StateFileBase.DeleteFile(AssemblyListFile.ItemSpec, Log); return(true); } } else { if (Assemblies == null) { Log.LogErrorWithCodeFromResources("UnregisterAssembly.AssemblyPathOrStateFileIsRequired", GetType().Name); return(false); } // TypeLibFiles isn't [Required], but if it is specified, it must have the same length as Assemblies if (TypeLibFiles != null && TypeLibFiles.Length != Assemblies.Length) { Log.LogErrorWithCodeFromResources("General.TwoVectorsMustHaveSameLength", Assemblies.Length, TypeLibFiles.Length, "Assemblies", "TypeLibFiles"); return(false); } cacheFile = new AssemblyRegistrationCache(); for (int i = 0; i < Assemblies.Length; i++) { // if the type lib path is not supplied, generate default one if (TypeLibFiles != null && TypeLibFiles[i] != null && TypeLibFiles[i].ItemSpec.Length > 0) { cacheFile.AddEntry(Assemblies[i].ItemSpec, TypeLibFiles[i].ItemSpec); } else { cacheFile.AddEntry(Assemblies[i].ItemSpec, Path.ChangeExtension(Assemblies[i].ItemSpec, ".tlb")); } } } bool taskReturnValue = true; try { for (int i = 0; i < cacheFile.Count; i++) { cacheFile.GetEntry(i, out string assemblyPath, out string typeLibraryPath); try { // If one of assemblies failed to unregister, the whole task failed. // We still process the rest of assemblies though. if (!Unregister(assemblyPath, typeLibraryPath)) { taskReturnValue = false; } } catch (ArgumentException ex) // assembly path has invalid chars in it { Log.LogErrorWithCodeFromResources("General.InvalidAssemblyName", assemblyPath, ex.Message); taskReturnValue = false; } #if DEBUG catch (Exception e) { Debug.Assert(false, "Unexpected exception in AssemblyRegistration.Execute. " + "Please log a MSBuild bug specifying the steps to reproduce the problem. " + e.Message); throw; } #endif } } finally { if (AssemblyListFile != null) { StateFileBase.DeleteFile(AssemblyListFile.ItemSpec, Log); } } return(taskReturnValue); }