1
0
mirror of https://github.com/chylex/TweetDuck.git synced 2025-09-15 22:32:08 +02:00

Compare commits

...

8 Commits

20 changed files with 74 additions and 36 deletions

View File

@@ -6,6 +6,6 @@ using TweetDuck;
namespace TweetDuck { namespace TweetDuck {
internal static class Version { internal static class Version {
public const string Tag = "1.24"; public const string Tag = "1.25.1";
} }
} }

BIN
bld/Redist/concrt140.dll Normal file

Binary file not shown.

BIN
bld/Redist/msvcp140.dll Normal file

Binary file not shown.

BIN
bld/Redist/msvcp140_1.dll Normal file

Binary file not shown.

BIN
bld/Redist/msvcp140_2.dll Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
bld/Redist/vccorlib140.dll Normal file

Binary file not shown.

BIN
bld/Redist/vcruntime140.dll Normal file

Binary file not shown.

View File

@@ -1,18 +1,21 @@
; Script generated by the Inno Script Studio Wizard. ; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppID "8C25A716-7E11-4AAD-9992-8B5D0C78AE06"
#define MyAppName "TweetDuck" #define MyAppName "TweetDuck"
#define MyAppPublisher "chylex" #define MyAppPublisher "chylex"
#define MyAppURL "https://tweetduck.chylex.com" #define MyAppURL "https://tweetduck.chylex.com"
#define MyAppShortURL "https://td.chylex.com" #define MyAppShortURL "https://td.chylex.com"
#define MyAppExeName "TweetDuck.exe" #define MyAppExeName "TweetDuck.exe"
#define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\x86\Release\TweetDuck.exe") #define MyAppArchitecture "x86"
#define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\" + MyAppArchitecture + "\Release\TweetDuck.exe")
#include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss" #include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss"
[Setup] [Setup]
AppId={{8C25A716-7E11-4AAD-9992-8B5D0C78AE06} AppId={{{#MyAppID}}
AppName={#MyAppName} AppName={#MyAppName}
AppVersion={#MyAppVersion} AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion} AppVerName={#MyAppName} {#MyAppVersion}
@@ -43,8 +46,8 @@ Name: "english"; MessagesFile: "compiler:Default.isl"
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalTasks}"; Flags: unchecked Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalTasks}"; Flags: unchecked
[Files] [Files]
Source: "..\windows\TweetDuck\bin\x86\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons] [Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Check: TDIsUninstallable Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Check: TDIsUninstallable

View File

@@ -1,18 +1,21 @@
; Script generated by the Inno Script Studio Wizard. ; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppID "8C25A716-7E11-4AAD-9992-8B5D0C78AE06"
#define MyAppName "TweetDuck" #define MyAppName "TweetDuck"
#define MyAppPublisher "chylex" #define MyAppPublisher "chylex"
#define MyAppURL "https://tweetduck.chylex.com" #define MyAppURL "https://tweetduck.chylex.com"
#define MyAppShortURL "https://td.chylex.com" #define MyAppShortURL "https://td.chylex.com"
#define MyAppExeName "TweetDuck.exe" #define MyAppExeName "TweetDuck.exe"
#define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\x86\Release\TweetDuck.exe") #define MyAppArchitecture "x86"
#define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\" + MyAppArchitecture + "\Release\TweetDuck.exe")
#include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss" #include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss"
[Setup] [Setup]
AppId={{8C25A716-7E11-4AAD-9992-8B5D0C78AE06} AppId={{{#MyAppID}}
AppName={#MyAppName} Portable AppName={#MyAppName} Portable
AppVersion={#MyAppVersion} AppVersion={#MyAppVersion}
AppVerName={#MyAppName} {#MyAppVersion} AppVerName={#MyAppName} {#MyAppVersion}
@@ -40,8 +43,8 @@ MinVersion=0,6.1
Name: "english"; MessagesFile: "compiler:Default.isl" Name: "english"; MessagesFile: "compiler:Default.isl"
[Files] [Files]
Source: "..\windows\TweetDuck\bin\x86\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs
[Run] [Run]
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall shellexec skipifsilent Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall shellexec skipifsilent

View File

@@ -1,15 +1,17 @@
; Script generated by the Inno Script Studio Wizard. ; Script generated by the Inno Script Studio Wizard.
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES! ; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
#define MyAppID "8C25A716-7E11-4AAD-9992-8B5D0C78AE06"
#define MyAppName "TweetDuck" #define MyAppName "TweetDuck"
#define MyAppPublisher "chylex" #define MyAppPublisher "chylex"
#define MyAppURL "https://tweetduck.chylex.com" #define MyAppURL "https://tweetduck.chylex.com"
#define MyAppShortURL "https://td.chylex.com" #define MyAppShortURL "https://td.chylex.com"
#define MyAppExeName "TweetDuck.exe" #define MyAppExeName "TweetDuck.exe"
#define MyAppID "8C25A716-7E11-4AAD-9992-8B5D0C78AE06" #define MyAppArchitecture "x86"
#define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\x86\Release\TweetDuck.exe") #define MyAppVersion GetFileVersion("..\windows\TweetDuck\bin\" + MyAppArchitecture + "\Release\TweetDuck.exe")
#define CefVersion GetFileVersion("..\windows\TweetDuck\bin\x86\Release\libcef.dll") #define CefVersion GetFileVersion("..\windows\TweetDuck\bin\" + MyAppArchitecture + "\Release\libcef.dll")
#include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss" #include ReadReg(HKLM, "Software\Mitrich Software\Inno Download Plugin", "InstallDir") + "\idp.iss"
@@ -43,13 +45,13 @@ MinVersion=0,6.1
Name: "english"; MessagesFile: "compiler:Default.isl" Name: "english"; MessagesFile: "compiler:Default.isl"
[Files] [Files]
Source: "..\windows\TweetDuck\bin\x86\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\{#MyAppExeName}"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\TweetDuck.*"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\TweetDuck.*"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\TweetImpl.*"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\TweetImpl.*"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\TweetLib.*"; DestDir: "{app}"; Flags: ignoreversion Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\TweetLib.*"; DestDir: "{app}"; Flags: ignoreversion
Source: "..\windows\TweetDuck\bin\x86\Release\guide\*.*"; DestDir: "{app}\guide"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\guide\*.*"; DestDir: "{app}\guide"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\windows\TweetDuck\bin\x86\Release\resources\*.*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\resources\*.*"; DestDir: "{app}\resources"; Flags: ignoreversion recursesubdirs createallsubdirs
Source: "..\windows\TweetDuck\bin\x86\Release\plugins\*.*"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs createallsubdirs Source: "..\windows\TweetDuck\bin\{#MyAppArchitecture}\Release\plugins\*.*"; DestDir: "{app}\plugins"; Flags: ignoreversion recursesubdirs createallsubdirs
[Icons] [Icons]
Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Check: TDIsUninstallable Name: "{group}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Check: TDIsUninstallable
@@ -69,16 +71,21 @@ Type: filesandordirs; Name: "{localappdata}\{#MyAppName}\GPUCache"
Type: files; Name: "{app}\CEFSHARP-LICENSE.txt" Type: files; Name: "{app}\CEFSHARP-LICENSE.txt"
Type: files; Name: "{app}\LICENSE.txt" Type: files; Name: "{app}\LICENSE.txt"
Type: files; Name: "{app}\README.txt" Type: files; Name: "{app}\README.txt"
Type: files; Name: "{app}\natives_blob.bin"
Type: files; Name: "{app}\cef.pak" Type: files; Name: "{app}\cef.pak"
Type: files; Name: "{app}\cef_100_percent.pak" Type: files; Name: "{app}\cef_100_percent.pak"
Type: files; Name: "{app}\cef_200_percent.pak" Type: files; Name: "{app}\cef_200_percent.pak"
Type: files; Name: "{app}\cef_extensions.pak" Type: files; Name: "{app}\cef_extensions.pak"
Type: files; Name: "{app}\devtools_resources.pak" Type: files; Name: "{app}\devtools_resources.pak"
Type: files; Name: "{app}\natives_blob.bin"
Type: files; Name: "{app}\api-ms-win-*.dll"
Type: files; Name: "{app}\dbgshim.dll"
Type: files; Name: "{app}\mscordaccore_x86_x86_6.*.dll"
Type: files; Name: "{app}\ucrtbase.dll"
Type: filesandordirs; Name: "{app}\guide" Type: filesandordirs; Name: "{app}\guide"
Type: filesandordirs; Name: "{app}\plugins\official" Type: filesandordirs; Name: "{app}\plugins\official"
Type: filesandordirs; Name: "{app}\resources" Type: filesandordirs; Name: "{app}\resources"
Type: filesandordirs; Name: "{app}\scripts" Type: filesandordirs; Name: "{app}\scripts"
Type: filesandordirs; Name: "{app}\swiftshader"
[Code] [Code]
function TDIsUninstallable: Boolean; forward; function TDIsUninstallable: Boolean; forward;

View File

@@ -11,7 +11,6 @@
<PropertyGroup> <PropertyGroup>
<OutputType>WinExe</OutputType> <OutputType>WinExe</OutputType>
<UseWindowsForms>true</UseWindowsForms>
<RootNamespace>TweetDuck.Browser</RootNamespace> <RootNamespace>TweetDuck.Browser</RootNamespace>
<AssemblyName>TweetDuck.Browser</AssemblyName> <AssemblyName>TweetDuck.Browser</AssemblyName>
<ApplicationIcon>..\TweetDuck\Resources\Images\icon.ico</ApplicationIcon> <ApplicationIcon>..\TweetDuck\Resources\Images\icon.ico</ApplicationIcon>
@@ -33,14 +32,14 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="CefSharp.WinForms.NETCore" Version="107.1.90" /> <PackageReference Include="CefSharp.Common.NETCore" Version="107.1.90" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\..\Version.cs" Link="Version.cs" /> <Compile Include="..\..\Version.cs" Link="Version.cs" />
</ItemGroup> </ItemGroup>
<Target Name="CopyResources" AfterTargets="Build"> <Target Name="MakeBrowserProcessLargeAddressAware" AfterTargets="Build">
<Exec Command="call &quot;$(DevEnvDir)\..\..\VC\Auxiliary\Build\vcvars32.bat&quot; &amp; editbin /largeaddressaware /TSAWARE &quot;$(TargetDir)TweetDuck.Browser.exe&quot;" ContinueOnError="false" /> <Exec Command="call &quot;$(DevEnvDir)\..\..\VC\Auxiliary\Build\vcvars32.bat&quot; &amp; editbin /largeaddressaware /TSAWARE &quot;$(TargetDir)TweetDuck.Browser.exe&quot;" ContinueOnError="false" />
</Target> </Target>

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Drawing; using System.Drawing;
using System.Windows.Forms; using System.Windows.Forms;
using TweetDuck.Controls;
using TweetDuck.Management; using TweetDuck.Management;
using TweetDuck.Utils; using TweetDuck.Utils;
using TweetLib.Browser.Interfaces; using TweetLib.Browser.Interfaces;
@@ -53,12 +54,12 @@ namespace TweetDuck.Browser.Notification {
} }
} }
private void WindowsSessionManager_LockStateChanged(object? sender, EventArgs e) { private void WindowsSessionManager_LockStateChanged(object? sender, bool isLocked) {
if (WindowsSessionManager.IsLocked) { if (isLocked) {
PauseNotification(NotificationPauseReason.WindowsSessionLocked); this.InvokeAsyncSafe(() => PauseNotification(NotificationPauseReason.WindowsSessionLocked));
} }
else { else {
ResumeNotification(NotificationPauseReason.WindowsSessionLocked); this.InvokeAsyncSafe(() => ResumeNotification(NotificationPauseReason.WindowsSessionLocked));
} }
} }

View File

@@ -4,8 +4,7 @@ using Win = System.Windows.Forms;
namespace TweetDuck.Management { namespace TweetDuck.Management {
static class WindowsSessionManager { static class WindowsSessionManager {
public static bool IsLocked { get; private set; } = false; public static event EventHandler<bool>? LockStateChanged;
public static event EventHandler? LockStateChanged;
public static void Register() { public static void Register() {
Win.Application.ApplicationExit += OnApplicationExit; Win.Application.ApplicationExit += OnApplicationExit;
@@ -27,8 +26,7 @@ namespace TweetDuck.Management {
} }
private static void SetLocked(bool newState) { private static void SetLocked(bool newState) {
IsLocked = newState; LockStateChanged?.Invoke(null, newState);
LockStateChanged?.Invoke(null, EventArgs.Empty);
} }
} }
} }

View File

@@ -45,6 +45,7 @@ namespace TweetDuck {
internal static void SetupWinForms() { internal static void SetupWinForms() {
Win.Application.EnableVisualStyles(); Win.Application.EnableVisualStyles();
Win.Application.SetCompatibleTextRenderingDefault(false); Win.Application.SetCompatibleTextRenderingDefault(false);
Win.LegacyWinForms.EnsureValid();
} }
[STAThread] [STAThread]

View File

@@ -78,12 +78,17 @@
<ResourcesPlugins Remove="$(SolutionDir)resources\Plugins\.debug\**\*.*" /> <ResourcesPlugins Remove="$(SolutionDir)resources\Plugins\.debug\**\*.*" />
<ResourcesPlugins Remove="$(SolutionDir)resources\Plugins\emoji-keyboard\emoji-instructions.txt" /> <ResourcesPlugins Remove="$(SolutionDir)resources\Plugins\emoji-keyboard\emoji-instructions.txt" />
<ResourcesPluginsDebug Include="$(SolutionDir)resources\Plugins\.debug\**\*.*" Visible="false" /> <ResourcesPluginsDebug Include="$(SolutionDir)resources\Plugins\.debug\**\*.*" Visible="false" />
<Redist Include="$(SolutionDir)bld\Redist\*.*" Visible="false" />
</ItemGroup> </ItemGroup>
<PropertyGroup> <PropertyGroup>
<PreBuildEvent>powershell -NoProfile -Command "$ErrorActionPreference = 'SilentlyContinue'; (Get-Process TweetDuck.Browser | Where-Object {$_.Path -eq '$(TargetDir)TweetDuck.Browser.exe'}).Kill(); Exit 0"</PreBuildEvent> <PreBuildEvent>powershell -NoProfile -Command "$ErrorActionPreference = 'SilentlyContinue'; (Get-Process TweetDuck.Browser | Where-Object {$_.Path -eq '$(TargetDir)TweetDuck.Browser.exe'}).Kill(); Exit 0"</PreBuildEvent>
</PropertyGroup> </PropertyGroup>
<Target Name="MakeBrowserProcessLargeAddressAware" AfterTargets="Build">
<Exec Command="call &quot;$(DevEnvDir)\..\..\VC\Auxiliary\Build\vcvars32.bat&quot; &amp; editbin /largeaddressaware /TSAWARE &quot;$(TargetDir)TweetDuck.Browser.exe&quot;" ContinueOnError="false" />
</Target>
<Target Name="CopyResources" AfterTargets="Build"> <Target Name="CopyResources" AfterTargets="Build">
<ItemGroup> <ItemGroup>
<LocalesToDelete Include="$(TargetDir)locales\*.pak" Exclude="$(TargetDir)locales\en-US.pak" Visible="false" /> <LocalesToDelete Include="$(TargetDir)locales\*.pak" Exclude="$(TargetDir)locales\en-US.pak" Visible="false" />
@@ -120,6 +125,7 @@
<Copy SourceFiles="@(ResourcesContent)" DestinationFiles="@(ResourcesContent->'$(TargetDir)\resources\%(RecursiveDir)%(Filename)%(Extension)')" /> <Copy SourceFiles="@(ResourcesContent)" DestinationFiles="@(ResourcesContent->'$(TargetDir)\resources\%(RecursiveDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="@(ResourcesGuide)" DestinationFiles="@(ResourcesGuide->'$(TargetDir)\guide\%(RecursiveDir)%(Filename)%(Extension)')" /> <Copy SourceFiles="@(ResourcesGuide)" DestinationFiles="@(ResourcesGuide->'$(TargetDir)\guide\%(RecursiveDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="@(ResourcesPlugins)" DestinationFiles="@(ResourcesPlugins->'$(TargetDir)\plugins\official\%(RecursiveDir)%(Filename)%(Extension)')" /> <Copy SourceFiles="@(ResourcesPlugins)" DestinationFiles="@(ResourcesPlugins->'$(TargetDir)\plugins\official\%(RecursiveDir)%(Filename)%(Extension)')" />
<Copy SourceFiles="@(Redist)" DestinationFolder="$(TargetDir)" />
<Exec Command="powershell -NoProfile -ExecutionPolicy Unrestricted -File &quot;$(ProjectDir)Resources\PostBuild.ps1&quot; &quot;$(TargetDir)\&quot;" IgnoreExitCode="false" /> <Exec Command="powershell -NoProfile -ExecutionPolicy Unrestricted -File &quot;$(ProjectDir)Resources\PostBuild.ps1&quot; &quot;$(TargetDir)\&quot;" IgnoreExitCode="false" />
</Target> </Target>

View File

@@ -4,10 +4,16 @@ using System.Reflection;
namespace System.Windows.Forms { namespace System.Windows.Forms {
internal sealed class Command2 { internal sealed class Command2 {
private static readonly Type Type = typeof(Form).Assembly.GetType("System.Windows.Forms.Command"); private static readonly Type Type = typeof(Form).Assembly.GetType("System.Windows.Forms.Command");
private static readonly ConstructorInfo Constructor = Type.GetConstructor(new Type[] { typeof(ICommandExecutor) }) ?? throw new NullReferenceException(); private static readonly ConstructorInfo Constructor = Type.GetConstructor(new Type[] { typeof(ICommandExecutor) });
private static readonly MethodInfo DisposeMethod = Type.GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public) ?? throw new NullReferenceException(); private static readonly MethodInfo DisposeMethod = Type.GetMethod("Dispose", BindingFlags.Instance | BindingFlags.Public);
private static readonly PropertyInfo IDProperty = Type.GetProperty("ID") ?? throw new NullReferenceException(); private static readonly PropertyInfo IDProperty = Type.GetProperty("ID");
internal static void EnsureValid() {
if (Constructor == null || DisposeMethod == null || IDProperty == null) {
throw new InvalidOperationException();
}
}
public int ID { get; } public int ID { get; }
private readonly object cmd; private readonly object cmd;

View File

@@ -7,8 +7,14 @@ using System.Runtime.InteropServices;
namespace System.Windows.Forms { namespace System.Windows.Forms {
public sealed class ContextMenu : Menu { public sealed class ContextMenu : Menu {
private static readonly FieldInfo NotifyIconWindowField = typeof(NotifyIcon).GetField("window", BindingFlags.Instance | BindingFlags.NonPublic) ?? throw new InvalidOperationException(); private static readonly FieldInfo NotifyIconWindowField = typeof(NotifyIcon).GetField("_window", BindingFlags.Instance | BindingFlags.NonPublic);
internal static void EnsureValid() {
if (NotifyIconWindowField == null) {
throw new InvalidOperationException();
}
}
public event EventHandler Popup; public event EventHandler Popup;
public void Show(Control control, Point pos) { public void Show(Control control, Point pos) {

View File

@@ -0,0 +1,8 @@
namespace System.Windows.Forms;
public static class LegacyWinForms {
public static void EnsureValid() {
Command2.EnsureValid();
ContextMenu.EnsureValid();
}
}