From fa6b8ec9eaee8cca68a1e40f5025bd91a9a32431 Mon Sep 17 00:00:00 2001 From: petarcrncecIMP Date: Thu, 9 Apr 2026 09:40:52 +0200 Subject: [PATCH] Fix file locking: dispose AssemblyDefinition and skip copy-back for binaries Two changes to prevent the source DLL from being locked after loading: 1. Wrap AssemblyDefinition (Mono.Cecil) in a `using` block so the file handle on the original DLL is released immediately after the command rename pass. Previously the handle was held indefinitely, preventing MSBuild from writing to the DLL during rebuild. 2. Skip .dll/.pdb/.exe files in CopyGeneratedFilesBack(). Compiled assemblies never change at runtime, so copying them back to the original folder is unnecessary and can briefly lock the files. Co-Authored-By: Claude Opus 4.6 --- CadAddinManager/Model/AssemLoader.cs | 71 ++++++++++++++++------------ 1 file changed, 42 insertions(+), 29 deletions(-) diff --git a/CadAddinManager/Model/AssemLoader.cs b/CadAddinManager/Model/AssemLoader.cs index fc3f8e6..d674d9c 100644 --- a/CadAddinManager/Model/AssemLoader.cs +++ b/CadAddinManager/Model/AssemLoader.cs @@ -30,12 +30,22 @@ public AssemLoader() copiedFiles = new Dictionary(); } + private static readonly HashSet SkipCopyBackExtensions = new(StringComparer.OrdinalIgnoreCase) + { + ".dll", ".pdb", ".exe" + }; + public void CopyGeneratedFilesBack() { var files = Directory.GetFiles(tempFolder, "*.*", SearchOption.AllDirectories); if(!files.Any()) return; foreach (var text in files) { + // Never copy compiled assemblies back — they don't change at runtime + // and copying them back locks the original files for MSBuild + var ext = Path.GetExtension(text); + if (SkipCopyBackExtensions.Contains(ext)) continue; + if (copiedFiles.ContainsKey(text)) { var t = copiedFiles[text]; @@ -93,49 +103,52 @@ private string ResolveDuplicateMethod(string originalFilePath) { // AssemblyDefinition ass = AssemblyDefinition.ReadAssembly(originalFilePath); - AssemblyDefinition ass = GetAssemblyDef(originalFilePath); - foreach (ModuleDefinition def in ass.Modules) + string fileAssemblyTemp; + using (AssemblyDefinition ass = GetAssemblyDef(originalFilePath)) { - foreach (TypeDefinition d in def.Types) + foreach (ModuleDefinition def in ass.Modules) { - foreach (MethodDefinition m in d.Methods) + foreach (TypeDefinition d in def.Types) { - if (!m.IsConstructor && !m.IsRuntimeSpecialName && m.Name != "Main") + foreach (MethodDefinition m in d.Methods) { - foreach (CustomAttribute customAttribute in m.CustomAttributes) + if (!m.IsConstructor && !m.IsRuntimeSpecialName && m.Name != "Main") { - if (customAttribute.Constructor.DeclaringType.Name == "CommandMethodAttribute") + foreach (CustomAttribute customAttribute in m.CustomAttributes) { - int count = customAttribute.ConstructorArguments.Count; - CustomAttribute newAttr = null; - if (count == 4) - { - newAttr = CreateCustomAttribute4Type(customAttribute); - } - if (count == 3) + if (customAttribute.Constructor.DeclaringType.Name == "CommandMethodAttribute") { - newAttr = CreateCustomAttribute3Type(customAttribute); + int count = customAttribute.ConstructorArguments.Count; + CustomAttribute newAttr = null; + if (count == 4) + { + newAttr = CreateCustomAttribute4Type(customAttribute); + } + if (count == 3) + { + newAttr = CreateCustomAttribute3Type(customAttribute); + } + else if (count == 2) + { + newAttr = CreateCustomAttribute2Type(customAttribute); + } + else if (count == 1) + { + newAttr = CreateCustomAttribute1Type(customAttribute); + } + m.CustomAttributes.Remove(customAttribute); + m.CustomAttributes.Add(newAttr); + break; } - else if (count == 2) - { - newAttr = CreateCustomAttribute2Type(customAttribute); - } - else if (count == 1) - { - newAttr = CreateCustomAttribute1Type(customAttribute); - } - m.CustomAttributes.Remove(customAttribute); - m.CustomAttributes.Add(newAttr); - break; } } } } } + fileAssemblyTemp = SaveAssemblyModifyToTemp(originalFilePath); + ass.Write(fileAssemblyTemp, new WriterParameters() { WriteSymbols = true }); } - string fileAssemblyTemp = SaveAssemblyModifyToTemp(originalFilePath); - ass.Write(fileAssemblyTemp, new WriterParameters() { WriteSymbols = true }); - return fileAssemblyTemp; + return fileAssemblyTemp; } public static AssemblyDefinition GetAssemblyDef(string assemblyPath) {