diff --git a/AuthenticationExample/AuthenticationExample.csproj b/AuthenticationExample/AuthenticationExample.csproj index 7249295..9afb063 100644 --- a/AuthenticationExample/AuthenticationExample.csproj +++ b/AuthenticationExample/AuthenticationExample.csproj @@ -57,8 +57,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/AuthenticationExample/Properties/AssemblyInfo.cs b/AuthenticationExample/Properties/AssemblyInfo.cs index d282ffd..1403438 100644 --- a/AuthenticationExample/Properties/AssemblyInfo.cs +++ b/AuthenticationExample/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("6.3.0.0")] -[assembly: AssemblyFileVersion("6.3.0.0")] +[assembly: AssemblyVersion("6.4.1.0")] +[assembly: AssemblyFileVersion("6.4.1.0")] diff --git a/AuthenticationExample/packages.config b/AuthenticationExample/packages.config index 3f6a6a6..8f52fbc 100644 --- a/AuthenticationExample/packages.config +++ b/AuthenticationExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/FDC3WPFExample/FDC3WPFExample.csproj b/FDC3WPFExample/FDC3WPFExample.csproj index a73a006..b0f79e3 100644 --- a/FDC3WPFExample/FDC3WPFExample.csproj +++ b/FDC3WPFExample/FDC3WPFExample.csproj @@ -57,8 +57,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/FDC3WPFExample/MainWindow.xaml b/FDC3WPFExample/MainWindow.xaml index 23282f1..42deb2b 100644 --- a/FDC3WPFExample/MainWindow.xaml +++ b/FDC3WPFExample/MainWindow.xaml @@ -9,8 +9,8 @@ xmlns:Custom="http://schemas.microsoft.com/winfx/2006/xaml/presentation/ribbon" xmlns:Finsemble1="clr-namespace:ChartIQ.Finsemble.HeaderControl;assembly=Finsemble" x:Class="FDC3WPFExample.MainWindow" mc:Ignorable="d" Title="MainWindow" Height="600" - Width="600" WindowStyle="None" Background="{x:Null}" - AllowsTransparency="True"> + Width="600" WindowStyle="None" + Background="{x:Null}"> - + diff --git a/FinsembleDemo.sln b/FinsembleDemo.sln index 0729164..ffe584b 100644 --- a/FinsembleDemo.sln +++ b/FinsembleDemo.sln @@ -27,6 +27,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "FreestandingWPFExample", "F EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinformExampleCore", "WinformExampleCore\WinformExampleCore.csproj", "{0E0D48C5-CDDD-4A27-9FC3-982092B8096D}" EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WinformMultiWindowExampleCore", "WinformMultiWindowExampleCore\WinformMultiWindowExampleCore.csproj", "{B60B83D3-0D6F-447E-BBE2-29733EFDDC42}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -181,6 +183,18 @@ Global {0E0D48C5-CDDD-4A27-9FC3-982092B8096D}.Release|x64.Build.0 = Release|x64 {0E0D48C5-CDDD-4A27-9FC3-982092B8096D}.Release|x86.ActiveCfg = Release|Any CPU {0E0D48C5-CDDD-4A27-9FC3-982092B8096D}.Release|x86.Build.0 = Release|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|x64.ActiveCfg = Debug|x64 + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|x64.Build.0 = Debug|x64 + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|x86.ActiveCfg = Debug|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Debug|x86.Build.0 = Debug|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|Any CPU.Build.0 = Release|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|x64.ActiveCfg = Release|x64 + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|x64.Build.0 = Release|x64 + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|x86.ActiveCfg = Release|Any CPU + {B60B83D3-0D6F-447E-BBE2-29733EFDDC42}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/FreestandingWPFExample/FreestandingWPFExample.csproj b/FreestandingWPFExample/FreestandingWPFExample.csproj index b101cc3..cabf3c8 100644 --- a/FreestandingWPFExample/FreestandingWPFExample.csproj +++ b/FreestandingWPFExample/FreestandingWPFExample.csproj @@ -5,9 +5,9 @@ net5.0-windows true AnyCPU;x64 - 6.3.0.0 - 6.3.0.0 - 6.3.0 + 6.4.1.0 + 6.4.1.0 + 6.4.1 diff --git a/MultiWindowExample/MultiWindowExample.csproj b/MultiWindowExample/MultiWindowExample.csproj index 7ead4f1..53f4780 100644 --- a/MultiWindowExample/MultiWindowExample.csproj +++ b/MultiWindowExample/MultiWindowExample.csproj @@ -57,8 +57,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/MultiWindowExample/Properties/AssemblyInfo.cs b/MultiWindowExample/Properties/AssemblyInfo.cs index 837e93f..fdf3d35 100644 --- a/MultiWindowExample/Properties/AssemblyInfo.cs +++ b/MultiWindowExample/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("6.3.0.0")] -[assembly: AssemblyFileVersion("6.3.0.0")] +[assembly: AssemblyVersion("6.4.1.0")] +[assembly: AssemblyFileVersion("6.4.1.0")] diff --git a/MultiWindowExample/packages.config b/MultiWindowExample/packages.config index 3f6a6a6..8f52fbc 100644 --- a/MultiWindowExample/packages.config +++ b/MultiWindowExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/WPFExample/MainWindow.xaml b/WPFExample/MainWindow.xaml index fa6ac55..265b93d 100644 --- a/WPFExample/MainWindow.xaml +++ b/WPFExample/MainWindow.xaml @@ -14,8 +14,7 @@ Height="600" Width="600" WindowStyle="None" - Background="{x:Null}" - AllowsTransparency="True"> + Background="{x:Null}"> ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/WPFExample/packages.config b/WPFExample/packages.config index 3f6a6a6..8f52fbc 100644 --- a/WPFExample/packages.config +++ b/WPFExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/WPFExampleCore/WPFExampleCore.csproj b/WPFExampleCore/WPFExampleCore.csproj index edde400..77aa2f3 100644 --- a/WPFExampleCore/WPFExampleCore.csproj +++ b/WPFExampleCore/WPFExampleCore.csproj @@ -5,7 +5,7 @@ net5.0-windows true AnyCPU;x64 - 6.3.0 + 6.4.1 @@ -13,10 +13,7 @@ - - - - + diff --git a/WPFMultiWindowExampleCore/WPFMultiWindowExampleCore.csproj b/WPFMultiWindowExampleCore/WPFMultiWindowExampleCore.csproj index 703c350..e3d4b15 100644 --- a/WPFMultiWindowExampleCore/WPFMultiWindowExampleCore.csproj +++ b/WPFMultiWindowExampleCore/WPFMultiWindowExampleCore.csproj @@ -6,14 +6,11 @@ true WPFMultiWindowExampleCore.AppStartup AnyCPU;x64 - 6.3.0 + 6.4.1 - - - - + diff --git a/WindowlessExample.Core/WindowlessExample.Core.csproj b/WindowlessExample.Core/WindowlessExample.Core.csproj index dd895bd..b00e7a2 100644 --- a/WindowlessExample.Core/WindowlessExample.Core.csproj +++ b/WindowlessExample.Core/WindowlessExample.Core.csproj @@ -4,13 +4,11 @@ WinExe net5.0 AnyCPU;x64 - 6.3.0 + 6.4.1 - - - + diff --git a/WindowlessExample/Properties/AssemblyInfo.cs b/WindowlessExample/Properties/AssemblyInfo.cs index 5b98429..1f5cd44 100644 --- a/WindowlessExample/Properties/AssemblyInfo.cs +++ b/WindowlessExample/Properties/AssemblyInfo.cs @@ -51,5 +51,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("6.3.0.0")] -[assembly: AssemblyFileVersion("6.3.0.0")] +[assembly: AssemblyVersion("6.4.1.0")] +[assembly: AssemblyFileVersion("6.4.1.0")] diff --git a/WindowlessExample/WindowlessExample.csproj b/WindowlessExample/WindowlessExample.csproj index 728e965..5aa1cf5 100644 --- a/WindowlessExample/WindowlessExample.csproj +++ b/WindowlessExample/WindowlessExample.csproj @@ -57,8 +57,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll diff --git a/WindowlessExample/packages.config b/WindowlessExample/packages.config index 3f6a6a6..8f52fbc 100644 --- a/WindowlessExample/packages.config +++ b/WindowlessExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/WinformExample/Properties/AssemblyInfo.cs b/WinformExample/Properties/AssemblyInfo.cs index ae14b69..2b17056 100644 --- a/WinformExample/Properties/AssemblyInfo.cs +++ b/WinformExample/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("6.3.0.0")] -[assembly: AssemblyFileVersion("6.3.0.0")] +[assembly: AssemblyVersion("6.4.1.0")] +[assembly: AssemblyFileVersion("6.4.1.0")] diff --git a/WinformExample/WinformExample.csproj b/WinformExample/WinformExample.csproj index 3900d49..734d42f 100644 --- a/WinformExample/WinformExample.csproj +++ b/WinformExample/WinformExample.csproj @@ -56,8 +56,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/WinformExample/packages.config b/WinformExample/packages.config index 97b6566..69b1480 100644 --- a/WinformExample/packages.config +++ b/WinformExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/WinformExampleCore/MainForm.cs b/WinformExampleCore/MainForm.cs index 628ceb7..becd8d7 100644 --- a/WinformExampleCore/MainForm.cs +++ b/WinformExampleCore/MainForm.cs @@ -78,8 +78,9 @@ private async void Finsemble_Connected(object sender, EventArgs e) SetUpLinkerChannels(systemChannels); // Listen to Fdc3Client state change to render connected channels - _bridge.Clients.Fdc3Client.StateChanged += Fdc3Client_StateChanged; ; - + _bridge.Clients.Fdc3Client.StateChanged += Fdc3Client_StateChanged; + // Show joined channels + Fdc3Client_StateChanged(null, _bridge.Clients.Fdc3Client.LastStateChangedArgs); // Example for Fdc3Client subscribe to specific context. The "*" for subscription to all contexts. _contextListenter = _bridge.Clients.Fdc3Client.DesktopAgentClient.AddContextListener("fdc3.instrument", HandleContext); @@ -286,6 +287,7 @@ private void HandleDragAndDropReceive(object sender, FinsembleEventArgs args) private void Fdc3Client_StateChanged(object sender, FinsembleEventArgs response) { + if (response == null) return; this.Invoke(new Action(async () => { if (response.error != null) diff --git a/WinformExampleCore/WinformExampleCore.csproj b/WinformExampleCore/WinformExampleCore.csproj index d013922..7e73059 100644 --- a/WinformExampleCore/WinformExampleCore.csproj +++ b/WinformExampleCore/WinformExampleCore.csproj @@ -5,13 +5,11 @@ net5.0-windows true AnyCPU;x64 - 6.3.0 + 6.4.1 - - - + @@ -36,4 +34,4 @@ - \ No newline at end of file + diff --git a/WinformMultiWindowExample/Properties/AssemblyInfo.cs b/WinformMultiWindowExample/Properties/AssemblyInfo.cs index a58c6a4..308e122 100644 --- a/WinformMultiWindowExample/Properties/AssemblyInfo.cs +++ b/WinformMultiWindowExample/Properties/AssemblyInfo.cs @@ -32,5 +32,5 @@ // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("6.3.0.0")] -[assembly: AssemblyFileVersion("6.3.0.0")] +[assembly: AssemblyVersion("6.4.1.0")] +[assembly: AssemblyFileVersion("6.4.1.0")] diff --git a/WinformMultiWindowExample/WinformMultiWindowExample.csproj b/WinformMultiWindowExample/WinformMultiWindowExample.csproj index 47a3514..2048ac5 100644 --- a/WinformMultiWindowExample/WinformMultiWindowExample.csproj +++ b/WinformMultiWindowExample/WinformMultiWindowExample.csproj @@ -56,8 +56,8 @@ ..\packages\EventHook.1.4.105\lib\net45\EventHook.dll - - ..\packages\Finsemble.6.3.0\lib\net452\Finsemble.dll + + ..\packages\Finsemble.6.4.1\lib\net452\Finsemble.dll ..\packages\Microsoft.IdentityModel.Logging.6.12.1\lib\net45\Microsoft.IdentityModel.Logging.dll diff --git a/WinformMultiWindowExample/packages.config b/WinformMultiWindowExample/packages.config index 3f6a6a6..8f52fbc 100644 --- a/WinformMultiWindowExample/packages.config +++ b/WinformMultiWindowExample/packages.config @@ -3,7 +3,7 @@ - + diff --git a/WinformMultiWindowExampleCore/FinsembleForm.cs b/WinformMultiWindowExampleCore/FinsembleForm.cs new file mode 100644 index 0000000..64ef17f --- /dev/null +++ b/WinformMultiWindowExampleCore/FinsembleForm.cs @@ -0,0 +1,76 @@ +using Finsemble.Winform.Core; +using Microsoft.IdentityModel.Tokens; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Text; +using System.Windows.Forms; + +namespace WinformMultiWindowExampleCore +{ + /// + /// FinsembleForm class encapsulate connection to Finsemble + /// + public class FinsembleForm:Form + { + public FinsembleWinform FSBL { get; private set; } + private bool allowshowdisplay = false; + private JsonWebKey JWK = new JsonWebKey() + { + D = "S7msrBKYM_VhXmAWTLhoRobLTevToYbX3xkbkN-EiaZ6Hg-xfozn5uAQGnBnoP1ldKOgoj5Z3dx6kTgR-3xfonEfdkk6wn0OVNbuFYyGkeeV4ts5JmyVpihFqE3RbkWuQ5D5xpIhXWl1fOWEuFfGCYIib2pmBUyc4Lz4OYmMOIGEC9nJg6ZuoKOh0nDZBjjO6vbYbXCEi0ys-FD7NAWsM8jTNDxLyXmpCNSVJOnGTX9CcxnFGdLVO8fqbooaydSHtFJE9YVqUKWp54hOBFMHdsTY5iT88urrvdBLxtGf6NGUVetpw-nFiOihDRPb9wMuLY9CT4DDzLecxadrLKh0PQ", + DP = "dw8tnJQEpXazaYFcOhCvlU0Y4kGiul1W-_MTCXml8njCEx0Gp4s8jWf_QK7PcdzZRl-t_NTu12i2UGn8lCvOrSc4g66OkwZxPCVuvGXqQQ2DHTgFR2vk-Q53cFrMtjo8FvplkQuf92vS58ulq-iogDp7xxxXTAhmWaPA_d2i3C0", + DQ = "EffO_SIA7qpBsSDHDKN3TdgybckYjN738roGKcU23ZXDDRy8h9X_lYtMSvjBQz7CRdia7F7aXGJLS08LSAfajRH-W8ssYfRge3twkrqxDXspWwIb77eMSINUUzRA1QQD7kSs_-LsU-rujsqZa-dnBxWhareFtVM-957lkzp4lTU", + E = "AQAB", + N = "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w", + P = "6RJ2697p-SS6CIJYdDU8AxgyKHx3kMkHnFzLQakoi1h6UUNxb-r8v1PUU5xZA5ijmvJv9Ag5uIOhT3u3vSOkADqGsqctNGtFf60hbjnkMDQnDNr2b-1_ayCn2pQM6mmisASfcnOJKUag4tLw3weK-t5uN9KYqfDBU7fVjqnq8HM", + Q = "4R0RUlCnmZRzEw9sqjwxMuvNM1BTSubvMvG0VIlBkYbCn9MOdwurBPxrYqnUcbw-q-qzQy6st6a4L-EAZSnfD3FEEFKeINOJK06l0EwjcLeP8B4YQ-bxd9UroXpl9ACiMqHzyvJCNOpw8A22nbjKVnVhW1E17F-LFAJoWBetYA0", + QI = "PODgpJrXxPAp72v_O0fNfAhWjHLeTk9TfLARl9lzPpYIoYR5tgP1Y_A-3feH_xtCfkzcCskfXIerQlY9lVmqs-eGEYjfuuPVYIruN4OsskMY1nz-h_14clyUmUwfCQJDV4qjcAzf80IMu53jYEW1BydRf90snRjk1dYgSq_qtTQ", + }; + + /// + /// The FinsembleForm conatructor. + /// + /// Command line parameters . + public FinsembleForm(string[] args) + { + ConnectToFinsemble(args); + + // Dispose of Finsemble object when window is closed. + this.FormClosed += FinsembleForm_FormClosed; + } + + //Don't show the form until Finsemble has connected + protected override void SetVisibleCore(bool value) + { + base.SetVisibleCore(allowshowdisplay ? value : allowshowdisplay); + } + + private void FinsembleForm_FormClosed(object sender, FormClosedEventArgs e) + { + Debug.WriteLine("disposing Finsemble bridge"); + FSBL.Dispose(); + Debug.WriteLine("dispose completed"); + } + + /// + /// The ConnectToFinsemble. + /// + /// Command line parameters . + private async void ConnectToFinsemble(string[] args) + { + FSBL = new FinsembleWinform(this, this.Handle.ToString("X"), args); + FSBL.Connected += Finsemble_Connected; + await FSBL.Connect("WinformMultiWindowExampleCore", JWK); + } + + private void Finsemble_Connected(object sender, EventArgs e) + { + Debug.WriteLine("FSBL connected"); + //show the form + this.allowshowdisplay = true; + this.Visible = true; + + FSBL.Clients.Logger.Log($"Winform core example connected to Finsemble. {this.Text}"); + } + } +} diff --git a/WinformMultiWindowExampleCore/Form1.Designer.cs b/WinformMultiWindowExampleCore/Form1.Designer.cs new file mode 100644 index 0000000..db27ac9 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form1.Designer.cs @@ -0,0 +1,41 @@ + +namespace WinformMultiWindowExampleCore +{ + partial class Form1 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "Form1"; + } + + #endregion + } +} + diff --git a/WinformMultiWindowExampleCore/Form1.cs b/WinformMultiWindowExampleCore/Form1.cs new file mode 100644 index 0000000..bc9ece8 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form1.cs @@ -0,0 +1,21 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Diagnostics; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace WinformMultiWindowExampleCore +{ + public partial class Form1 : FinsembleForm + { + public Form1(string[] args):base(args) + { + InitializeComponent(); + } + } +} diff --git a/WinformMultiWindowExampleCore/Form1.resx b/WinformMultiWindowExampleCore/Form1.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form1.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form2.Designer.cs b/WinformMultiWindowExampleCore/Form2.Designer.cs new file mode 100644 index 0000000..af4ff4a --- /dev/null +++ b/WinformMultiWindowExampleCore/Form2.Designer.cs @@ -0,0 +1,40 @@ + +namespace WinformMultiWindowExampleCore +{ + partial class Form2 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "Form2"; + } + + #endregion + } +} \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form2.cs b/WinformMultiWindowExampleCore/Form2.cs new file mode 100644 index 0000000..1b8452f --- /dev/null +++ b/WinformMultiWindowExampleCore/Form2.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace WinformMultiWindowExampleCore +{ + public partial class Form2 : FinsembleForm + { + public Form2(string[] args) : base(args) + { + InitializeComponent(); + } + } +} diff --git a/WinformMultiWindowExampleCore/Form2.resx b/WinformMultiWindowExampleCore/Form2.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form2.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form3.Designer.cs b/WinformMultiWindowExampleCore/Form3.Designer.cs new file mode 100644 index 0000000..54aefaa --- /dev/null +++ b/WinformMultiWindowExampleCore/Form3.Designer.cs @@ -0,0 +1,40 @@ + +namespace WinformMultiWindowExampleCore +{ + partial class Form3 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "Form3"; + } + + #endregion + } +} \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form3.cs b/WinformMultiWindowExampleCore/Form3.cs new file mode 100644 index 0000000..abc1d9b --- /dev/null +++ b/WinformMultiWindowExampleCore/Form3.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace WinformMultiWindowExampleCore +{ + public partial class Form3 : FinsembleForm + { + public Form3(string[] args) : base(args) + { + InitializeComponent(); + } + } +} diff --git a/WinformMultiWindowExampleCore/Form3.resx b/WinformMultiWindowExampleCore/Form3.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form3.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form4.Designer.cs b/WinformMultiWindowExampleCore/Form4.Designer.cs new file mode 100644 index 0000000..d46802d --- /dev/null +++ b/WinformMultiWindowExampleCore/Form4.Designer.cs @@ -0,0 +1,40 @@ + +namespace WinformMultiWindowExampleCore +{ + partial class Form4 + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(800, 450); + this.Text = "Form4"; + } + + #endregion + } +} \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Form4.cs b/WinformMultiWindowExampleCore/Form4.cs new file mode 100644 index 0000000..eca5cca --- /dev/null +++ b/WinformMultiWindowExampleCore/Form4.cs @@ -0,0 +1,18 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Text; +using System.Windows.Forms; + +namespace WinformMultiWindowExampleCore +{ + public partial class Form4 : FinsembleForm + { + public Form4(string[] args) : base(args) + { + InitializeComponent(); + } + } +} diff --git a/WinformMultiWindowExampleCore/Form4.resx b/WinformMultiWindowExampleCore/Form4.resx new file mode 100644 index 0000000..1af7de1 --- /dev/null +++ b/WinformMultiWindowExampleCore/Form4.resx @@ -0,0 +1,120 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/WinformMultiWindowExampleCore/Program.cs b/WinformMultiWindowExampleCore/Program.cs new file mode 100644 index 0000000..dccdb6c --- /dev/null +++ b/WinformMultiWindowExampleCore/Program.cs @@ -0,0 +1,168 @@ +using Finsemble.Winform.Core; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using System.IO.Pipes; + +namespace WinformMultiWindowExampleCore +{ + static class Program + { + private static readonly string Unique = "0f03c714-b597-4c17-a351-62f35535599a"; + + /// + /// The main entry point for the application. + /// + [STAThread] + static void Main() + { +#if DEBUG + Debugger.Launch(); +#endif + Application.SetHighDpiMode(HighDpiMode.SystemAware); + Application.EnableVisualStyles(); + Application.SetCompatibleTextRenderingDefault(false); + + Application.ThreadException += Application_ThreadException; + Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException); + + // create a global mutex + using (var mutex = new Mutex(false, "Finsemble")) + { + var mutexAcquired = false; + try + { + // acquire the mutex (or timeout after 60 seconds) + // will return false if it timed out + mutexAcquired = mutex.WaitOne(60000); + } + catch (AbandonedMutexException) + { + // abandoned mutexes are still acquired, we just need + // to handle the exception and treat it as acquisition + mutexAcquired = true; + } + + // if it wasn't acquired, it timed out, so can handle that how ever we want + if (!mutexAcquired) + { + Debug.Print("I have timed out acquiring the mutex and can handle that somehow"); + return; + } + + // otherwise, we've acquired the mutex and should do what we need to do, + // then ensure that we always release the mutex + if (SingleInstance.InitializeAsFirstInstance(Unique)) + { + SingleInstance.MessageReceived += SingleInstance_MessageReceived; + mutex.ReleaseMutex(); + + var form = CreateForm(Environment.GetCommandLineArgs(), out string formName); + if (form != null) + { + Application.Run(form); + } + else + { + MessageBox.Show($"\"{formName}\" unknown name of form!"); + } + + + // Allow single instance code to perform cleanup operations + SingleInstance.Cleanup(); + } + } + } + + /// + /// Occurs when subsequent instances are started. + /// + /// + private static void SingleInstance_MessageReceived(string[] args) + { + if (Application.OpenForms.Count > 0) + { + //create and show new form + Application.OpenForms[0].Invoke(new Action(() => + { + var form = CreateForm(args, out string formName); + form?.Show(); + })); + } + } + + private static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) + { +#if DEBUG + Debug.Print($"An Unhandled Exception has occurred. Exception: {e.Exception}"); +#endif + Application.Exit(); + } + + /// + /// The GetNonFinsembleArgs. + /// + /// The args . + /// The . + private static IEnumerable GetNonFinsembleArgs(IList args) + { + var nonFSBLArgs = args.Where(str => !str.Contains("=") && !str.Contains(".exe") && !str.Contains(".dll")); + return nonFSBLArgs; + } + + /// + /// The CreateForm. + /// + /// The args . + /// The . + private static Form CreateForm(string[] args, out string passedFormName) + { + Form form = null; + passedFormName = string.Empty; + + if (args.Length < 2) + { + // Invalid number of arguments + return form; + } + + var nonFSBLArgs = GetNonFinsembleArgs(args); + passedFormName = nonFSBLArgs.FirstOrDefault(); + + switch (passedFormName) + { + case "Form1": + { + form = new Form1(args); + break; + } + case "Form2": + { + form = new Form2(args); + break; + } + case "Form3": + { + form = new Form3(args); + break; + } + case "Form4": + { + form = new Form4(args); + break; + } + default: + { + // Unknown window, ignore + break; + } + } + + return form; + } + } +} diff --git a/WinformMultiWindowExampleCore/Properties/launchSettings.json b/WinformMultiWindowExampleCore/Properties/launchSettings.json new file mode 100644 index 0000000..35b7e72 --- /dev/null +++ b/WinformMultiWindowExampleCore/Properties/launchSettings.json @@ -0,0 +1,8 @@ +{ + "profiles": { + "WinformMultiWindowExampleCore": { + "commandName": "Project", + "commandLineArgs": "Form1" + } + } +} diff --git a/WinformMultiWindowExampleCore/SingleInstance.cs b/WinformMultiWindowExampleCore/SingleInstance.cs new file mode 100644 index 0000000..33e4a36 --- /dev/null +++ b/WinformMultiWindowExampleCore/SingleInstance.cs @@ -0,0 +1,176 @@ +using System; +using System.Collections.Generic; +using System.IO.Pipes; +using System.Text; +using System.Threading; +using System.Threading.Tasks; +using System.Text.Json.Serialization; +using System.Text.Json; + +namespace WinformMultiWindowExampleCore +{ + public static class SingleInstance + { + /// + /// TokenSource for canceling waiting to pipe + /// + private static CancellationTokenSource stopWaitingPipeConnectionTokenSource; + + /// + /// NamedPipeServerStream for communications. + /// + private static NamedPipeServerStream pipeServer; + + /// + /// Application mutex. + /// + static System.Threading.Mutex singleInstanceMutex; + + internal delegate void MessageReciveHandler(string[] args); + + /// + /// Message receive event from another app instances + /// + internal static event MessageReciveHandler MessageReceived; + + /// + /// Checks if the instance of the application attempting to start is the first instance. + /// If not, activates the first instance. + /// + /// True if this is the first instance of the application. + public static bool InitializeAsFirstInstance(string uniqueName) + { + var commandLineArgs = Environment.GetCommandLineArgs(); + + // Build unique application Id and the channel name. + string applicationIdentifier = uniqueName + Environment.UserName; + string channelName = String.Concat(applicationIdentifier, ":", "SingeInstanceChannel"); + + singleInstanceMutex = new Mutex(true, applicationIdentifier, out var isSingleInstance); + + if (isSingleInstance) + { + CreateRemoteService(channelName); + } + else + { + SignalFirstInstance(channelName, commandLineArgs); + } + + return isSingleInstance; + } + + /// + /// Cleans up single-instance code, clearing shared resources, mutexes, etc. + /// + public static void Cleanup() + { + if (stopWaitingPipeConnectionTokenSource != null) + { + stopWaitingPipeConnectionTokenSource.Cancel(); + } + + if (singleInstanceMutex != null) + { + singleInstanceMutex.Close(); + singleInstanceMutex = null; + } + + if (pipeServer != null) + { + pipeServer.Close(); + pipeServer = null; + } + } + + + /// + /// Creates a remote service for communication. + /// + /// Application's channel name. + private static void CreateRemoteService(string channelName) + { + //Run Pipe listener + Task.Run(async () => + { + pipeServer = new NamedPipeServerStream(channelName, PipeDirection.InOut, 1, PipeTransmissionMode.Message); + stopWaitingPipeConnectionTokenSource = new CancellationTokenSource(); + + await pipeServer.WaitForConnectionAsync(stopWaitingPipeConnectionTokenSource.Token); + + if (stopWaitingPipeConnectionTokenSource.Token.IsCancellationRequested) + return; + + try + { + using (var reader = new System.IO.StreamReader(pipeServer)) + { + var stopRead = false; + while (!stopRead) + { + var message = reader.ReadLine(); + + if (message != null) + { + var args = JsonSerializer.Deserialize(message); + MessageReceived?.Invoke(args); + } + + if (pipeServer.IsMessageComplete) + { + stopRead = true; + } + } + reader.Close(); + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.Print(ex.Message); + } + finally + { + //Create new instance of NamedPipeServerStream for new client + CreateRemoteService(channelName); + } + }); + } + + + /// + /// Creates a client channel and send message to the remoting service exposed by the server - + /// in this case, the remoting service exposed by the first instance. Calls a function of the remoting service + /// class to pass on command line arguments from the second instance to the first and cause it to activate itself. + /// + /// Application's channel name. + /// + /// Command line arguments for the second instance, passed to the first instance to take appropriate action. + /// + private static void SignalFirstInstance(string channelName, string[] args) + { + try + { + using (NamedPipeClientStream namedPipeClient = new NamedPipeClientStream(channelName)) + { + namedPipeClient.Connect(1000); + + if (namedPipeClient.IsConnected) + { + using (var writer = new System.IO.StreamWriter(namedPipeClient)) + { + writer.WriteLine(JsonSerializer.Serialize(args)); + writer.Flush(); + writer.Close(); + } + } + + namedPipeClient.Close(); + } + } + catch (Exception ex) + { + System.Diagnostics.Debug.Print(ex.Message); + } + } + } +} diff --git a/WinformMultiWindowExampleCore/WinformMultiWindowExampleCore.csproj b/WinformMultiWindowExampleCore/WinformMultiWindowExampleCore.csproj new file mode 100644 index 0000000..37356b9 --- /dev/null +++ b/WinformMultiWindowExampleCore/WinformMultiWindowExampleCore.csproj @@ -0,0 +1,15 @@ + + + + WinExe + net5.0-windows + true + AnyCPU;x64 + 6.4.1 + + + + + + + diff --git a/appd.json b/appd.json index b6395b0..c08f338 100644 --- a/appd.json +++ b/appd.json @@ -9,18 +9,14 @@ { "name": "ViewChart", "displayName": "View Chart", - "contexts": [ - "fdc3.instrument" - ] + "contexts": ["fdc3.instrument"] } ], "manifest": { "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -81,9 +77,7 @@ "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -136,32 +130,29 @@ } } }, - "WPFExample": { - "appId": "WPFExample", - "name": "WPFExample", + "Finsemble WPF Demo": { + "appId": "Finsemble WPF Demo", + "name": "Finsemble WPF Demo", "intents": [ { "name": "ViewChart", "displayName": "View Chart", - "contexts": [ - "fdc3.instrument" - ] + "contexts": ["fdc3.instrument"] } ], "manifest": { "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, "window": { - "id": "WPFExample", + "id": "Finsemble WPF Demo", "windowType": "FinsembleNativeWindow", "path": "$wpfExampleRoot/WPFExample.exe", + "arguments": "appName=\"Finsemble WPF Demo\"", "url": "", "minHeight": 300, "minWidth": 300, @@ -215,9 +206,7 @@ "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -278,9 +267,7 @@ "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -339,9 +326,7 @@ "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -373,9 +358,7 @@ "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -406,18 +389,14 @@ { "name": "fdc3.wpfExampleTesting", "displayName": "WPFExampleTesting", - "contexts": [ - "fdc3.wpfExampleTesting" - ] + "contexts": ["fdc3.wpfExampleTesting"] } ], "manifest": { "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -468,18 +447,14 @@ { "name": "fdc3.wpfCoreExampleTesting", "displayName": "WPFCoreExampleTesting", - "contexts": [ - "fdc3.wpfCoreExampleTesting" - ] + "contexts": ["fdc3.wpfCoreExampleTesting"] } ], "manifest": { "signatureKey": { "e": "AQAB", "ext": true, - "key_ops": [ - "verify" - ], + "key_ops": ["verify"], "kty": "RSA", "n": "zPOxYfLiAd3rM7KOLDBIeLl0kjQ7fk43mTTc1Nm9BDaSNVWqvOshSMCHmqOrKZX_WwA67Y6CQxWI5rZ6WNzoLHQU3PyqOvAdB7RgXCHlSeVYZ2haTcbWRjAXQ89H1WfnW96VwAbZn5nccxQGYlZIl3AMcwNRqV4hmiKtJVq4-2OzA-zs9Yg4Pfs6TbKR1XbNKz6EAPHDev0-7Xdnb6x1-qr4uL2Bq0ZwgfnyKQIRLc3zhD5kwqiJ5N7uZAZomLRkMFMXwy1UftD6fQUlFT2yoISn403RwN7YHEL8KoA9X7Jgs-dtlBh8c38QzQ1vbdMBzPuyRb07GMMKb6bdjdBV1w" }, @@ -1228,4 +1203,4 @@ } } } -} \ No newline at end of file +}