ProjectFile?TryCreateSatelliteFile(ModuleDef module, string rsrcName, FilenameCreator filenameCreator, ProjectFile nonSatFile) { if (!Options.CreateResX) { return(null); } var asm = module.Assembly; Debug.Assert(!(asm is null) && !UTF8String.IsNullOrEmpty(asm.Culture)); if (asm is null || UTF8String.IsNullOrEmpty(asm.Culture)) { return(null); } var name = FileUtils.RemoveExtension(rsrcName); var ext = FileUtils.GetExtension(rsrcName); var locName = name + "." + asm.Culture + ext; var er = module.Resources.OfType <EmbeddedResource>().FirstOrDefault(a => StringComparer.Ordinal.Equals(a.Name, locName)); var set = TryCreateResourceElementSet(module, er); if (set is null) { return(null); } var dirName = Path.GetDirectoryName(nonSatFile.Filename); var dir = Directory.Length + 1 > dirName.Length ? string.Empty : dirName.Substring(Directory.Length + 1); name = Path.GetFileNameWithoutExtension(nonSatFile.Filename); ext = Path.GetExtension(nonSatFile.Filename); var filename = filenameCreator.CreateFromRelativePath(Path.Combine(dir, name) + "." + asm.Culture, ext); return(CreateResXFile(module, er, set, filename, string.Empty, true)); }
IEnumerable <ProjectFile> CreateSatelliteFiles(string rsrcName, FilenameCreator filenameCreator, ProjectFile nonSatFile) { foreach (var satMod in satelliteAssemblyFinder.GetSatelliteAssemblies(Options.Module)) { var satFile = TryCreateSatelliteFile(satMod, rsrcName, filenameCreator, nonSatFile); if (!(satFile is null)) { yield return(satFile); } } }
public static ApplicationManifest TryCreate(Win32Resources resources, FilenameCreator filenameCreator) { if (resources == null) return null; var dir = resources.Find(new ResourceName(RT_MANIFEST)); if (dir == null || dir.Directories.Count == 0) return null; dir = dir.Directories[0]; if (dir.Data.Count == 0) return null; var data = dir.Data[0].Data.ReadAllBytes(); return new ApplicationManifest(filenameCreator.CreateName("app.manifest"), data); }
public static ApplicationIcon TryCreate(Win32Resources resources, string filenameNoExt, FilenameCreator filenameCreator) { if (resources == null) return null; var dir = resources.Find(new ResourceName(RT_GROUP_ICON)); if (dir == null || dir.Directories.Count == 0) return null; dir = dir.Directories[0]; if (dir.Data.Count == 0) return null; var iconDir = resources.Find(new ResourceName(RT_ICON)); if (iconDir == null) return null; var iconData = TryCreateIcon(dir.Data[0].Data, iconDir); if (iconData == null) return null; return new ApplicationIcon(filenameCreator.CreateName(filenameNoExt + ".ico"), iconData); }
public static ApplicationManifest TryCreate(Win32Resources resources, FilenameCreator filenameCreator) { if (resources == null) { return(null); } var dir = resources.Find(new ResourceName(RT_MANIFEST)); if (dir == null || dir.Directories.Count == 0) { return(null); } dir = dir.Directories[0]; if (dir.Data.Count == 0) { return(null); } var reader = dir.Data[0].CreateReader(); return(new ApplicationManifest(filenameCreator.CreateName("app.manifest"), ref reader)); }
ProjectFile CreateTypeProjectFile(TypeDef type, FilenameCreator filenameCreator) { var bamlFile = TryGetBamlFile(type); if (!(bamlFile is null)) { var filename = filenameCreator.Create(GetTypeExtension(type), type.FullName); TypeProjectFile newFile; var isAppType = DotNetUtils.IsSystemWindowsApplication(type); if (!Options.Decompiler.CanDecompile(DecompilationType.PartialType)) { newFile = new TypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); } else { newFile = new XamlTypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); } newFile.DependentUpon = bamlFile; if (isAppType && DotNetUtils.IsStartUpClass(type)) { bamlFile.IsAppDef = true; StartupObject = null; } if (isAppType) { appTypeProjFile = newFile; } return(newFile); } const string DESIGNER = ".Designer"; var resxFile = TryGetResXFile(type); if (DotNetUtils.IsWinForm(type)) { var fname = !(resxFile is null) ? Path.GetFileNameWithoutExtension(resxFile.Filename) : type.Name.String; var filename = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, fname); var dname = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, fname + DESIGNER); var newFile = new WinFormsProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); if (!(resxFile is null)) { resxFile.DependentUpon = newFile; } var winFormsDesignerFile = new WinFormsDesignerProjectFile(newFile, dname, createDecompilerOutput); winFormsDesignerFile.DependentUpon = newFile; Files.Add(winFormsDesignerFile); return(newFile); } else if (!(resxFile is null)) { var filename = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, Path.GetFileNameWithoutExtension(resxFile.Filename) + DESIGNER); var newFile = new TypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); newFile.DependentUpon = resxFile; newFile.AutoGen = true; newFile.DesignTime = true; resxFile.Generator = type.IsPublic ? "PublicResXFileCodeGenerator" : "ResXFileCodeGenerator"; resxFile.LastGenOutput = newFile; return(newFile); } var bt = type.BaseType; if (!(bt is null) && bt.FullName == "System.Configuration.ApplicationSettingsBase") { var designerFilename = filenameCreator.Create(DESIGNER + GetTypeExtension(type), type.FullName); var settingsFilename = filenameCreator.Create(".settings", type.FullName); ProjectFile designerTypeFile; if (Options.Decompiler.CanDecompile(DecompilationType.PartialType)) { var typeFilename = filenameCreator.Create(GetTypeExtension(type), type.FullName); var settingsTypeFile = new SettingsTypeProjectFile(type, typeFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); designerTypeFile = new SettingsDesignerTypeProjectFile(settingsTypeFile, designerFilename, createDecompilerOutput); Files.Add(settingsTypeFile); } else { designerTypeFile = new TypeProjectFile(type, designerFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); } var settingsFile = new SettingsProjectFile(type, settingsFilename); designerTypeFile.DependentUpon = settingsFile; designerTypeFile.AutoGen = true; designerTypeFile.DesignTimeSharedInput = true; settingsFile.Generator = type.IsPublic ? "PublicSettingsSingleFileGenerator" : "SettingsSingleFileGenerator"; settingsFile.LastGenOutput = designerTypeFile; Files.Add(settingsFile); return(designerTypeFile); } var newFilename = filenameCreator.Create(GetTypeExtension(type), type.FullName); return(new TypeProjectFile(type, newFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput)); }
public void CreateProjectFiles(DecompileContext ctx) { var filenameCreator = new FilenameCreator(Directory, DefaultNamespace); var resourceNameCreator = new ResourceNameCreator(Options.Module, filenameCreator); AllowUnsafeBlocks = DotNetUtils.IsUnsafe(Options.Module); InitializeSplashScreen(); if (Options.Decompiler.CanDecompile(DecompilationType.AssemblyInfo)) { var filename = filenameCreator.CreateFromRelativePath(Path.Combine(PropertiesFolder, "AssemblyInfo"), Options.Decompiler.FileExtension); Files.Add(new AssemblyInfoProjectFile(Options.Module, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput)); } var ep = Options.Module.EntryPoint; if (!(ep is null) && !(ep.DeclaringType is null)) { StartupObject = ep.DeclaringType.ReflectionFullName; } applicationManifest = ApplicationManifest.TryCreate(Options.Module.Win32Resources, filenameCreator); if (!(ApplicationManifest is null)) { Files.Add(new ApplicationManifestProjectFile(ApplicationManifest.Filename)); } foreach (var rsrc in Options.Module.Resources) { ctx.CancellationToken.ThrowIfCancellationRequested(); switch (rsrc.ResourceType) { case ResourceType.Embedded: foreach (var file in CreateEmbeddedResourceFiles(Options.Module, resourceNameCreator, (EmbeddedResource)rsrc)) { Files.Add(file); Files.AddRange(CreateSatelliteFiles(rsrc.Name, filenameCreator, file)); } break; case ResourceType.AssemblyLinked: //TODO: What should be created here? break; case ResourceType.Linked: //TODO: What should be created here? break; default: break; } } InitializeXaml(); InitializeResX(); foreach (var type in Options.Module.Types) { ctx.CancellationToken.ThrowIfCancellationRequested(); if (!DecompileType(type)) { continue; } Files.Add(CreateTypeProjectFile(type, filenameCreator)); } CreateEmptyAppXamlFile(); var existingAppConfig = Options.Module.Location + ".config"; if (File.Exists(existingAppConfig)) { Files.Add(new AppConfigProjectFile(filenameCreator.CreateName("app.config"), existingAppConfig)); } applicationIcon = ApplicationIcon.TryCreate(Options.Module.Win32Resources, Path.GetFileName(Directory), filenameCreator); var dirs = new HashSet <string>(Files.Select(a => GetDirectoryName(a.Filename)).OfType <string>(), StringComparer.OrdinalIgnoreCase); int errors = 0; foreach (var dir in dirs) { ctx.CancellationToken.ThrowIfCancellationRequested(); try { System.IO.Directory.CreateDirectory(dir); } catch (Exception ex) { if (errors++ < 20) { ctx.Logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_CouldNotCreateDirectory2, dir, ex.Message)); } } } }
public void Create() { SatelliteAssemblyFinder?satelliteAssemblyFinder = null; try { var opts = new ParallelOptions { CancellationToken = options.CancellationToken, MaxDegreeOfParallelism = options.NumberOfThreads <= 0 ? Environment.ProcessorCount : options.NumberOfThreads, }; var filenameCreator = new FilenameCreator(options.Directory); var ctx = new DecompileContext(options.CancellationToken, logger); satelliteAssemblyFinder = new SatelliteAssemblyFinder(); Parallel.ForEach(options.ProjectModules, opts, modOpts => { options.CancellationToken.ThrowIfCancellationRequested(); string name; lock (filenameCreator) name = filenameCreator.Create(modOpts.Module); var p = new Project(modOpts, name, satelliteAssemblyFinder, options.CreateDecompilerOutput); lock (projects) projects.Add(p); p.CreateProjectFiles(ctx); }); var jobs = GetJobs().ToArray(); bool writeSolutionFile = !string.IsNullOrEmpty(options.SolutionFilename); int maxProgress = jobs.Length + projects.Count; if (writeSolutionFile) { maxProgress++; } progressListener.SetMaxProgress(maxProgress); Parallel.ForEach(GetJobs(), opts, job => { options.CancellationToken.ThrowIfCancellationRequested(); try { job.Create(ctx); } catch (OperationCanceledException) { throw; } catch (Exception ex) { if (job is IFileJob fjob) { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FileCreationFailed3, fjob.Filename, job.Description, ex.Message)); } else { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FileCreationFailed2, job.Description, ex.Message)); } } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); }); Parallel.ForEach(projects, opts, p => { options.CancellationToken.ThrowIfCancellationRequested(); try { var writer = new ProjectWriter(p, p.Options.ProjectVersion ?? options.ProjectVersion, projects, options.UserGACPaths); writer.Write(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FailedToCreateProjectFile, p.Filename, ex.Message)); } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); }); if (writeSolutionFile) { options.CancellationToken.ThrowIfCancellationRequested(); try { var writer = new SolutionWriter(options.ProjectVersion, projects, SolutionFilename); writer.Write(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FailedToCreateSolutionFile, SolutionFilename, ex.Message)); } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); } Debug.Assert(totalProgress == maxProgress); progressListener.SetProgress(maxProgress); } finally { if (satelliteAssemblyFinder is not null) { satelliteAssemblyFinder.Dispose(); } } }
public static ApplicationIcon TryCreate(Win32Resources resources, string filenameNoExt, FilenameCreator filenameCreator) { if (resources == null) { return(null); } var dir = resources.Find(new ResourceName(RT_GROUP_ICON)); if (dir == null || dir.Directories.Count == 0) { return(null); } dir = dir.Directories[0]; if (dir.Data.Count == 0) { return(null); } var iconDir = resources.Find(new ResourceName(RT_ICON)); if (iconDir == null) { return(null); } var reader = dir.Data[0].CreateReader(); var iconData = TryCreateIcon(ref reader, iconDir); if (iconData == null) { return(null); } return(new ApplicationIcon(filenameCreator.CreateName(filenameNoExt + ".ico"), iconData)); }
public ResourceNameCreator(ModuleDef module, FilenameCreator filenameCreator) { this.module = module; this.filenameCreator = filenameCreator; }
public void CreateProjectFiles(DecompileContext ctx) { var filenameCreator = new FilenameCreator(Directory, DefaultNamespace); var resourceNameCreator = new ResourceNameCreator(Options.Module, filenameCreator); AllowUnsafeBlocks = DotNetUtils.IsUnsafe(Options.Module); InitializeSplashScreen(); if (Options.Decompiler.CanDecompile(DecompilationType.AssemblyInfo)) { var filename = filenameCreator.CreateFromRelativePath(Path.Combine(PropertiesFolder, "AssemblyInfo"), Options.Decompiler.FileExtension); Files.Add(new AssemblyInfoProjectFile(Options.Module, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput)); } var ep = Options.Module.EntryPoint; if (ep != null && ep.DeclaringType != null) StartupObject = ep.DeclaringType.ReflectionFullName; applicationManifest = ApplicationManifest.TryCreate(Options.Module.Win32Resources, filenameCreator); if (ApplicationManifest != null) Files.Add(new ApplicationManifestProjectFile(ApplicationManifest.Filename)); foreach (var rsrc in Options.Module.Resources) { ctx.CancellationToken.ThrowIfCancellationRequested(); switch (rsrc.ResourceType) { case ResourceType.Embedded: foreach (var file in CreateEmbeddedResourceFiles(Options.Module, resourceNameCreator, (EmbeddedResource)rsrc)) { Files.Add(file); Files.AddRange(CreateSatelliteFiles(rsrc.Name, filenameCreator, file)); } break; case ResourceType.AssemblyLinked: //TODO: What should be created here? break; case ResourceType.Linked: //TODO: What should be created here? break; default: break; } } InitializeXaml(); InitializeResX(); foreach (var type in Options.Module.Types) { ctx.CancellationToken.ThrowIfCancellationRequested(); if (!DecompileType(type)) continue; Files.Add(CreateTypeProjectFile(type, filenameCreator)); } CreateEmptyAppXamlFile(); var existingAppConfig = Options.Module.Location + ".config"; if (File.Exists(existingAppConfig)) Files.Add(new AppConfigProjectFile(filenameCreator.CreateName("App.config"), existingAppConfig)); applicationIcon = ApplicationIcon.TryCreate(Options.Module.Win32Resources, Path.GetFileName(Directory), filenameCreator); var dirs = new HashSet<string>(Files.Select(a => GetDirectoryName(a.Filename)).Where(a => a != null), StringComparer.OrdinalIgnoreCase); int errors = 0; foreach (var dir in dirs) { ctx.CancellationToken.ThrowIfCancellationRequested(); try { System.IO.Directory.CreateDirectory(dir); } catch (Exception ex) { if (errors++ < 20) ctx.Logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_CouldNotCreateDirectory2, dir, ex.Message)); } } }
ProjectFile TryCreateSatelliteFile(ModuleDef module, string rsrcName, FilenameCreator filenameCreator, ProjectFile nonSatFile) { if (!Options.CreateResX) return null; var asm = module.Assembly; Debug.Assert(asm != null && !UTF8String.IsNullOrEmpty(asm.Culture)); if (asm == null || UTF8String.IsNullOrEmpty(asm.Culture)) return null; var name = FileUtils.RemoveExtension(rsrcName); var ext = FileUtils.GetExtension(rsrcName); var locName = name + "." + asm.Culture + ext; var er = module.Resources.OfType<EmbeddedResource>().FirstOrDefault(a => StringComparer.Ordinal.Equals(a.Name, locName)); var set = TryCreateResourceElementSet(module, er); if (set == null) return null; var dir = Path.GetDirectoryName(nonSatFile.Filename).Substring(Directory.Length + 1); name = Path.GetFileNameWithoutExtension(nonSatFile.Filename); ext = Path.GetExtension(nonSatFile.Filename); var filename = filenameCreator.CreateFromRelativePath(Path.Combine(dir, name) + "." + asm.Culture, ext); return CreateResXFile(module, er, set, filename, string.Empty, true); }
IEnumerable<ProjectFile> CreateSatelliteFiles(string rsrcName, FilenameCreator filenameCreator, ProjectFile nonSatFile) { foreach (var satMod in satelliteAssemblyFinder.GetSatelliteAssemblies(Options.Module)) { var satFile = TryCreateSatelliteFile(satMod, rsrcName, filenameCreator, nonSatFile); if (satFile != null) yield return satFile; } }
ProjectFile CreateTypeProjectFile(TypeDef type, FilenameCreator filenameCreator) { var bamlFile = TryGetBamlFile(type); if (bamlFile != null) { var filename = filenameCreator.Create(GetTypeExtension(type), type.FullName); TypeProjectFile newFile; var isAppType = DotNetUtils.IsSystemWindowsApplication(type); if (!Options.Decompiler.CanDecompile(DecompilationType.PartialType)) newFile = new TypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); else newFile = new XamlTypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); newFile.DependentUpon = bamlFile; if (isAppType && DotNetUtils.IsStartUpClass(type)) { bamlFile.IsAppDef = true; StartupObject = null; } if (isAppType) appTypeProjFile = newFile; return newFile; } const string DESIGNER = ".Designer"; var resxFile = TryGetResXFile(type); if (resxFile != null) { if (DotNetUtils.IsWinForm(type)) { var filename = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, Path.GetFileNameWithoutExtension(resxFile.Filename)); var newFile = new WinFormsProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); resxFile.DependentUpon = newFile; var dname = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, Path.GetFileNameWithoutExtension(resxFile.Filename) + DESIGNER); var winFormsDesignerFile = new WinFormsDesignerProjectFile(newFile, dname, createDecompilerOutput); winFormsDesignerFile.DependentUpon = newFile; Files.Add(winFormsDesignerFile); return newFile; } else { var filename = filenameCreator.CreateFromNamespaceName(GetTypeExtension(type), type.ReflectionNamespace, Path.GetFileNameWithoutExtension(resxFile.Filename) + DESIGNER); var newFile = new TypeProjectFile(type, filename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); newFile.DependentUpon = resxFile; newFile.AutoGen = true; newFile.DesignTime = true; resxFile.Generator = type.IsPublic ? "PublicResXFileCodeGenerator" : "ResXFileCodeGenerator"; resxFile.LastGenOutput = newFile; return newFile; } } var bt = type.BaseType; if (bt != null && bt.FullName == "System.Configuration.ApplicationSettingsBase") { var designerFilename = filenameCreator.Create(DESIGNER + GetTypeExtension(type), type.FullName); var settingsFilename = filenameCreator.Create(".settings", type.FullName); ProjectFile designerTypeFile; if (Options.Decompiler.CanDecompile(DecompilationType.PartialType)) { var typeFilename = filenameCreator.Create(GetTypeExtension(type), type.FullName); var settingsTypeFile = new SettingsTypeProjectFile(type, typeFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); designerTypeFile = new SettingsDesignerTypeProjectFile(settingsTypeFile, designerFilename, createDecompilerOutput); Files.Add(settingsTypeFile); } else designerTypeFile = new TypeProjectFile(type, designerFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); var settingsFile = new SettingsProjectFile(type, settingsFilename); designerTypeFile.DependentUpon = settingsFile; designerTypeFile.AutoGen = true; designerTypeFile.DesignTimeSharedInput = true; settingsFile.Generator = type.IsPublic ? "PublicSettingsSingleFileGenerator" : "SettingsSingleFileGenerator"; settingsFile.LastGenOutput = designerTypeFile; Files.Add(settingsFile); return designerTypeFile; } var newFilename = filenameCreator.Create(GetTypeExtension(type), type.FullName); return new TypeProjectFile(type, newFilename, Options.DecompilationContext, Options.Decompiler, createDecompilerOutput); }
public void Create() { SatelliteAssemblyFinder satelliteAssemblyFinder = null; try { var opts = new ParallelOptions { CancellationToken = options.CancellationToken, MaxDegreeOfParallelism = options.NumberOfThreads <= 0 ? Environment.ProcessorCount : options.NumberOfThreads, }; var filenameCreator = new FilenameCreator(options.Directory); var ctx = new DecompileContext(options.CancellationToken, logger); satelliteAssemblyFinder = new SatelliteAssemblyFinder(); Parallel.ForEach(options.ProjectModules, opts, modOpts => { options.CancellationToken.ThrowIfCancellationRequested(); string name; lock (filenameCreator) name = filenameCreator.Create(modOpts.Module); var p = new Project(modOpts, name, satelliteAssemblyFinder, options.CreateDecompilerOutput); lock (projects) projects.Add(p); p.CreateProjectFiles(ctx); }); var jobs = GetJobs().ToArray(); bool writeSolutionFile = !string.IsNullOrEmpty(options.SolutionFilename); int maxProgress = jobs.Length + projects.Count; if (writeSolutionFile) maxProgress++; progressListener.SetMaxProgress(maxProgress); Parallel.ForEach(GetJobs(), opts, job => { options.CancellationToken.ThrowIfCancellationRequested(); try { job.Create(ctx); } catch (OperationCanceledException) { throw; } catch (Exception ex) { var fjob = job as IFileJob; if (fjob != null) logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FileCreationFailed3, fjob.Filename, job.Description, ex.Message)); else logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FileCreationFailed2, job.Description, ex.Message)); } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); }); Parallel.ForEach(projects, opts, p => { options.CancellationToken.ThrowIfCancellationRequested(); try { var writer = new ProjectWriter(p, p.Options.ProjectVersion ?? options.ProjectVersion, projects, options.UserGACPaths); writer.Write(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FailedToCreateProjectFile, p.Filename, ex.Message)); } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); }); if (writeSolutionFile) { options.CancellationToken.ThrowIfCancellationRequested(); try { var writer = new SolutionWriter(options.ProjectVersion, projects, SolutionFilename); writer.Write(); } catch (OperationCanceledException) { throw; } catch (Exception ex) { logger.Error(string.Format(dnSpy_Decompiler_Resources.MSBuild_FailedToCreateSolutionFile, SolutionFilename, ex.Message)); } progressListener.SetProgress(Interlocked.Increment(ref totalProgress)); } Debug.Assert(totalProgress == maxProgress); progressListener.SetProgress(maxProgress); } finally { if (satelliteAssemblyFinder != null) satelliteAssemblyFinder.Dispose(); } }