diff --git a/Build/RegFree.targets b/Build/RegFree.targets
index 9775afbf1c..e83d420156 100644
--- a/Build/RegFree.targets
+++ b/Build/RegFree.targets
@@ -66,7 +66,7 @@
-
+
diff --git a/Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs b/Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs
index 64b543f996..06560ce753 100644
--- a/Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs
+++ b/Build/Src/FwBuildTasks/FwBuildTasksTests/RegFreeCreatorTests.cs
@@ -1,4 +1,4 @@
-// Copyright (c) 2025 SIL International
+// Copyright (c) 2025 SIL International
// This software is licensed under the LGPL, version 2.1 or later
// (http://www.gnu.org/licenses/lgpl-2.1.html)
@@ -21,6 +21,7 @@ namespace SIL.FieldWorks.Build.Tasks.FwBuildTasksTests
public sealed class RegFreeCreatorTests
{
private const string AsmNamespace = "urn:schemas-microsoft-com:asm.v1";
+ private const string RemovedManagedLgIcuCollatorClsid = "{e771361c-ff54-4120-9525-98a0b7a9accf}";
[Test]
public void ProcessManagedAssembly_PlacesClrClassAsChildOfAssembly()
@@ -65,6 +66,76 @@ public void ProcessManagedAssembly_PlacesClrClassAsChildOfAssembly()
}
}
+ [Test]
+ public void ProcessManagedAssembly_TargetComVisibleFalseClass_DoesNotEmitClrClass()
+ {
+ var tempDir = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString("N"));
+ Directory.CreateDirectory(tempDir);
+ var assemblyPath = Path.Combine(tempDir, "SampleComVisibleFalseClass.dll");
+
+ try
+ {
+ const string source = @"using System.Runtime.InteropServices;
+[assembly: ComVisible(true)]
+[assembly: Guid(""3D757DD4-8985-4CA6-B2C4-FA2B950C9F6D"")]
+namespace RegFreeCreatorTestAssembly
+{
+ [ComVisible(false)]
+ [Guid(""e771361c-ff54-4120-9525-98a0b7a9accf"")]
+ public class SampleComVisibleFalseClass
+ {
+ }
+}";
+ CompileAssembly(assemblyPath, source);
+
+ var doc = new XmlDocument();
+ var root = doc.CreateElement("assembly", AsmNamespace);
+ doc.AppendChild(root);
+ var logger = new TaskLoggingHelper(new TestBuildEngine(), nameof(RegFreeCreatorTests));
+ var creator = new RegFreeCreator(doc, logger);
+
+ var foundClrClass = creator.ProcessManagedAssembly(root, assemblyPath);
+ Assert.That(foundClrClass, Is.False, "Assembly with only ComVisible(false) class should not produce clrClass entries.");
+
+ var ns = new XmlNamespaceManager(doc.NameTable);
+ ns.AddNamespace("asmv1", AsmNamespace);
+ var clrClassUnderAssembly = root.SelectSingleNode("asmv1:clrClass", ns);
+ Assert.That(clrClassUnderAssembly, Is.Null, "clrClass must NOT be produced for ComVisible(false) class.");
+ var removedClrClass = root.SelectSingleNode("asmv1:clrClass[@clsid='" + RemovedManagedLgIcuCollatorClsid + "']", ns);
+ Assert.That(removedClrClass, Is.Null, "Removed ManagedLgIcuCollator CLSID must not appear in generated clrClass entries.");
+ Assert.That(root.OuterXml, Does.Not.Contain(RemovedManagedLgIcuCollatorClsid));
+ }
+ finally
+ {
+ if (Directory.Exists(tempDir))
+ {
+ Directory.Delete(tempDir, true);
+ }
+ }
+ }
+
+ [Test]
+ public void AddExcludedClsids_NormalizesClsidValues()
+ {
+ var doc = new XmlDocument();
+ var root = doc.CreateElement("assembly", AsmNamespace);
+ doc.AppendChild(root);
+ var logger = new TaskLoggingHelper(new TestBuildEngine(), nameof(RegFreeCreatorTests));
+ var creator = new RegFreeCreator(doc, logger);
+
+ creator.AddExcludedClsids(new[] { "e771361c-ff54-4120-9525-98a0b7a9accf", "{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}" });
+
+ // Use reflection to verify the private field _excludedClsids was populated and normalized
+ var field = typeof(RegFreeCreator).GetField("_excludedClsids", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
+ Assert.That(field, Is.Not.Null, "Should find the private _excludedClsids field.");
+
+ var excludedHashSet = (System.Collections.Generic.HashSet)field.GetValue(creator);
+ Assert.That(excludedHashSet, Is.Not.Null);
+ Assert.That(excludedHashSet.Count, Is.EqualTo(2));
+ Assert.That(excludedHashSet.Contains(RemovedManagedLgIcuCollatorClsid), Is.True, "Should normalize Clsid without braces.");
+ Assert.That(excludedHashSet.Contains("{3fb0fcd2-ac55-42a8-b580-73b89a2b6215}"), Is.True, "Should preserve Clsid with braces.");
+ }
+
private static void CompileComVisibleAssembly(string outputPath)
{
const string source = @"using System.Runtime.InteropServices;
@@ -79,7 +150,11 @@ public class SampleComClass
{
}
}";
+ CompileAssembly(outputPath, source);
+ }
+ private static void CompileAssembly(string outputPath, string source)
+ {
var provider = new CSharpCodeProvider();
var parameters = new CompilerParameters
{
@@ -94,7 +169,7 @@ public class SampleComClass
if (results.Errors.HasErrors)
{
var message = string.Join(Environment.NewLine, results.Errors.Cast().Select(e => e.ToString()));
- throw new InvalidOperationException($"Failed to compile COM-visible test assembly:{Environment.NewLine}{message}");
+ throw new InvalidOperationException($"Failed to compile test assembly:{Environment.NewLine}{message}");
}
}
}
diff --git a/Build/mkall.targets b/Build/mkall.targets
index 03670e185b..2e441e5e60 100644
--- a/Build/mkall.targets
+++ b/Build/mkall.targets
@@ -43,7 +43,8 @@
-
+
+
diff --git a/Src/Common/FieldWorks/BuildInclude.targets b/Src/Common/FieldWorks/BuildInclude.targets
index a9c9e96c43..47f39f2eee 100644
--- a/Src/Common/FieldWorks/BuildInclude.targets
+++ b/Src/Common/FieldWorks/BuildInclude.targets
@@ -7,7 +7,7 @@
-
+
diff --git a/Src/Common/FwUtils/Win32Wrappers.cs b/Src/Common/FwUtils/Win32Wrappers.cs
index c4030d1a36..36c2981edd 100644
--- a/Src/Common/FwUtils/Win32Wrappers.cs
+++ b/Src/Common/FwUtils/Win32Wrappers.cs
@@ -2854,22 +2854,6 @@ public enum ToolBarButtonInfoFlags : long
#endregion
#region Ole32.dll
- ///
- /// Carries out the clipboard shutdown sequence. It also releases the IDataObject
- /// pointer that was previously placed on the clipboard.
- ///
- /// true if the clipboard has been flushed.
- [DllImport("ole32.dll")]
- public static extern int OleFlushClipboard();
-
- ///
- /// Determines whether the data object pointer previously placed on the clipboard is
- /// still on the clipboard.
- ///
- /// [in] Pointer to the data object previously copied or cut.
- /// true if object still on the clipboard.
- [DllImport("ole32.dll")]
- public static extern bool OleIsCurrentClipboard([MarshalAs(UnmanagedType.IUnknown)]object pDataObject);
#endregion
#region Shell32.dll
diff --git a/Src/Generic/ModuleEntry.cpp b/Src/Generic/ModuleEntry.cpp
index b0636d54a5..73cfe2fd19 100644
--- a/Src/Generic/ModuleEntry.cpp
+++ b/Src/Generic/ModuleEntry.cpp
@@ -57,7 +57,6 @@ bool ModuleEntry::s_fPerUserRegistration = false;
#endif // WIN32
#ifdef EXE_MODULE
-IDataObjectPtr ModuleEntry::s_qdobjClipboard; // data stored in clipboard by this app.
bool ModuleEntry::s_fIsExe = true;
#else // EXE_MODULE
@@ -84,11 +83,6 @@ ModuleEntry::~ModuleEntry()
The code in this section only gets included for EXE servers.
/**********************************************************************************************/
-void ModuleEntry::SetClipboard(IDataObject * pdobjClipboard)
-{
- s_qdobjClipboard = pdobjClipboard;
-}
-
/*----------------------------------------------------------------------------------------------
For an exe, we post a WM_QUIT message to the main thread when the module reference
count goes to zero.
@@ -154,7 +148,6 @@ bool ModuleEntry::Startup(HINSTANCE hinst, LPSTR pszCmdLine)
// Initialize COM
HRESULT hr = OleInitialize(NULL);
- s_qdobjClipboard.Clear();
if (FAILED(hr))
{
@@ -230,17 +223,6 @@ void ModuleEntry::ShutDown()
}
}
- // Uninitialize COM, first shutting down the clipboard.
- if (s_qdobjClipboard.Ptr())
- {
- hr = OleIsCurrentClipboard(s_qdobjClipboard.Ptr());
- WarnHr(hr);
- if (hr == S_OK)
- {
- WarnHr(OleFlushClipboard());
- }
- s_qdobjClipboard.Clear();
- }
OleUninitialize();
}
@@ -266,7 +248,6 @@ int ModuleEntry::WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine,
// Initialize COM
HRESULT hr = OleInitialize(NULL);
- s_qdobjClipboard.Clear();
if (FAILED(hr))
{
@@ -324,17 +305,6 @@ int ModuleEntry::WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine,
WarnHr(hr);
}
- // Uninitialize COM, first shutting down the clipboard.
- if (s_qdobjClipboard.Ptr())
- {
- hr = OleIsCurrentClipboard(s_qdobjClipboard.Ptr());
- WarnHr(hr);
- if (hr == S_OK)
- {
- WarnHr(OleFlushClipboard());
- }
- s_qdobjClipboard.Clear();
- }
OleUninitialize();
return nRet;
@@ -347,13 +317,6 @@ int ModuleEntry::WinMain(HINSTANCE hinst, HINSTANCE hinstPrev, LPSTR pszCmdLine,
The code in this section only gets included for DLLs.
/**********************************************************************************************/
-/*----------------------------------------------------------------------------------------------
- For a DLL, we don't have a global place to record this, so ignore it.
-----------------------------------------------------------------------------------------------*/
-void ModuleEntry::SetClipboard(IDataObject * pdobjClipboard)
-{
-}
-
/*----------------------------------------------------------------------------------------------
For a DLL, we just decrement the count. (But DON'T put this inline in the header! It
messes up the strategy for linking in the right version of ModuleEntry for DLLs versus
diff --git a/Src/Generic/ModuleEntry.h b/Src/Generic/ModuleEntry.h
index e184b5a7f2..0279be7947 100644
--- a/Src/Generic/ModuleEntry.h
+++ b/Src/Generic/ModuleEntry.h
@@ -166,8 +166,6 @@ class ModuleEntry : public LLBase
}
#ifdef EXE_MODULE
- // Data placed on the clipboard by this program.
- static IDataObjectPtr s_qdobjClipboard;
#ifdef USING_MFC
static bool Startup(HINSTANCE hinst, LPSTR pszCmdLine);
@@ -204,8 +202,6 @@ class ModuleEntry : public LLBase
{ return s_hmod; }
static LPCTSTR GetModulePathName(void);
- static void SetClipboard(IDataObject * pdobjClipboard);
-
// These methods increment and decrement the reference count for the module. A module
// will not be unloaded from memory as long as something is still referencing it.
// If these are not called properly, the module might be unloaded from memory too early,
diff --git a/Src/ManagedLgIcuCollator/LgIcuCollator.cs b/Src/ManagedLgIcuCollator/LgIcuCollator.cs
index 795c782d7c..f3bec438c9 100644
--- a/Src/ManagedLgIcuCollator/LgIcuCollator.cs
+++ b/Src/ManagedLgIcuCollator/LgIcuCollator.cs
@@ -17,9 +17,7 @@ namespace SIL.FieldWorks.Language
/// Direct port of the C++ class LgIcuCollator
///
[Serializable]
- [ComVisible(true)]
- [ClassInterface(ClassInterfaceType.None)]
- [Guid("e771361c-ff54-4120-9525-98a0b7a9accf")]
+ [ComVisible(false)]
public class ManagedLgIcuCollator : ILgCollatingEngine, IDisposable
{
#region Member variables