diff --git a/Directory.Packages.props b/Directory.Packages.props
index 8a44ec12f..7b49e983f 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -59,4 +59,4 @@
-
+
\ No newline at end of file
diff --git a/src/fdc3/dotnet/AppDirectory/AppDirectory.sln b/src/fdc3/dotnet/AppDirectory/AppDirectory.sln
index f9f6b43b5..7b6cdf9c4 100644
--- a/src/fdc3/dotnet/AppDirectory/AppDirectory.sln
+++ b/src/fdc3/dotnet/AppDirectory/AppDirectory.sln
@@ -11,12 +11,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AppDirectory.Tests", "test\
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{62C29BA4-0D3B-4764-A898-38F29FF5C36C}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Testing", "..\..\..\shared\dotnet\MorganStanley.ComposeUI.Testing\MorganStanley.ComposeUI.Testing.csproj", "{08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC}"
-EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "test", "test", "{976748F5-4871-48F4-8AE0-99ABFB733D29}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.ModuleLoader.Abstractions", "..\..\..\module-loader\dotnet\src\MorganStanley.ComposeUI.ModuleLoader.Abstractions\MorganStanley.ComposeUI.ModuleLoader.Abstractions.csproj", "{7038B36A-ADD6-4882-BFBC-ED7E4B422520}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Testing", "..\..\..\shared\dotnet\tests\TestUtils\MorganStanley.ComposeUI.Testing\MorganStanley.ComposeUI.Testing.csproj", "{823FEEB6-1B94-42EF-B2E6-28C7A8F649E6}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -31,14 +31,14 @@ Global
{EAA7B5A8-FD08-4E2F-809B-6CBD489714C1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{EAA7B5A8-FD08-4E2F-809B-6CBD489714C1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{EAA7B5A8-FD08-4E2F-809B-6CBD489714C1}.Release|Any CPU.Build.0 = Release|Any CPU
- {08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC}.Release|Any CPU.Build.0 = Release|Any CPU
{7038B36A-ADD6-4882-BFBC-ED7E4B422520}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7038B36A-ADD6-4882-BFBC-ED7E4B422520}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7038B36A-ADD6-4882-BFBC-ED7E4B422520}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7038B36A-ADD6-4882-BFBC-ED7E4B422520}.Release|Any CPU.Build.0 = Release|Any CPU
+ {823FEEB6-1B94-42EF-B2E6-28C7A8F649E6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {823FEEB6-1B94-42EF-B2E6-28C7A8F649E6}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {823FEEB6-1B94-42EF-B2E6-28C7A8F649E6}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {823FEEB6-1B94-42EF-B2E6-28C7A8F649E6}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -46,8 +46,8 @@ Global
GlobalSection(NestedProjects) = preSolution
{4B8CA047-2023-4E1A-BD73-85F7EB1D56B3} = {9E52D00C-AABB-4579-8724-6CC7049F021E}
{EAA7B5A8-FD08-4E2F-809B-6CBD489714C1} = {976748F5-4871-48F4-8AE0-99ABFB733D29}
- {08AEA9CD-1DA8-4A73-BB10-90B0EF0EE8DC} = {62C29BA4-0D3B-4764-A898-38F29FF5C36C}
{7038B36A-ADD6-4882-BFBC-ED7E4B422520} = {62C29BA4-0D3B-4764-A898-38F29FF5C36C}
+ {823FEEB6-1B94-42EF-B2E6-28C7A8F649E6} = {62C29BA4-0D3B-4764-A898-38F29FF5C36C}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {D2C43446-C01E-438A-8A88-554F1351D134}
diff --git a/src/fdc3/dotnet/AppDirectory/test/AppDirectory.Tests/AppDirectory.Tests.csproj b/src/fdc3/dotnet/AppDirectory/test/AppDirectory.Tests/AppDirectory.Tests.csproj
index 451ba818f..29d42cee7 100644
--- a/src/fdc3/dotnet/AppDirectory/test/AppDirectory.Tests/AppDirectory.Tests.csproj
+++ b/src/fdc3/dotnet/AppDirectory/test/AppDirectory.Tests/AppDirectory.Tests.csproj
@@ -29,7 +29,7 @@
-
+
diff --git a/src/messaging/dotnet/Messaging.sln b/src/messaging/dotnet/Messaging.sln
index 218114cd7..f6fa697b4 100644
--- a/src/messaging/dotnet/Messaging.sln
+++ b/src/messaging/dotnet/Messaging.sln
@@ -29,10 +29,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Mes
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "lib", "lib", "{B7E63957-3C1B-4A16-B530-3EAD0D0C5F07}"
EndProject
-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Testing", "..\..\shared\dotnet\MorganStanley.ComposeUI.Testing\MorganStanley.ComposeUI.Testing.csproj", "{AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE}"
-EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Messaging.Host.Tests", "test\Host.Tests\MorganStanley.ComposeUI.Messaging.Host.Tests.csproj", "{CEF78D3F-C645-4471-BAD2-9C538A0CA763}"
EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Testing", "..\..\shared\dotnet\tests\TestUtils\MorganStanley.ComposeUI.Testing\MorganStanley.ComposeUI.Testing.csproj", "{F1B0C089-450E-4B02-881F-F41A8B7F5867}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -75,14 +75,14 @@ Global
{AA63BC7C-9DB8-4062-A689-7FA9689EF6B1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{AA63BC7C-9DB8-4062-A689-7FA9689EF6B1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{AA63BC7C-9DB8-4062-A689-7FA9689EF6B1}.Release|Any CPU.Build.0 = Release|Any CPU
- {AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE}.Release|Any CPU.Build.0 = Release|Any CPU
{CEF78D3F-C645-4471-BAD2-9C538A0CA763}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CEF78D3F-C645-4471-BAD2-9C538A0CA763}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CEF78D3F-C645-4471-BAD2-9C538A0CA763}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CEF78D3F-C645-4471-BAD2-9C538A0CA763}.Release|Any CPU.Build.0 = Release|Any CPU
+ {F1B0C089-450E-4B02-881F-F41A8B7F5867}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {F1B0C089-450E-4B02-881F-F41A8B7F5867}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {F1B0C089-450E-4B02-881F-F41A8B7F5867}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {F1B0C089-450E-4B02-881F-F41A8B7F5867}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -97,8 +97,8 @@ Global
{CDC30566-1801-40CD-9EBD-2913418FC2F9} = {78E94277-B0B4-425C-9C47-81E09933FE5B}
{29122DF1-0AE3-4101-9D96-4711553C7696} = {B245E9BB-69CC-4457-9FDF-635E742993CB}
{AA63BC7C-9DB8-4062-A689-7FA9689EF6B1} = {78E94277-B0B4-425C-9C47-81E09933FE5B}
- {AE71CBC4-FD4E-4C66-B894-D7C31DE4D1BE} = {B7E63957-3C1B-4A16-B530-3EAD0D0C5F07}
{CEF78D3F-C645-4471-BAD2-9C538A0CA763} = {78E94277-B0B4-425C-9C47-81E09933FE5B}
+ {F1B0C089-450E-4B02-881F-F41A8B7F5867} = {B7E63957-3C1B-4A16-B530-3EAD0D0C5F07}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {38CFF5DF-459A-49E1-8189-2DB429A99B3A}
diff --git a/src/messaging/dotnet/test/Client.Tests/MorganStanley.ComposeUI.Messaging.Client.Tests.csproj b/src/messaging/dotnet/test/Client.Tests/MorganStanley.ComposeUI.Messaging.Client.Tests.csproj
index 419c38142..4632aa710 100644
--- a/src/messaging/dotnet/test/Client.Tests/MorganStanley.ComposeUI.Messaging.Client.Tests.csproj
+++ b/src/messaging/dotnet/test/Client.Tests/MorganStanley.ComposeUI.Messaging.Client.Tests.csproj
@@ -11,7 +11,7 @@
-
+
diff --git a/src/messaging/dotnet/test/IntegrationTests/MorganStanley.ComposeUI.Messaging.IntegrationTests.csproj b/src/messaging/dotnet/test/IntegrationTests/MorganStanley.ComposeUI.Messaging.IntegrationTests.csproj
index 9230cba71..33eed27ed 100644
--- a/src/messaging/dotnet/test/IntegrationTests/MorganStanley.ComposeUI.Messaging.IntegrationTests.csproj
+++ b/src/messaging/dotnet/test/IntegrationTests/MorganStanley.ComposeUI.Messaging.IntegrationTests.csproj
@@ -15,7 +15,7 @@
-
+
\ No newline at end of file
diff --git a/src/messaging/dotnet/test/Server.Tests/MorganStanley.ComposeUI.Messaging.Server.Tests.csproj b/src/messaging/dotnet/test/Server.Tests/MorganStanley.ComposeUI.Messaging.Server.Tests.csproj
index a689ae382..b2e7e53f9 100644
--- a/src/messaging/dotnet/test/Server.Tests/MorganStanley.ComposeUI.Messaging.Server.Tests.csproj
+++ b/src/messaging/dotnet/test/Server.Tests/MorganStanley.ComposeUI.Messaging.Server.Tests.csproj
@@ -14,7 +14,7 @@
-
+
\ No newline at end of file
diff --git a/src/shared/dotnet/MorganStanley.ComposeUI.Shared.sln b/src/shared/dotnet/MorganStanley.ComposeUI.Shared.sln
index c73c52e13..94c7a7e69 100644
--- a/src/shared/dotnet/MorganStanley.ComposeUI.Shared.sln
+++ b/src/shared/dotnet/MorganStanley.ComposeUI.Shared.sln
@@ -11,6 +11,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Uti
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Utilities.Tests", "tests\MorganStanley.ComposeUI.Utilities.Tests\MorganStanley.ComposeUI.Utilities.Tests.csproj", "{ED668A15-0186-41CD-B79D-2D9F18A6F15B}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "TestUtils", "TestUtils", "{01E62FC1-7F5E-4C75-8F6C-1C9027BCBFEC}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MorganStanley.ComposeUI.Testing", "tests\TestUtils\MorganStanley.ComposeUI.Testing\MorganStanley.ComposeUI.Testing.csproj", "{71213EAF-2B49-4756-AD62-EE3C1CB7315C}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -25,6 +29,10 @@ Global
{ED668A15-0186-41CD-B79D-2D9F18A6F15B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ED668A15-0186-41CD-B79D-2D9F18A6F15B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ED668A15-0186-41CD-B79D-2D9F18A6F15B}.Release|Any CPU.Build.0 = Release|Any CPU
+ {71213EAF-2B49-4756-AD62-EE3C1CB7315C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {71213EAF-2B49-4756-AD62-EE3C1CB7315C}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {71213EAF-2B49-4756-AD62-EE3C1CB7315C}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {71213EAF-2B49-4756-AD62-EE3C1CB7315C}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -32,6 +40,8 @@ Global
GlobalSection(NestedProjects) = preSolution
{13B9FB01-144E-4BBE-9920-1C69B44FB711} = {8E838164-6370-4320-ACD5-CD1E6631C09C}
{ED668A15-0186-41CD-B79D-2D9F18A6F15B} = {51355F98-9BDE-42CA-B284-296AAE6B6B38}
+ {01E62FC1-7F5E-4C75-8F6C-1C9027BCBFEC} = {51355F98-9BDE-42CA-B284-296AAE6B6B38}
+ {71213EAF-2B49-4756-AD62-EE3C1CB7315C} = {01E62FC1-7F5E-4C75-8F6C-1C9027BCBFEC}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {EF62D6D0-E133-4C3A-A1AF-79C44BAD39C4}
diff --git a/src/shared/dotnet/src/MorganStanley.ComposeUI.Utilities/NativeMethods.cs b/src/shared/dotnet/src/MorganStanley.ComposeUI.Utilities/NativeMethods.cs
new file mode 100644
index 000000000..e21f121a9
--- /dev/null
+++ b/src/shared/dotnet/src/MorganStanley.ComposeUI.Utilities/NativeMethods.cs
@@ -0,0 +1,24 @@
+/*
+ * Morgan Stanley makes this available to you under the Apache License,
+ * Version 2.0 (the "License"). You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0.
+ *
+ * See the NOTICE file distributed with this work for additional information
+ * regarding copyright ownership. Unless required by applicable law or agreed
+ * to in writing, software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+ * or implied. See the License for the specific language governing permissions
+ * and limitations under the License.
+ */
+
+using System.Runtime.InteropServices;
+using System;
+
+namespace MorganStanley.ComposeUI.Utilities;
+
+public static class NativeMethods
+{
+ [DllImport("gdi32.dll", SetLastError = true)]
+ public static extern bool DeleteObject(in IntPtr hObject);
+}
\ No newline at end of file
diff --git a/src/shared/dotnet/MorganStanley.ComposeUI.Testing/MorganStanley.ComposeUI.Testing.csproj b/src/shared/dotnet/tests/TestUtils/MorganStanley.ComposeUI.Testing/MorganStanley.ComposeUI.Testing.csproj
similarity index 100%
rename from src/shared/dotnet/MorganStanley.ComposeUI.Testing/MorganStanley.ComposeUI.Testing.csproj
rename to src/shared/dotnet/tests/TestUtils/MorganStanley.ComposeUI.Testing/MorganStanley.ComposeUI.Testing.csproj
diff --git a/src/shared/dotnet/MorganStanley.ComposeUI.Testing/TaskExtensions.cs b/src/shared/dotnet/tests/TestUtils/MorganStanley.ComposeUI.Testing/TaskExtensions.cs
similarity index 100%
rename from src/shared/dotnet/MorganStanley.ComposeUI.Testing/TaskExtensions.cs
rename to src/shared/dotnet/tests/TestUtils/MorganStanley.ComposeUI.Testing/TaskExtensions.cs
diff --git a/src/shell/dotnet/Shell.sln b/src/shell/dotnet/Shell.sln
index aab923825..f563c0fb3 100644
--- a/src/shell/dotnet/Shell.sln
+++ b/src/shell/dotnet/Shell.sln
@@ -34,7 +34,9 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "examples", "examples", "{DA
examples\module-catalog.json = examples\module-catalog.json
EndProjectSection
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DiagnosticsExample", "..\..\..\examples\dotnet-diagnostics\DiagnosticsExample\DiagnosticsExample.csproj", "{24E64AFE-D2C5-487D-85F3-B0CE5AC0A128}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DiagnosticsExample", "..\..\..\examples\dotnet-diagnostics\DiagnosticsExample\DiagnosticsExample.csproj", "{24E64AFE-D2C5-487D-85F3-B0CE5AC0A128}"
+EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{9173857E-84BF-4F8B-906B-39BCF0A8915B}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
diff --git a/src/shell/dotnet/Shell/App.xaml.cs b/src/shell/dotnet/Shell/App.xaml.cs
index 8f5205621..3bd52206d 100644
--- a/src/shell/dotnet/Shell/App.xaml.cs
+++ b/src/shell/dotnet/Shell/App.xaml.cs
@@ -31,7 +31,6 @@
using MorganStanley.ComposeUI.ModuleLoader;
using MorganStanley.ComposeUI.Shell.Abstractions;
using MorganStanley.ComposeUI.Shell.Fdc3;
-using MorganStanley.ComposeUI.Shell.ImageSource;
using MorganStanley.ComposeUI.Shell.Messaging;
using MorganStanley.ComposeUI.Shell.Modules;
using MorganStanley.ComposeUI.Shell.Utilities;
@@ -125,7 +124,7 @@ private async Task StartAsync(StartupEventArgs e)
};
await _host.Services.GetRequiredService().RegisterServiceAsync("Diagnostics", (e, m, t) =>
- ValueTask.FromResult(MessageBuffer.Factory.CreateJson(diagnostics))!);
+ ValueTask.FromResult(MessageBuffer.Factory.CreateJson(diagnostics))!);
await OnHostInitializedAsync();
@@ -231,10 +230,10 @@ private void OnAsyncStartupCompleted(StartupEventArgs e)
});
var moduleLoader = _host.Services.GetRequiredService();
- moduleLoader.StartModule(new StartRequest(moduleId, new List>()
- {
- { new(WebWindowOptions.ParameterName, JsonSerializer.Serialize(webWindowOptions)) }
- }));
+ moduleLoader.StartModule(new StartRequest(moduleId, new List>
+ {
+ new(WebWindowOptions.ParameterName, JsonSerializer.Serialize(webWindowOptions))
+ }));
return;
}
diff --git a/src/shell/dotnet/Shell/MainWindow.xaml b/src/shell/dotnet/Shell/MainWindow.xaml
index a272fe59f..58b5caad3 100644
--- a/src/shell/dotnet/Shell/MainWindow.xaml
+++ b/src/shell/dotnet/Shell/MainWindow.xaml
@@ -15,12 +15,12 @@ See the License for the specific language governing permissions and limitations
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:MorganStanley.ComposeUI.Shell"
mc:Ignorable="d"
- Title="ComposeUI Shell"
- Height="450"
- Width="600"
+ Title="ComposeUI Shell"
+ Height="450"
+ Width="600"
Background="{DynamicResource {x:Static SystemColors.AppWorkspaceBrushKey}}"
WindowStartupLocation="CenterScreen"
- Initialized="RibbonWindow_Initialized">
+ Initialized="RibbonWindow_Initialized">
diff --git a/src/shell/dotnet/Shell/MainWindow.xaml.cs b/src/shell/dotnet/Shell/MainWindow.xaml.cs
index 2755c4a49..ed3b9812f 100644
--- a/src/shell/dotnet/Shell/MainWindow.xaml.cs
+++ b/src/shell/dotnet/Shell/MainWindow.xaml.cs
@@ -15,10 +15,11 @@
using System.IO;
using System.Windows;
using System.Windows.Controls.Ribbon;
-using System.Windows.Media.Imaging;
using CommunityToolkit.Mvvm.ComponentModel;
using MorganStanley.ComposeUI.ModuleLoader;
using MorganStanley.ComposeUI.Shell.ImageSource;
+using MorganStanley.ComposeUI.Shell.Utilities;
+using IconUtilities = MorganStanley.ComposeUI.Shell.Utilities.IconUtilities;
namespace MorganStanley.ComposeUI.Shell;
@@ -106,12 +107,15 @@ public ModuleViewModel(IModuleManifest manifest, ImageSourceProvider imageSource
}
else if (manifest.TryGetDetails(out var nativeManifestDetails))
{
- var icon = System.Drawing.Icon.ExtractAssociatedIcon(Path.GetFullPath(nativeManifestDetails.Path.ToString()));
+ using var icon =
+ System.Drawing.Icon.ExtractAssociatedIcon(Path.GetFullPath(nativeManifestDetails.Path.ToString()));
- ImageSource = System.Windows.Interop.Imaging.CreateBitmapSourceFromHIcon(
- icon.Handle,
- new Int32Rect { Width = icon.Width, Height = icon.Height },
- BitmapSizeOptions.FromEmptyOptions());
+ if (icon != null)
+ {
+ using var bitmap = icon.ToBitmap();
+
+ ImageSource = bitmap.ToImageSource();
+ }
}
}
diff --git a/src/shell/dotnet/Shell/Utilities/DiagnosticInfo.cs b/src/shell/dotnet/Shell/Utilities/DiagnosticInfo.cs
index fd190cd1b..62a467523 100644
--- a/src/shell/dotnet/Shell/Utilities/DiagnosticInfo.cs
+++ b/src/shell/dotnet/Shell/Utilities/DiagnosticInfo.cs
@@ -1,14 +1,23 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
+// /*
+// * Morgan Stanley makes this available to you under the Apache License,
+// * Version 2.0 (the "License"). You may obtain a copy of the License at
+// *
+// * http://www.apache.org/licenses/LICENSE-2.0.
+// *
+// * See the NOTICE file distributed with this work for additional information
+// * regarding copyright ownership. Unless required by applicable law or agreed
+// * to in writing, software distributed under the License is distributed on an
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+// * or implied. See the License for the specific language governing permissions
+// * and limitations under the License.
+// */
-namespace MorganStanley.ComposeUI.Shell.Utilities
+using System;
+
+namespace MorganStanley.ComposeUI.Shell.Utilities;
+
+internal class DiagnosticInfo
{
- internal class DiagnosticInfo
- {
- public DateTime StartupTime { get; set; }
- public string ShellVersion { get; set; }
- }
-}
+ public DateTime StartupTime { get; set; }
+ public string ShellVersion { get; set; }
+}
\ No newline at end of file
diff --git a/src/shell/dotnet/Shell/Utilities/IconUtilities.cs b/src/shell/dotnet/Shell/Utilities/IconUtilities.cs
new file mode 100644
index 000000000..3557d0918
--- /dev/null
+++ b/src/shell/dotnet/Shell/Utilities/IconUtilities.cs
@@ -0,0 +1,49 @@
+// /*
+// * Morgan Stanley makes this available to you under the Apache License,
+// * Version 2.0 (the "License"). You may obtain a copy of the License at
+// *
+// * http://www.apache.org/licenses/LICENSE-2.0.
+// *
+// * See the NOTICE file distributed with this work for additional information
+// * regarding copyright ownership. Unless required by applicable law or agreed
+// * to in writing, software distributed under the License is distributed on an
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+// * or implied. See the License for the specific language governing permissions
+// * and limitations under the License.
+// */
+
+using System.Drawing;
+using System.Drawing.Imaging;
+using System.IO;
+using System.Windows.Media.Imaging;
+using MorganStanley.ComposeUI.Utilities;
+
+namespace MorganStanley.ComposeUI.Shell.Utilities;
+public static class IconUtilities
+{
+ public static System.Windows.Media.ImageSource ToImageSource(this Bitmap bitmap)
+ {
+ try
+ {
+ using var memoryStream = new MemoryStream();
+
+ bitmap.Save(memoryStream, ImageFormat.Png);
+ memoryStream.Position = 0;
+
+ var bitmapImage = new BitmapImage();
+
+ bitmapImage.BeginInit();
+ bitmapImage.StreamSource = memoryStream;
+ bitmapImage.CacheOption = BitmapCacheOption.OnLoad;
+ bitmapImage.EndInit();
+ bitmapImage.Freeze();
+
+ return bitmapImage;
+ }
+ finally
+ {
+ NativeMethods.DeleteObject(bitmap.GetHbitmap());
+ }
+ }
+}
+
diff --git a/src/shell/dotnet/tests/Shell.Tests/Shell.Tests.csproj b/src/shell/dotnet/tests/Shell.Tests/Shell.Tests.csproj
index 7f94cb03a..00a38f434 100644
--- a/src/shell/dotnet/tests/Shell.Tests/Shell.Tests.csproj
+++ b/src/shell/dotnet/tests/Shell.Tests/Shell.Tests.csproj
@@ -10,6 +10,7 @@
+
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/shell/dotnet/tests/Shell.Tests/Utilities/IconUtilities.Tests.cs b/src/shell/dotnet/tests/Shell.Tests/Utilities/IconUtilities.Tests.cs
new file mode 100644
index 000000000..2b3d040fe
--- /dev/null
+++ b/src/shell/dotnet/tests/Shell.Tests/Utilities/IconUtilities.Tests.cs
@@ -0,0 +1,45 @@
+// /*
+// * Morgan Stanley makes this available to you under the Apache License,
+// * Version 2.0 (the "License"). You may obtain a copy of the License at
+// *
+// * http://www.apache.org/licenses/LICENSE-2.0.
+// *
+// * See the NOTICE file distributed with this work for additional information
+// * regarding copyright ownership. Unless required by applicable law or agreed
+// * to in writing, software distributed under the License is distributed on an
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express
+// * or implied. See the License for the specific language governing permissions
+// * and limitations under the License.
+// */
+
+using System.Drawing;
+using FluentAssertions;
+
+namespace MorganStanley.ComposeUI.Shell.Utilities;
+
+public class IconUtilitiesTests
+{
+ [Fact]
+ public void Bitmap_handle_is_no_longer_held_after_it_has_been_disposed()
+ {
+ var icon = new Icon(SystemIcons.Exclamation, 40, 40);
+ var bitmap = icon.ToBitmap();
+
+ var result = bitmap.ToImageSource();
+
+ result.Should().NotBeNull();
+
+ bitmap.Dispose();
+ icon.Dispose();
+
+ var action1 = () => bitmap.GetHbitmap();
+ var action2 = () => bitmap.GetHicon();
+ var action3 = () => icon.Handle;
+ var action4 = () => result;
+
+ action1.Should().Throw();
+ action2.Should().Throw();
+ action3.Should().Throw();
+ action4.Should().NotThrow();
+ }
+}