diff --git a/.editorconfig b/.editorconfig
index a33a9742..fe3764bd 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -1,205 +1,210 @@
-# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
-
-###############################
-# Core EditorConfig Options # https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
-###############################
-# Remove the line below if you want to inherit .editorconfig settings from higher directories
-root = true
-
-# All files
-[*]
-# Don't use tabs for indentation.
-indent_style = space
-max_line_length = 120
-end_of_line = lf
-charset = utf-8
-trim_trailing_whitespace = true
-insert_final_newline = true
-# (Please don't specify an indent_size here; that has too many unintended consequences.)
-spelling_languages = en-us, uk-ua
-
-# Code files
-[*.cs]
-indent_size = 2
-
-# XML project files
-[*.{csproj,projitems,shproj,wixproj,runsettings}]
-indent_size = 2
-
-# XML config files
-[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct,wxs}]
-indent_size = 2
-
-# XAML files
-[*.xaml]
-indent_size = 2
-
-# JSON files
-[*.json]
-indent_size = 2
-
-# XML files
-[*.xml, *.svg]
-indent_size = 2
-
-# Powershell files
-[*.ps1]
-indent_size = 2
-
-# Shell script files
-[*.sh]
-indent_size = 2
-
-
-###############################
-# Code style rules # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
-###############################
-[*.cs]
-
-# | Language rules
-# |-- Parentheses preferences
-dotnet_diagnostic.IDE0047.severity = none
-dotnet_diagnostic.IDE0048.severity = none
-# |-- Namespace options
-csharp_style_namespace_declarations = file_scoped:silent
-# |-- var preferences
-csharp_style_var_for_built_in_types = true:silent
-csharp_style_var_when_type_is_apparent = true:silent
-csharp_style_var_elsewhere = true:silent
-# |-- Expression-bodied members
-dotnet_diagnostic.IDE0021.severity = none
-dotnet_diagnostic.IDE0022.severity = none
-dotnet_diagnostic.IDE0023.severity = none
-dotnet_diagnostic.IDE0024.severity = none
-
-# | Formatting rules
-# |-- Using directive options
-dotnet_sort_system_directives_first = true
-dotnet_separate_import_directive_groups = false
-# |-- Dotnet namespace options
-dotnet_style_namespace_match_folder = true
-# |-- New-line options
-csharp_new_line_before_open_brace = all
-csharp_new_line_before_else = true
-csharp_new_line_before_catch = true
-csharp_new_line_before_finally = true
-csharp_new_line_before_members_in_object_initializers = true
-csharp_new_line_before_members_in_anonymous_types = true
-csharp_new_line_between_query_expression_clauses = true
-# |-- Indentation options
-csharp_indent_case_contents = true
-csharp_indent_switch_labels = true
-csharp_indent_labels = flush_left
-csharp_indent_block_contents = true
-csharp_indent_braces = false
-csharp_indent_case_contents_when_block = false
-# |-- Spacing options
-csharp_space_after_cast = true
-csharp_space_after_keywords_in_control_flow_statements = true
-#csharp_space_between_parentheses = control_flow_statements, expressions, type_casts
-csharp_space_before_colon_in_inheritance_clause = true
-csharp_space_after_colon_in_inheritance_clause = true
-csharp_space_around_binary_operators = before_and_after
-csharp_space_between_method_declaration_parameter_list_parentheses = false
-csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
-csharp_space_between_method_declaration_name_and_open_parenthesis = false
-csharp_space_between_method_call_parameter_list_parentheses = false
-csharp_space_between_method_call_empty_parameter_list_parentheses = false
-csharp_space_between_method_call_name_and_opening_parenthesis = false
-csharp_space_after_comma = true
-csharp_space_before_comma = false
-csharp_space_after_dot = false
-csharp_space_before_dot = false
-csharp_space_after_semicolon_in_for_statement = true
-csharp_space_before_semicolon_in_for_statement = false
-csharp_space_around_declaration_statements = false
-csharp_space_before_open_square_brackets = false
-csharp_space_between_empty_square_brackets = false
-csharp_space_between_square_brackets = false
-# |--Wrap options
-csharp_preserve_single_line_statements = false
-csharp_preserve_single_line_blocks = true
-
-# | Naming rules
-# |-- Non-private static fields are PascalCase
-dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = warning
-dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
-dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
-dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
-dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
-dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
-dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
-# |-- Non-private readonly fields are PascalCase
-dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning
-dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
-dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style
-dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
-dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
-dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
-dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
-# |-- Constants are PascalCase
-dotnet_naming_rule.constants_should_be_pascal_case.severity = warning
-dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
-dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style
-dotnet_naming_symbols.constants.applicable_kinds = field, local
-dotnet_naming_symbols.constants.required_modifiers = const
-dotnet_naming_style.constant_style.capitalization = pascal_case
-# |-- Static fields are camelCase and start with s_
-dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
-dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
-dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
-dotnet_naming_symbols.static_fields.applicable_kinds = field
-dotnet_naming_symbols.static_fields.required_modifiers = static
-dotnet_naming_style.static_field_style.capitalization = camel_case
-dotnet_naming_style.static_field_style.required_prefix = s_
-# |-- Instance fields are camelCase and start with _
-dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning
-dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
-dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
-dotnet_naming_symbols.instance_fields.applicable_kinds = field
-dotnet_naming_style.instance_field_style.capitalization = camel_case
-dotnet_naming_style.instance_field_style.required_prefix = _
-# |-- Locals and parameters are camelCase
-dotnet_naming_rule.locals_should_be_camel_case.severity = warning
-dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
-dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
-dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
-dotnet_naming_style.camel_case_style.capitalization = camel_case
-# |-- Local functions are PascalCase
-dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning
-dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
-dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style
-dotnet_naming_symbols.local_functions.applicable_kinds = local_function
-dotnet_naming_style.local_function_style.capitalization = pascal_case
-# |-- Interfaces are PascalCase and start with I
-dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
-dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
-dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
-dotnet_naming_symbols.interface.applicable_kinds = interface
-dotnet_naming_style.begins_with_i.required_prefix = I
-dotnet_naming_style.begins_with_i.capitalization = pascal_case
-# |-- By default, name items with PascalCase
-dotnet_naming_rule.members_should_be_pascal_case.severity = warning
-dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
-dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style
-dotnet_naming_symbols.all_members.applicable_kinds = *
-dotnet_naming_style.pascal_case_style.capitalization = pascal_case
-
-
-###############################
-# Warnings Suppressing #
-###############################
-[*.cs]
-
-# CA1010: Collections should implement generic interface
+# To learn more about .editorconfig see https://aka.ms/editorconfigdocs
+
+###############################
+# Core EditorConfig Options # https://docs.microsoft.com/en-us/visualstudio/ide/editorconfig-code-style-settings-reference
+###############################
+# Remove the line below if you want to inherit .editorconfig settings from higher directories
+root = true
+
+# All files
+[*]
+# Don't use tabs for indentation.
+indent_style = space
+max_line_length = 120
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+# (Please don't specify an indent_size here; that has too many unintended consequences.)
+spelling_languages = en-us, uk-ua
+
+# Code files
+[*.cs]
+indent_size = 2
+
+# XML project files
+[*.{csproj,projitems,shproj,wixproj,runsettings}]
+indent_size = 2
+
+# XML config files
+[*.{props,targets,ruleset,config,nuspec,resx,vsixmanifest,vsct,wxs}]
+indent_size = 2
+
+# XAML files
+[*.xaml]
+indent_size = 2
+
+# JSON files
+[*.json]
+indent_size = 2
+
+# XML files
+[*.xml, *.svg]
+indent_size = 2
+
+# Powershell files
+[*.ps1]
+indent_size = 2
+
+# Shell script files
+[*.sh]
+indent_size = 2
+
+
+###############################
+# Code style rules # https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/style-rules/
+###############################
+[*.cs]
+
+# | Language rules
+# |-- Parentheses preferences
+dotnet_diagnostic.IDE0047.severity = none
+dotnet_diagnostic.IDE0048.severity = none
+# |-- Namespace options
+csharp_style_namespace_declarations = file_scoped:silent
+# |-- var preferences
+csharp_style_var_for_built_in_types = true:silent
+csharp_style_var_when_type_is_apparent = true:silent
+csharp_style_var_elsewhere = true:silent
+# |-- Expression-bodied members
+dotnet_diagnostic.IDE0021.severity = none
+dotnet_diagnostic.IDE0022.severity = none
+dotnet_diagnostic.IDE0023.severity = none
+dotnet_diagnostic.IDE0024.severity = none
+
+# | Formatting rules
+# |-- Using directive options
+dotnet_sort_system_directives_first = true
+dotnet_separate_import_directive_groups = false
+# |-- Dotnet namespace options
+dotnet_style_namespace_match_folder = true
+# |-- New-line options
+csharp_new_line_before_open_brace = all
+csharp_new_line_before_else = true
+csharp_new_line_before_catch = true
+csharp_new_line_before_finally = true
+csharp_new_line_before_members_in_object_initializers = true
+csharp_new_line_before_members_in_anonymous_types = true
+csharp_new_line_between_query_expression_clauses = true
+# |-- Indentation options
+csharp_indent_case_contents = true
+csharp_indent_switch_labels = true
+csharp_indent_labels = flush_left
+csharp_indent_block_contents = true
+csharp_indent_braces = false
+csharp_indent_case_contents_when_block = false
+# |-- Spacing options
+csharp_space_after_cast = true
+csharp_space_after_keywords_in_control_flow_statements = true
+#csharp_space_between_parentheses = control_flow_statements, expressions, type_casts
+csharp_space_before_colon_in_inheritance_clause = true
+csharp_space_after_colon_in_inheritance_clause = true
+csharp_space_around_binary_operators = before_and_after
+csharp_space_between_method_declaration_parameter_list_parentheses = false
+csharp_space_between_method_declaration_empty_parameter_list_parentheses = false
+csharp_space_between_method_declaration_name_and_open_parenthesis = false
+csharp_space_between_method_call_parameter_list_parentheses = false
+csharp_space_between_method_call_empty_parameter_list_parentheses = false
+csharp_space_between_method_call_name_and_opening_parenthesis = false
+csharp_space_after_comma = true
+csharp_space_before_comma = false
+csharp_space_after_dot = false
+csharp_space_before_dot = false
+csharp_space_after_semicolon_in_for_statement = true
+csharp_space_before_semicolon_in_for_statement = false
+csharp_space_around_declaration_statements = false
+csharp_space_before_open_square_brackets = false
+csharp_space_between_empty_square_brackets = false
+csharp_space_between_square_brackets = false
+# |--Wrap options
+csharp_preserve_single_line_statements = false
+csharp_preserve_single_line_blocks = true
+
+# | Naming rules
+# |-- Non-private static fields are PascalCase
+dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.severity = warning
+dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.symbols = non_private_static_fields
+dotnet_naming_rule.non_private_static_fields_should_be_pascal_case.style = non_private_static_field_style
+dotnet_naming_symbols.non_private_static_fields.applicable_kinds = field
+dotnet_naming_symbols.non_private_static_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
+dotnet_naming_symbols.non_private_static_fields.required_modifiers = static
+dotnet_naming_style.non_private_static_field_style.capitalization = pascal_case
+# |-- Non-private readonly fields are PascalCase
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.severity = warning
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.symbols = non_private_readonly_fields
+dotnet_naming_rule.non_private_readonly_fields_should_be_pascal_case.style = non_private_static_field_style
+dotnet_naming_symbols.non_private_readonly_fields.applicable_kinds = field
+dotnet_naming_symbols.non_private_readonly_fields.applicable_accessibilities = public, protected, internal, protected_internal, private_protected
+dotnet_naming_symbols.non_private_readonly_fields.required_modifiers = readonly
+dotnet_naming_style.non_private_readonly_field_style.capitalization = pascal_case
+# |-- Constants are PascalCase
+dotnet_naming_rule.constants_should_be_pascal_case.severity = warning
+dotnet_naming_rule.constants_should_be_pascal_case.symbols = constants
+dotnet_naming_rule.constants_should_be_pascal_case.style = non_private_static_field_style
+dotnet_naming_symbols.constants.applicable_kinds = field, local
+dotnet_naming_symbols.constants.required_modifiers = const
+dotnet_naming_style.constant_style.capitalization = pascal_case
+# |-- Static fields are camelCase and start with s_
+dotnet_naming_rule.static_fields_should_be_camel_case.severity = suggestion
+dotnet_naming_rule.static_fields_should_be_camel_case.symbols = static_fields
+dotnet_naming_rule.static_fields_should_be_camel_case.style = static_field_style
+dotnet_naming_symbols.static_fields.applicable_kinds = field
+dotnet_naming_symbols.static_fields.required_modifiers = static
+dotnet_naming_style.static_field_style.capitalization = camel_case
+dotnet_naming_style.static_field_style.required_prefix = s_
+# |-- Instance fields are camelCase and start with _
+dotnet_naming_rule.instance_fields_should_be_camel_case.severity = warning
+dotnet_naming_rule.instance_fields_should_be_camel_case.symbols = instance_fields
+dotnet_naming_rule.instance_fields_should_be_camel_case.style = instance_field_style
+dotnet_naming_symbols.instance_fields.applicable_kinds = field
+dotnet_naming_style.instance_field_style.capitalization = camel_case
+dotnet_naming_style.instance_field_style.required_prefix = _
+# |-- Locals and parameters are camelCase
+dotnet_naming_rule.locals_should_be_camel_case.severity = warning
+dotnet_naming_rule.locals_should_be_camel_case.symbols = locals_and_parameters
+dotnet_naming_rule.locals_should_be_camel_case.style = camel_case_style
+dotnet_naming_symbols.locals_and_parameters.applicable_kinds = parameter, local
+dotnet_naming_style.camel_case_style.capitalization = camel_case
+# |-- Local functions are PascalCase
+dotnet_naming_rule.local_functions_should_be_pascal_case.severity = warning
+dotnet_naming_rule.local_functions_should_be_pascal_case.symbols = local_functions
+dotnet_naming_rule.local_functions_should_be_pascal_case.style = non_private_static_field_style
+dotnet_naming_symbols.local_functions.applicable_kinds = local_function
+dotnet_naming_style.local_function_style.capitalization = pascal_case
+# |-- Interfaces are PascalCase and start with I
+dotnet_naming_rule.interface_should_be_begins_with_i.severity = warning
+dotnet_naming_rule.interface_should_be_begins_with_i.symbols = interface
+dotnet_naming_rule.interface_should_be_begins_with_i.style = begins_with_i
+dotnet_naming_symbols.interface.applicable_kinds = interface
+dotnet_naming_style.begins_with_i.required_prefix = I
+dotnet_naming_style.begins_with_i.capitalization = pascal_case
+# |-- By default, name items with PascalCase
+dotnet_naming_rule.members_should_be_pascal_case.severity = warning
+dotnet_naming_rule.members_should_be_pascal_case.symbols = all_members
+dotnet_naming_rule.members_should_be_pascal_case.style = non_private_static_field_style
+dotnet_naming_symbols.all_members.applicable_kinds = *
+dotnet_naming_style.pascal_case_style.capitalization = pascal_case
+
+
+###############################
+# Warnings Suppressing #
+###############################
+[*.cs]
+
+# CA1010: Collections should implement generic interface
dotnet_diagnostic.CA1010.severity = none
-# CS1591: Missing XML comment for publicly visible type or member
-dotnet_diagnostic.CS1591.severity = none
-
+# CA1062: Validate arguments of public methods
+dotnet_diagnostic.CA1062.severity = none
+
+# CS1591: Missing XML comment for publicly visible type or member
+dotnet_diagnostic.CS1591.severity = none
+
dotnet_diagnostic.S1186.severity = none
+dotnet_diagnostic.S3885.severity = none
dotnet_diagnostic.S4200.severity = none
-
-dotnet_diagnostic.VSTHRD100.severity = none
-
-dotnet_diagnostic.SYSLIB1054.severity = none
+dotnet_diagnostic.S6602.severity = none
+
+dotnet_diagnostic.VSTHRD100.severity = none
+
+dotnet_diagnostic.SYSLIB1054.severity = none
diff --git a/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj b/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj
index 842d651a..c881acd3 100644
--- a/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj
+++ b/Plugins/Tum4ik.JustClipboardManager.PluginsDevKit/Tum4ik.JustClipboardManager.PluginDevKit.csproj
@@ -29,14 +29,14 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
-
+
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj b/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj
index be906843..6148c17e 100644
--- a/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj
+++ b/Tests/Tum4ik.Deployment.UnitTests/Tum4ik.Deployment.UnitTests.csproj
@@ -10,9 +10,9 @@
-
-
-
+
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs b/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs
index 0c4a1a0c..8a553c64 100644
--- a/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs
+++ b/Tests/Tum4ik.JustClipboardManager.UnitTests/Services/ClipboardHookServiceTests.cs
@@ -38,7 +38,7 @@ internal async Task HwndHook_ClipboardUpdateMsg_PublishesClipboardChangedEvent()
var handled = false;
testeeService.HwndHook(WinHandle, 0x031D, default, default, ref handled);
- await Task.Delay(505);
+ await Task.Delay(600);
clipboardChangedEvent.Received(1).Publish();
}
diff --git a/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj b/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj
index 0e677a64..ae7df5fd 100644
--- a/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj
+++ b/Tests/Tum4ik.JustClipboardManager.UnitTests/Tum4ik.JustClipboardManager.UnitTests.csproj
@@ -23,14 +23,14 @@
-
+
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
-
+
+
runtime; build; native; contentfiles; analyzers; buildtransitive
all
diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs
index 22249289..8f54474d 100644
--- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs
+++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IClipboard.cs
@@ -1,9 +1,9 @@
using System.Windows;
-using YT.IIGen.Attributes;
+using Tum4ik.StinimGen.Attributes;
namespace Tum4ik.JustClipboardManager.Ioc.Wrappers;
-[IIFor(typeof(Clipboard), "ClipboardWrapper")]
+[IIFor(typeof(Clipboard), WrapperClassName = "ClipboardWrapper")]
internal partial interface IClipboard
{
}
diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs
index 7debd9eb..1ef79d23 100644
--- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs
+++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IEnvironment.cs
@@ -1,8 +1,8 @@
-using YT.IIGen.Attributes;
+using Tum4ik.StinimGen.Attributes;
namespace Tum4ik.JustClipboardManager.Ioc.Wrappers;
-[IIFor(typeof(Environment), "EnvironmentWrapper")]
+[IIFor(typeof(Environment), WrapperClassName = "EnvironmentWrapper")]
internal partial interface IEnvironment
{
}
diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs
index 002caaee..9cd0dcd1 100644
--- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs
+++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IFile.cs
@@ -1,9 +1,9 @@
-using System.IO;
-using YT.IIGen.Attributes;
+using System.IO;
+using Tum4ik.StinimGen.Attributes;
namespace Tum4ik.JustClipboardManager.Ioc.Wrappers;
-[IIFor(typeof(File), "FileWrapper")]
+[IIFor(typeof(File), WrapperClassName = "FileWrapper")]
internal partial interface IFile
{
}
diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs
index 7f15b705..2b6c9579 100644
--- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs
+++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IPath.cs
@@ -1,9 +1,9 @@
using System.IO;
-using YT.IIGen.Attributes;
+using Tum4ik.StinimGen.Attributes;
namespace Tum4ik.JustClipboardManager.Ioc.Wrappers;
-[IIFor(typeof(Path), "PathWrapper")]
+[IIFor(typeof(Path), WrapperClassName = "PathWrapper")]
internal partial interface IPath
{
}
diff --git a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs
index 96c372ad..a77b85b0 100644
--- a/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs
+++ b/Tum4ik.JustClipboardManager/Ioc/Wrappers/IProcess.cs
@@ -1,9 +1,9 @@
using System.Diagnostics;
-using YT.IIGen.Attributes;
+using Tum4ik.StinimGen.Attributes;
namespace Tum4ik.JustClipboardManager.Ioc.Wrappers;
-[IIFor(typeof(Process), "ProcessWrapper")]
+[IIFor(typeof(Process), WrapperClassName = "ProcessWrapper")]
internal partial interface IProcess
{
}
diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs
index 154c058e..048ecfee 100644
--- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs
+++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IKernel32DllService.cs
@@ -3,26 +3,10 @@
namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers;
internal interface IKernel32DllService
{
- ///
- /// Adds a character string to the global atom table and returns a unique value (an atom) identifying the string.
- ///
- ///
- /// The null-terminated string to be added. The string can have a maximum size of 255 bytes.
- /// Strings that differ only in case are considered identical. The case of the first string of this name
- /// added to the table is preserved and returned by the GlobalGetAtomName function.
- ///
- ///
- /// If the function succeeds, the return value is the newly created atom.
- /// If the function fails, the return value is zero.
- ///
+ ///
ushort GlobalAddAtom(string lpString) => PInvoke.GlobalAddAtom(lpString);
- ///
- /// Decrements the reference count of a global string atom. If the atom's reference count reaches zero,
- /// removes the string associated with the atom from the global atom table.
- ///
- /// The atom and character string to be deleted.
- /// The function always returns (ATOM) 0.
+ ///
ushort GlobalDeleteAtom(ushort nAtom) => PInvoke.GlobalDeleteAtom(nAtom);
}
diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs
index 79673ce7..b9cca1f8 100644
--- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs
+++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IOleaccDllService.cs
@@ -6,6 +6,7 @@
namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers;
internal interface IOleaccDllService
{
+ ///
unsafe int AccessibleObjectFromWindow(nint hwnd, OBJECT_IDENTIFIER dwId, Guid riid, out object ppvObject)
{
var result = PInvoke.AccessibleObjectFromWindow((HWND) hwnd, (uint) dwId, riid, out var ppv);
diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs
index 7619be4c..370ca9cf 100644
--- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs
+++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/ISHCoreDllService.cs
@@ -6,20 +6,7 @@ namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers;
internal interface ISHCoreDllService
{
- ///
- /// Queries the dots per inch (dpi) of a display.
- ///
- /// Handle of the monitor being queried.
- /// The type of DPI being queried.
- ///
- /// The value of the DPI along the X axis. This value always refers to the horizontal edge,
- /// even when the screen is rotated.
- ///
- ///
- /// The value of the DPI along the Y axis. This value always refers to the vertical edge,
- /// even when the screen is rotated.
- ///
- /// True if operation succeeds, otherwise - false.
+ ///
bool GetDpiForMonitor(nint hmonitor, MONITOR_DPI_TYPE dpiType, out uint dpiX, out uint dpiY)
{
var result = PInvoke.GetDpiForMonitor((HMONITOR)hmonitor, dpiType, out dpiX, out dpiY);
diff --git a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs
index 3ca81439..868ffe9e 100644
--- a/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs
+++ b/Tum4ik.JustClipboardManager/Services/PInvokeWrappers/IUser32DllService.cs
@@ -10,100 +10,26 @@
namespace Tum4ik.JustClipboardManager.Services.PInvokeWrappers;
internal interface IUser32DllService
{
- ///
- /// Retrieves the position of the mouse cursor, in screen coordinates.
- ///
- ///
- /// A pointer to a structure that receives the screen coordinates of the cursor.
- ///
- /// Returns true if successful or false otherwise.
+ ///
bool GetCursorPos(out Point lpPoint) => PInvoke.GetCursorPos(out lpPoint);
- ///
- /// Changes the size, position, and Z order of a child, pop-up, or top-level window. These windows are ordered
- /// according to their appearance on the screen. The topmost window receives the highest rank and is the first
- /// window in the Z order.
- ///
- /// A handle to the window.
- ///
- /// A handle to the window to precede the positioned window in the Z order. This parameter must be a window handle
- /// or one of the following values.
- ///
- /// The new position of the left side of the window, in client coordinates.
- /// The new position of the top of the window, in client coordinates.
- /// The new width of the window, in pixels.
- /// The new height of the window, in pixels.
- /// The window sizing and positioning flags.
- ///
- /// If the function succeeds, the return value is true.
- /// If the function fails, the return value is false.
- ///
+ ///
bool SetWindowPos(nint hWnd, nint hWndInsertAfter, int X, int Y, int cx, int cy, SET_WINDOW_POS_FLAGS uFlags)
=> PInvoke.SetWindowPos((HWND) hWnd, (HWND) hWndInsertAfter, X, Y, cx, cy, uFlags);
- ///
- /// Sets the specified window's show state.
- ///
- /// A handle to the window.
- /// Controls how the window is to be shown.
- ///
- /// If the window was previously visible, the return value is nonzero.
- /// If the window was previously hidden, the return value is zero.
- ///
+ ///
bool ShowWindow(nint hWnd, SHOW_WINDOW_CMD nCmdShow) => PInvoke.ShowWindow((HWND) hWnd, nCmdShow);
- ///
- /// Retrieves a handle to the foreground window (the window with which the user is currently working). The system
- /// assigns a slightly higher priority to the thread that creates the foreground window than it does to other threads.
- ///
- ///
- /// C++ ( Type: Type: HWND )
The return value is a handle to the foreground window. The foreground window
- /// can be NULL in certain circumstances, such as when a window is losing activation.
- ///
+ ///
nint GetForegroundWindow() => PInvoke.GetForegroundWindow();
- ///
- /// Retrieves a handle to the display monitor that contains a specified point.
- ///
- /// Specifies the point of interest in virtual-screen coordinates.
- ///
- /// Determines the function's return value if the point is not contained within any display monitor.
- /// This parameter can be one of the values.
- ///
- ///
- /// If the point is contained by a display monitor, the return value is a handle to that display monitor.
- /// If the point is not contained by a display monitor,
- /// the return value depends on the value of .
- ///
+ ///
nint MonitorFromPoint(Point pt, MONITOR_FROM_FLAGS dwFlags) => PInvoke.MonitorFromPoint(pt, dwFlags);
- ///
- /// Retrieves a handle to the display monitor that has the largest area of intersection with the bounding rectangle
- /// of a specified window.
- ///
- /// A handle to the window of interest.
- ///
- /// Determines the function's return value if the window does not intersect any display monitor.
- ///
- ///
- /// If the window intersects one or more display monitor rectangles, the return value is an HMONITOR handle to
- /// the display monitor that has the largest area of intersection with the window.
- /// If the window does not intersect a display monitor, the return value depends on the value of dwFlags.
- ///
- ///
- /// If the window is currently minimized, MonitorFromWindow uses the rectangle of the window before it was minimized.
- ///
+ ///
nint MonitorFromWindow(nint hwnd, MONITOR_FROM_FLAGS dwFlags) => PInvoke.MonitorFromWindow((HWND) hwnd, dwFlags);
- ///
- /// Retrieves information about a display monitor.
- ///
- /// A handle to the display monitor of interest.
- /// Information about the specified display monitor.
- ///
- /// If the function succeeds, the return value is true.
- /// If the function fails, the return value is false.
- ///
+ ///
bool GetMonitorInfo(nint hMonitor, out MONITORINFO monitorInfo)
{
monitorInfo = new MONITORINFO();
@@ -111,100 +37,29 @@ bool GetMonitorInfo(nint hMonitor, out MONITORINFO monitorInfo)
return PInvoke.GetMonitorInfo((HMONITOR) hMonitor, ref monitorInfo);
}
- ///
- /// Defines a system-wide hot key.
- ///
- ///
- /// A handle to the window that will receive WM_HOTKEY messages generated by the hot key.
- /// If this parameter is NULL, WM_HOTKEY messages are posted to the message queue of the calling thread
- /// and must be processed in the message loop.
- ///
- ///
- /// The identifier of the hot key. If the hWnd parameter is NULL,
- /// then the hot key is associated with the current thread rather than with a particular window.
- ///
- /// The keys that must be pressed in combination with the .
- /// The key code of the hot key.
- ///
- /// If the function succeeds, the return value is true.
- /// If the function fails, the return value is false.
- ///
+ ///
bool RegisterHotKey(nint hWnd, int id, ModifierKeys modifiers, Key key)
{
var vk = (uint) KeyInterop.VirtualKeyFromKey(key);
return PInvoke.RegisterHotKey((HWND) hWnd, id, (HOT_KEY_MODIFIERS) modifiers, vk);
}
- ///
- /// Frees a hot key previously registered by the calling thread.
- ///
- ///
- /// A handle to the window associated with the hot key to be freed.
- /// This parameter should be NULL if the hot key is not associated with a window.
- ///
- /// The identifier of the hot key to be freed.
- ///
- /// If the function succeeds, the return value is true.
- /// If the function fails, the return value is false.
- ///
+ ///
bool UnregisterHotKey(nint hWnd, int id) => PInvoke.UnregisterHotKey((HWND) hWnd, id);
- ///
- /// Places the given window in the system-maintained clipboard format listener list.
- ///
- /// A handle to the window to be placed in the clipboard format listener list.
- /// Returns TRUE if successful, FALSE otherwise
+ ///
bool AddClipboardFormatListener(nint hwnd) => PInvoke.AddClipboardFormatListener((HWND) hwnd);
- ///
- /// Removes the given window from the system-maintained clipboard format listener list.
- ///
- /// A handle to the window to remove from the clipboard format listener list.
- /// Returns TRUE if successful, FALSE otherwise.
+ ///
bool RemoveClipboardFormatListener(nint hwnd) => PInvoke.RemoveClipboardFormatListener((HWND) hwnd);
- ///
- /// Synthesizes keystrokes, mouse motions, and button clicks.
- ///
- ///
- /// An array of structures.
- /// Each structure represents an event to be inserted into the keyboard or mouse input stream.
- ///
- ///
- /// The size, in bytes, of an structure.
- /// If cbSize is not the size of an structure, the function fails.
- ///
- ///
- /// The function returns the number of events that it successfully inserted into the keyboard or mouse input stream.
- /// If the function returns zero, the input was already blocked by another thread.
- ///
- uint SendInput(INPUT[] pInputs, int cbSize) => PInvoke.SendInput(/*cInputs,*/ pInputs, cbSize);
-
- ///
- /// Brings the thread that created the specified window into the foreground and activates the window.
- /// Keyboard input is directed to the window, and various visual cues are changed for the user.
- /// The system assigns a slightly higher priority to the thread that created the foreground window
- /// than it does to other threads.
- ///
- /// A handle to the window that should be activated and brought to the foreground.
- ///
- /// If the window was brought to the foreground, the return value is true.
- /// If the window was not brought to the foreground, the return value is false.
- ///
+ ///
+ uint SendInput(INPUT[] pInputs, int cbSize) => PInvoke.SendInput(pInputs, cbSize);
+
+ ///
bool SetForegroundWindow(nint hWnd) => PInvoke.SetForegroundWindow((HWND) hWnd);
- ///
- /// Sets the keyboard focus to the specified window.
- /// The window must be attached to the calling thread's message queue.
- ///
- ///
- /// A handle to the window that will receive the keyboard input. If this parameter is NULL, keystrokes are ignored.
- ///
- ///
- /// If the function succeeds, the return value is the handle to the window that previously had the keyboard focus.
- /// If the hWnd parameter is invalid or the window is not attached to the calling thread's message queue,
- /// the return value is NULL.
- ///
+ ///
nint SetFocus(nint hWnd) => PInvoke.SetFocus((HWND) hWnd);
}
diff --git a/Tum4ik.JustClipboardManager/Services/PasteService.cs b/Tum4ik.JustClipboardManager/Services/PasteService.cs
index ce95a85d..d68f7bc5 100644
--- a/Tum4ik.JustClipboardManager/Services/PasteService.cs
+++ b/Tum4ik.JustClipboardManager/Services/PasteService.cs
@@ -19,7 +19,7 @@ public PasteService(IClipboardService clipboardService,
private static readonly unsafe int InputStructSize = sizeof(INPUT);
- public void PasteData(nint targetWindowPtr, ICollection data, string? additionalInfo)
+ public unsafe void PasteData(nint targetWindowPtr, ICollection data, string? additionalInfo)
{
if (data.Count == 0)
{
diff --git a/Tum4ik.JustClipboardManager/Services/UpdateService.cs b/Tum4ik.JustClipboardManager/Services/UpdateService.cs
index c9886be2..d0d0e784 100644
--- a/Tum4ik.JustClipboardManager/Services/UpdateService.cs
+++ b/Tum4ik.JustClipboardManager/Services/UpdateService.cs
@@ -1,178 +1,182 @@
-using System.Diagnostics.CodeAnalysis;
-using System.IO;
-using System.Net.Http;
-using Microsoft.AppCenter.Crashes;
-using Octokit;
-using Tum4ik.JustClipboardManager.Ioc.Wrappers;
-using FileMode = System.IO.FileMode;
-
-namespace Tum4ik.JustClipboardManager.Services;
-internal class UpdateService : IUpdateService
-{
- private readonly IInfoService _infoService;
- private readonly IGitHubClient _gitHubClient;
- private readonly IEnvironment _environment;
-
- public UpdateService(IInfoService infoService,
- IGitHubClient gitHubClient,
- IEnvironment environment)
- {
- _infoService = infoService;
- _gitHubClient = gitHubClient;
- _environment = environment;
- }
-
-
- public async Task CheckForUpdatesAsync()
- {
- try
- {
- var latestRelease = await _gitHubClient.Repository
- .Release
- .GetLatest("Tum4ik", "just-clipboard-manager")
- .ConfigureAwait(false);
- if (Version.TryParse(latestRelease.TagName, out var latestReleaseVersion))
- {
- if (latestReleaseVersion > _infoService.Version)
- {
- var osArchitecture = _environment.Is64BitOperatingSystem ? "x64" : "x86";
- var downloadLink = latestRelease.Assets
- .Single(a => a.Name.Contains(osArchitecture, StringComparison.OrdinalIgnoreCase)
- && a.Name.Contains(".exe", StringComparison.OrdinalIgnoreCase))
- .BrowserDownloadUrl;
- return new(true)
- {
- LatestVersion = latestReleaseVersion,
- DownloadLink = new(downloadLink),
- ReleaseNotes = latestRelease.Body
- };
- }
- }
- else
- {
- Crashes.TrackError(
- new ArgumentException("Parse version problem when check for updates."), new Dictionary()
- {
- { "Lates release tag", latestRelease.TagName }
- }
- );
- }
- }
- catch (TaskCanceledException)
- {
- // TODO
- }
- catch (HttpRequestException)
- {
- // TODO: log request problem
- }
- catch (ApiException)
- {
- // TODO: log github api exception
+using System.Diagnostics.CodeAnalysis;
+using System.IO;
+using System.Net.Http;
+using Microsoft.AppCenter.Crashes;
+using Octokit;
+using Tum4ik.JustClipboardManager.Ioc.Wrappers;
+using FileMode = System.IO.FileMode;
+
+namespace Tum4ik.JustClipboardManager.Services;
+internal class UpdateService : IUpdateService
+{
+ private readonly IInfoService _infoService;
+ private readonly IGitHubClient _gitHubClient;
+ private readonly IEnvironment _environment;
+
+ public UpdateService(IInfoService infoService,
+ IGitHubClient gitHubClient,
+ IEnvironment environment)
+ {
+ _infoService = infoService;
+ _gitHubClient = gitHubClient;
+ _environment = environment;
+ }
+
+
+ public async Task CheckForUpdatesAsync()
+ {
+ try
+ {
+ var latestRelease = await _gitHubClient.Repository
+ .Release
+ .GetLatest("Tum4ik", "just-clipboard-manager")
+ .ConfigureAwait(false);
+ if (Version.TryParse(latestRelease.TagName, out var latestReleaseVersion))
+ {
+ if (latestReleaseVersion > _infoService.Version)
+ {
+ var osArchitecture = _environment.Is64BitOperatingSystem ? "x64" : "x86";
+ var downloadLink = latestRelease.Assets
+ .Single(a => a.Name.Contains(osArchitecture, StringComparison.OrdinalIgnoreCase)
+ && a.Name.Contains(".exe", StringComparison.OrdinalIgnoreCase))
+ .BrowserDownloadUrl;
+ return new(true)
+ {
+ LatestVersion = latestReleaseVersion,
+ DownloadLink = new(downloadLink),
+ ReleaseNotes = latestRelease.Body
+ };
+ }
+ }
+ else
+ {
+ Crashes.TrackError(
+ new ArgumentException("Parse version problem when check for updates."), new Dictionary()
+ {
+ { "Lates release tag", latestRelease.TagName }
+ }
+ );
+ }
+ }
+ catch (TaskCanceledException)
+ {
+ // TODO
+ }
+ catch (HttpRequestException)
+ {
+ // TODO: log request problem
+ }
+ catch (ApiException)
+ {
+ // TODO: log github api exception
+ }
+
+ return new(false);
+ }
+
+
+ public async Task DownloadUpdatesAsync(Uri downloadLink,
+ IProgress? progress,
+ CancellationToken cancellationToken)
+ {
+ using var httpClient = new HttpClient();
+ try
+ {
+ using var response = await httpClient
+ .GetAsync(downloadLink, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
+ .ConfigureAwait(false);
+ response.EnsureSuccessStatusCode();
+
+ var exeFilePath = Path.Combine(Path.GetTempPath(), downloadLink.Segments.Last());
+ var buffer = new byte[8192];
+ var totalBytes = response.Content.Headers.ContentLength;
+ var totalBytesDownloaded = 0L;
+
+ using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
+ using var fileStream =
+ new FileStream(exeFilePath, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length, true);
+
+ var prevPercentage = 0;
+ while (true)
+ {
+ var bytesDownloaded = await contentStream
+ .ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken)
+ .ConfigureAwait(false);
+ if (bytesDownloaded == 0)
+ {
+ progress?.Report(100);
+ break;
+ }
+
+ await fileStream.WriteAsync(buffer.AsMemory(0, bytesDownloaded), cancellationToken).ConfigureAwait(false);
+ totalBytesDownloaded += bytesDownloaded;
+
+ int currentPercentage;
+ if (totalBytes.HasValue)
+ {
+ currentPercentage = GetDownloadPercentage(totalBytes.Value, totalBytesDownloaded);
+ }
+ else
+ {
+ currentPercentage = 0;
+ }
+
+ if (currentPercentage > prevPercentage)
+ {
+ prevPercentage = currentPercentage;
+ progress?.Report(currentPercentage);
+ }
+ }
+
+ return new(exeFilePath);
+ }
+ catch (HttpRequestException)
+ {
+ // TODO: log request problem
+ }
+ catch (TaskCanceledException)
+ {
+ // download canceled
}
-
- return new(false);
- }
-
-
- public async Task DownloadUpdatesAsync(Uri downloadLink,
- IProgress? progress,
- CancellationToken cancellationToken)
- {
- using var httpClient = new HttpClient();
- try
+ catch (IOException)
{
- using var response = await httpClient
- .GetAsync(downloadLink, HttpCompletionOption.ResponseHeadersRead, cancellationToken)
- .ConfigureAwait(false);
- response.EnsureSuccessStatusCode();
-
- var exeFilePath = Path.Combine(Path.GetTempPath(), downloadLink.Segments.Last());
- var buffer = new byte[8192];
- var totalBytes = response.Content.Headers.ContentLength;
- var totalBytesDownloaded = 0L;
-
- using var contentStream = await response.Content.ReadAsStreamAsync(cancellationToken).ConfigureAwait(false);
- using var fileStream =
- new FileStream(exeFilePath, FileMode.Create, FileAccess.Write, FileShare.None, buffer.Length, true);
-
- var prevPercentage = 0;
- while (true)
- {
- var bytesDownloaded = await contentStream
- .ReadAsync(buffer.AsMemory(0, buffer.Length), cancellationToken)
- .ConfigureAwait(false);
- if (bytesDownloaded == 0)
- {
- progress?.Report(100);
- break;
- }
-
- await fileStream.WriteAsync(buffer.AsMemory(0, bytesDownloaded), cancellationToken).ConfigureAwait(false);
- totalBytesDownloaded += bytesDownloaded;
-
- int currentPercentage;
- if (totalBytes.HasValue)
- {
- currentPercentage = GetDownloadPercentage(totalBytes.Value, totalBytesDownloaded);
- }
- else
- {
- currentPercentage = 0;
- }
-
- if (currentPercentage > prevPercentage)
- {
- prevPercentage = currentPercentage;
- progress?.Report(currentPercentage);
- }
- }
-
- return new(exeFilePath);
- }
- catch (HttpRequestException)
- {
- // TODO: log request problem
- }
- catch (TaskCanceledException)
- {
- // download canceled
- }
-
- return null;
- }
-
-
- [ExcludeFromCodeCoverage]
- public void InstallUpdates(FileInfo exeFile)
- {
-#if !DEBUG
- System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(exeFile.FullName, "/SILENT")
- {
- UseShellExecute = true
- });
-#endif
- }
-
-
- public async void SilentUpdate()
- {
- var checkUpdatesResult = await CheckForUpdatesAsync().ConfigureAwait(false);
- if (checkUpdatesResult.NewVersionIsAvailable
- && checkUpdatesResult.DownloadLink is not null)
- {
- var exe = await DownloadUpdatesAsync(checkUpdatesResult.DownloadLink, null, CancellationToken.None)
- .ConfigureAwait(false);
- if (exe is not null)
- {
- InstallUpdates(exe);
- }
- }
- }
-
-
- private static int GetDownloadPercentage(long totalSize, long downloadedSize)
- {
- return (int) ((double) downloadedSize / totalSize * 100);
- }
-}
+ // aborted connection
+ }
+
+ return null;
+ }
+
+
+ [ExcludeFromCodeCoverage]
+ public void InstallUpdates(FileInfo exeFile)
+ {
+#if !DEBUG
+ System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(exeFile.FullName, "/SILENT")
+ {
+ UseShellExecute = true
+ });
+#endif
+ }
+
+
+ public async void SilentUpdate()
+ {
+ var checkUpdatesResult = await CheckForUpdatesAsync().ConfigureAwait(false);
+ if (checkUpdatesResult.NewVersionIsAvailable
+ && checkUpdatesResult.DownloadLink is not null)
+ {
+ var exe = await DownloadUpdatesAsync(checkUpdatesResult.DownloadLink, null, CancellationToken.None)
+ .ConfigureAwait(false);
+ if (exe is not null)
+ {
+ InstallUpdates(exe);
+ }
+ }
+ }
+
+
+ private static int GetDownloadPercentage(long totalSize, long downloadedSize)
+ {
+ return (int) ((double) downloadedSize / totalSize * 100);
+ }
+}
diff --git a/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj b/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj
index 49562074..7fbfe9d1 100644
--- a/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj
+++ b/Tum4ik.JustClipboardManager/Tum4ik.JustClipboardManager.csproj
@@ -175,10 +175,10 @@
-
+
-
+
@@ -191,14 +191,14 @@
all
-
+
-
-
-
+
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
-
+
+