Compare commits

...

40 Commits

Author SHA1 Message Date
4e8c500fb2 merged from work 2023-05-06 13:23:42 +02:00
11e3a02511 merged from work 2019-12-20 20:02:14 +01:00
202608651b „README.md“ ändern 2019-02-12 08:26:08 +01:00
8f2ead4f48 Merge branch 'master' of https://git.boerchers.org/holger/Katteker 2018-12-14 20:41:32 +01:00
e86cb4fcc2 update nuget packages 2018-12-14 20:41:23 +01:00
cd8bd89373 „README.md“ ändern 2018-10-01 21:10:53 +02:00
a5532b6fa1 tada 2018-09-28 21:58:43 +02:00
f7abe144aa Added compilers 2018-09-28 21:57:07 +02:00
1676d03490 cleanup 2018-08-25 20:42:08 +02:00
bfb6971564 Added another command line parser. Has a nice parameter verification framework 2018-08-16 21:36:25 +02:00
a08d551403 Fun with MaterialDesignInXAML 2018-08-03 21:57:38 +02:00
d39ffa2cb2 Playing with Snackbar 2018-08-02 22:53:13 +02:00
ad14691479 Added Material Design themes 2018-08-02 22:10:11 +02:00
3e7f8c5a23 Merge branch 'master' of https://git.boerchers.org/holger/Katteker 2018-08-02 21:47:34 +02:00
ec576558c8 Fixed a lot of "in the wild" problems. 2018-08-02 12:55:50 +02:00
c7b026ce15 „README.md“ ändern 2018-08-02 12:54:29 +02:00
d85858b0c1 TemporaryDirectory will deleted at the end of process, Path of NSIS is besite of base directory. 2018-08-02 10:23:45 +02:00
f8ca13d7e6 Added Jetbrains.Annotations, updated Autofac 2018-07-31 22:41:26 +02:00
947db44090 More Prism stuff 2018-07-31 20:58:55 +02:00
9c23948f38 simplify ApplicationArguments 2018-07-30 23:09:41 +02:00
aa70a24a26 Little refactoring and improved error handling. 2018-07-30 15:07:48 +02:00
0ed81d68c8 Added Prism to example, Added ability to filter files and minor bugfixes 2018-07-28 23:57:14 +02:00
a18f7b0837 „README.md“ ändern 2018-07-23 20:19:21 +02:00
eaec8c632b The application will written appdata\programs, PhysicalFile is now a struct. should be enough 2018-07-15 22:00:40 +02:00
7009fb1690 Updated readme 2018-07-08 14:30:52 +02:00
92b32975e8 fixed warnings. 2018-06-16 09:59:36 +02:00
ebc776459d Renamed Katteker.Gui to Katteker.UserInterface. 2018-06-16 09:45:56 +02:00
3aebff4e6d moved to nunit 2018-06-03 23:14:33 +02:00
26343921f7 Merge branch 'master' of https://git.boerchers.org/holger/Katteker 2018-05-26 23:18:45 +02:00
d87adfc7f0 Refactored ChangelogHelper 2018-05-26 23:18:39 +02:00
f7800dfb11 cleanup 2018-05-18 20:05:15 +02:00
6d086205d4 cleanup code 2018-05-18 20:00:56 +02:00
e68f256d80 updated README.md 2018-05-18 10:40:16 +02:00
17e12093f8 cleanup code, added version to commandline interface, updated MSTest nuget packages. 2018-05-18 10:38:59 +02:00
cf4cc2cd93 filehash over the whole file. 2018-05-18 08:59:06 +02:00
3da9846ae3 Deleted copy of MarkdownSharp.cs 2018-05-14 20:20:32 +02:00
71d5981b8d Added unittest 2018-04-04 20:28:52 +02:00
ff424c6c14 funny stuff 2018-03-27 16:10:38 +02:00
45768d89a6 Added comments. 2018-03-27 15:16:24 +02:00
c4132b4061 cleanup, renaming and so on... 2018-03-27 11:28:30 +02:00
163 changed files with 21533 additions and 7328 deletions

196
.editorconfig Normal file
View File

@ -0,0 +1,196 @@
# Remove the line below if you want to inherit .editorconfig settings from higher directories
root = true
# C# files
[*.cs]
#### Core EditorConfig Options ####
# Indentation and spacing
indent_size = 4
indent_style = space
tab_width = 4
# New line preferences
end_of_line = crlf
insert_final_newline = false
#### .NET Coding Conventions ####
# Organize usings
dotnet_separate_import_directive_groups = false
dotnet_sort_system_directives_first = false
# this. and Me. preferences
dotnet_style_qualification_for_event = false:suggestion
dotnet_style_qualification_for_field = false:silent
dotnet_style_qualification_for_method = false:suggestion
dotnet_style_qualification_for_property = false:suggestion
# Language keywords vs BCL types preferences
dotnet_style_predefined_type_for_locals_parameters_members = true:warning
dotnet_style_predefined_type_for_member_access = true:warning
# Parentheses preferences
dotnet_style_parentheses_in_arithmetic_binary_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_other_binary_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_other_operators = always_for_clarity:suggestion
dotnet_style_parentheses_in_relational_binary_operators = always_for_clarity:suggestion
# Modifier preferences
dotnet_style_require_accessibility_modifiers = for_non_interface_members:silent
# Expression-level preferences
csharp_style_deconstructed_variable_declaration = true:suggestion
csharp_style_inlined_variable_declaration = true:suggestion
csharp_style_throw_expression = true:suggestion
dotnet_style_coalesce_expression = true:suggestion
dotnet_style_collection_initializer = true:suggestion
dotnet_style_explicit_tuple_names = true:suggestion
dotnet_style_null_propagation = true:suggestion
dotnet_style_object_initializer = true:suggestion
dotnet_style_prefer_auto_properties = true:suggestion
dotnet_style_prefer_compound_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_assignment = true:suggestion
dotnet_style_prefer_conditional_expression_over_return = true:suggestion
dotnet_style_prefer_inferred_anonymous_type_member_names = true:suggestion
dotnet_style_prefer_inferred_tuple_names = true:suggestion
dotnet_style_prefer_is_null_check_over_reference_equality_method = true:suggestion
# Field preferences
dotnet_style_readonly_field = true:suggestion
# Parameter preferences
dotnet_code_quality_unused_parameters = all:suggestion
#### C# Coding Conventions ####
# var preferences
csharp_style_var_elsewhere = true:suggestion
csharp_style_var_for_built_in_types = true:suggestion
csharp_style_var_when_type_is_apparent = true:suggestion
# Expression-bodied members
csharp_style_expression_bodied_accessors = true:silent
csharp_style_expression_bodied_constructors = false:silent
csharp_style_expression_bodied_indexers = true:silent
csharp_style_expression_bodied_lambdas = true:silent
csharp_style_expression_bodied_local_functions = false:silent
csharp_style_expression_bodied_methods = true:silent
csharp_style_expression_bodied_operators = when_on_single_line:silent
csharp_style_expression_bodied_properties = true:silent
# Pattern matching preferences
csharp_style_pattern_matching_over_as_with_null_check = true:suggestion
csharp_style_pattern_matching_over_is_with_cast_check = true:suggestion
# Null-checking preferences
csharp_style_conditional_delegate_call = true:suggestion
# Modifier preferences
csharp_prefer_static_local_function = true:suggestion
csharp_preferred_modifier_order = public,private,protected,internal,static,extern,new,virtual,abstract,sealed,override,readonly,unsafe,volatile,async
# Code-block preferences
csharp_prefer_braces = true:silent
csharp_prefer_simple_using_statement = false:suggestion
# Expression-level preferences
csharp_prefer_simple_default_expression = true:suggestion
csharp_style_pattern_local_over_anonymous_function = true:suggestion
csharp_style_prefer_index_operator = true:suggestion
csharp_style_prefer_range_operator = true:suggestion
csharp_style_unused_value_assignment_preference = discard_variable:suggestion
csharp_style_unused_value_expression_statement_preference = discard_variable:silent
# 'using' directive preferences
csharp_using_directive_placement = outside_namespace:warning
#### C# Formatting Rules ####
# New line preferences
csharp_new_line_before_catch = true
csharp_new_line_before_else = true
csharp_new_line_before_finally = true
csharp_new_line_before_members_in_anonymous_types = true
csharp_new_line_before_members_in_object_initializers = true
csharp_new_line_before_open_brace = all
csharp_new_line_between_query_expression_clauses = true
# Indentation preferences
csharp_indent_block_contents = true
csharp_indent_braces = false
csharp_indent_case_contents = true
csharp_indent_case_contents_when_block = true
csharp_indent_labels = no_change
csharp_indent_switch_labels = true
# Space preferences
csharp_space_after_cast = false
csharp_space_after_colon_in_inheritance_clause = true
csharp_space_after_comma = true
csharp_space_after_dot = false
csharp_space_after_keywords_in_control_flow_statements = true
csharp_space_after_semicolon_in_for_statement = true
csharp_space_around_binary_operators = before_and_after
csharp_space_around_declaration_statements = false
csharp_space_before_colon_in_inheritance_clause = true
csharp_space_before_comma = false
csharp_space_before_dot = false
csharp_space_before_open_square_brackets = false
csharp_space_before_semicolon_in_for_statement = false
csharp_space_between_empty_square_brackets = false
csharp_space_between_method_call_empty_parameter_list_parentheses = false
csharp_space_between_method_call_name_and_opening_parenthesis = false
csharp_space_between_method_call_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_declaration_parameter_list_parentheses = false
csharp_space_between_parentheses = false
csharp_space_between_square_brackets = false
# Wrapping preferences
csharp_preserve_single_line_blocks = true
csharp_preserve_single_line_statements = true
#### Naming styles ####
# Naming rules
dotnet_naming_rule.interface_should_be_begins_with_i.severity = suggestion
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_rule.types_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.types_should_be_pascal_case.symbols = types
dotnet_naming_rule.types_should_be_pascal_case.style = pascal_case
dotnet_naming_rule.non_field_members_should_be_pascal_case.severity = suggestion
dotnet_naming_rule.non_field_members_should_be_pascal_case.symbols = non_field_members
dotnet_naming_rule.non_field_members_should_be_pascal_case.style = pascal_case
# Symbol specifications
dotnet_naming_symbols.interface.applicable_kinds = interface
dotnet_naming_symbols.interface.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.interface.required_modifiers =
dotnet_naming_symbols.types.applicable_kinds = class, struct, interface, enum
dotnet_naming_symbols.types.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.types.required_modifiers =
dotnet_naming_symbols.non_field_members.applicable_kinds = property, event, method
dotnet_naming_symbols.non_field_members.applicable_accessibilities = public, internal, private, protected, protected_internal
dotnet_naming_symbols.non_field_members.required_modifiers =
# Naming styles
dotnet_naming_style.pascal_case.required_prefix =
dotnet_naming_style.pascal_case.required_suffix =
dotnet_naming_style.pascal_case.word_separator =
dotnet_naming_style.pascal_case.capitalization = pascal_case
dotnet_naming_style.begins_with_i.required_prefix = I
dotnet_naming_style.begins_with_i.required_suffix =
dotnet_naming_style.begins_with_i.word_separator =
dotnet_naming_style.begins_with_i.capitalization = pascal_case

7
.gitignore vendored
View File

@ -111,3 +111,10 @@ UpgradeLog*.XML
.vs
*.DotSettings
/Creator/SetupTmpl.cs
nsis/*
/Creator/SetupTemplate1.cs
/KattekerCreator/contrib/AppStub.exe
/KattekerCreator/contrib/AppStub.exe.config
/.idea
/app-stub/target
/nupkg

27
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,27 @@
{
// Use IntelliSense to find out which attributes exist for C# debugging
// Use hover for the description of the existing attributes
// For further information visit https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Launch (console)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build",
// If you have changed target frameworks, make sure to update the program path.
"program": "${workspaceFolder}/KattekerCreator/bin/Debug/netcoreapp3.0/KattekerCreator.dll",
"args": [],
"cwd": "${workspaceFolder}/KattekerCreator",
// For more information about the 'console' field, see https://github.com/OmniSharp/omnisharp-vscode/blob/master/debugger-launchjson.md#console-terminal-window
"console": "internalConsole",
"stopAtEntry": false
},
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

36
.vscode/tasks.json vendored Normal file
View File

@ -0,0 +1,36 @@
{
"version": "2.0.0",
"tasks": [
{
"label": "build",
"command": "dotnet",
"type": "process",
"args": [
"build",
"${workspaceFolder}/KattekerCreator/KattekerCreator.csproj"
],
"problemMatcher": "$tsc"
},
{
"label": "publish",
"command": "dotnet",
"type": "process",
"args": [
"publish",
"${workspaceFolder}/KattekerCreator/KattekerCreator.csproj"
],
"problemMatcher": "$tsc"
},
{
"label": "watch",
"command": "dotnet",
"type": "process",
"args": [
"watch",
"run",
"${workspaceFolder}/KattekerCreator/KattekerCreator.csproj"
],
"problemMatcher": "$tsc"
}
]
}

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
</configuration>

View File

@ -1,53 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>AppStub</RootNamespace>
<AssemblyName>AppStub</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="..\Katteker\Common\SemVersion.cs">
<Link>SemVersion.cs</Link>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,78 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Windows.Forms;
using Semver;
namespace AppStub
{
internal static class Program
{
[STAThread]
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
try
{
var commandline = string.Join(" ", args);
var location = new FileInfo(Assembly.GetExecutingAssembly().Location);
var directory = location.Directory;
if (directory == null) return;
var files = directory.EnumerateFiles(location.Name, SearchOption.AllDirectories)
.Where(x => x.Directory?.Name.StartsWith("app-") == true);
var entries = new SortedList<SemVersion, FileInfo>();
foreach (var file in files)
{
var version = SemVersion.TryParse(file.Directory?.Name.Replace("app-", ""), out var value)
? value
: new SemVersion(0);
entries.Add(version, file);
}
var latestVersion = entries.LastOrDefault().Value;
if (latestVersion == null) throw new FileNotFoundException();
DeleteOldVersionDirectories(entries.Where(x => x.Value != latestVersion));
using (var process = new Process())
{
process.StartInfo =
new ProcessStartInfo(latestVersion.FullName)
{
Arguments = commandline,
WorkingDirectory = latestVersion.DirectoryName ?? Assembly.GetExecutingAssembly().Location,
UseShellExecute = false
};
process.Start();
process.WaitForExit();
}
}
catch (Exception e)
{
MessageBox.Show(e.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static void DeleteOldVersionDirectories(IEnumerable<KeyValuePair<SemVersion, FileInfo>> dirEntries)
{
#if !DEBUG
foreach (var directoryInfo in dirEntries)
{
try
{
directoryInfo.Value.Directory?.Delete(true);
}
catch
{
// silently ignore
}
}
#endif
}
}
}

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("AppStub")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("AppStub")]
[assembly: AssemblyCopyright("Copyright © 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("e746ae0f-beea-4c18-9ed8-2e708ed00a5b")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5"/></startup>
</configuration>

View File

@ -1,19 +0,0 @@
using System;
using System.IO;
namespace Katteker.AppStub
{
public class AppEntry : IComparable<AppEntry>
{
public AppEntry(DirectoryInfo info)
{
DirInfo = info;
Version = SemanticVersion.Parse(info.Name.Replace("app-", ""));
}
public SemanticVersion Version { get; }
public DirectoryInfo DirInfo { get; }
public int CompareTo(AppEntry other) => Version.CompareTo(other.Version);
}
}

View File

@ -1,70 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{AF7579CC-C0B2-4E5A-B052-00D2991DC715}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Katteker.AppStubEx</RootNamespace>
<AssemblyName>AppStubEx</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup>
<StartupObject />
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.ServiceProcess" />
<Reference Include="System.Windows.Forms" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="AppEntry.cs" />
<Compile Include="IniFile.cs" />
<Compile Include="InstallerUx.cs">
<SubType>Form</SubType>
</Compile>
<Compile Include="InstallerUx.designer.cs">
<DependentUpon>InstallerUx.cs</DependentUpon>
</Compile>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SemanticVersion.cs" />
<Compile Include="Taskbar.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<EmbeddedResource Include="InstallerUx.resx">
<DependentUpon>InstallerUx.cs</DependentUpon>
</EmbeddedResource>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,50 +0,0 @@
using System.IO;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
namespace Katteker.AppStub
{
public class IniFile // revision 11
{
private readonly FileInfo _path;
private readonly string _exe = Assembly.GetExecutingAssembly().GetName().Name;
[DllImport("kernel32", CharSet = CharSet.Unicode)]
private static extern long WritePrivateProfileString(string section, string key, string value, string filePath);
[DllImport("kernel32", CharSet = CharSet.Unicode)]
private static extern int GetPrivateProfileString(string section, string key, string Default, StringBuilder retVal, int size, string filePath);
public IniFile(string iniPath = null)
{
_path = new FileInfo(iniPath ?? _exe + ".ini");
}
public string Read(string key, string section = null)
{
var retVal = new StringBuilder(255);
GetPrivateProfileString(section ?? _exe, key, "", retVal, 255, _path.FullName);
return retVal.ToString();
}
public void Write(string key, string value, string section = null)
{
WritePrivateProfileString(section ?? _exe, key, value, _path.FullName);
}
public void DeleteKey(string key, string section = null)
{
Write(key, null, section ?? _exe);
}
public void DeleteSection(string section = null)
{
Write(null, null, section ?? _exe);
}
public bool Exists => _path.Exists;
public bool KeyExists(string key, string section = null) => Read(key, section).Length > 0;
}
}

View File

@ -1,73 +0,0 @@
using System;
using System.Drawing;
using System.Windows.Forms;
namespace Katteker.AppStub
{
public sealed partial class InstallerUx : Form
{
private int _autoCloseCountdown = 10;
public InstallerUx(string appName)
{
Font = SystemFonts.MessageBoxFont;
InitializeComponent();
SetLocationAndShow();
this.appName.Text = appName;
}
private void SetLocationAndShow()
{
var taskBar = new Taskbar();
switch (taskBar.Position)
{
case TaskbarPosition.Unknown:
break;
case TaskbarPosition.Left:
Location = new Point(taskBar.Bounds.Left + taskBar.Bounds.Width, taskBar.Bounds.Bottom - Size.Height);
break;
case TaskbarPosition.Top:
Location = new Point(taskBar.Bounds.Right - Size.Width, taskBar.Bounds.Bottom);
break;
case TaskbarPosition.Right:
Location = new Point(taskBar.Bounds.Left - Size.Width, taskBar.Bounds.Bottom - Size.Height);
break;
case TaskbarPosition.Bottom:
Location = new Point(taskBar.Bounds.Right - Size.Width, taskBar.Bounds.Top - Size.Height);
break;
default:
break;
}
Show();
}
private void closeBtn_Click(object sender, EventArgs e)
{
Close();
}
private void installBtn_Click(object sender, EventArgs e)
{
_autoCloseCountdown = 0;
MessageBox.Show("Hallo Welt");
}
private void autoCloseTimer_Tick(object sender, EventArgs e)
{
switch (_autoCloseCountdown)
{
case 1:
Close();
break;
case 0:
countDownLbl.Text = string.Empty;
autoCloseTimer.Enabled = false;
break;
default:
countDownLbl.Tag = --_autoCloseCountdown;
countDownLbl.Text = _autoCloseCountdown.ToString();
break;
}
}
}
}

View File

@ -1,149 +0,0 @@
namespace Katteker.AppStub
{
sealed partial class InstallerUx
{
/// <summary>
/// Erforderliche Designervariable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Verwendete Ressourcen bereinigen.
/// </summary>
/// <param name="disposing">True, wenn verwaltete Ressourcen gelöscht werden sollen; andernfalls False.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Vom Windows Form-Designer generierter Code
/// <summary>
/// Erforderliche Methode für die Designerunterstützung.
/// Der Inhalt der Methode darf nicht mit dem Code-Editor geändert werden.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.closeBtn = new System.Windows.Forms.Button();
this.installBtn = new System.Windows.Forms.Button();
this.messageLbl = new System.Windows.Forms.Label();
this.appName = new System.Windows.Forms.Label();
this.countDownLbl = new System.Windows.Forms.Label();
this.autoCloseTimer = new System.Windows.Forms.Timer(this.components);
this.SuspendLayout();
//
// closeBtn
//
this.closeBtn.AutoSize = true;
this.closeBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.closeBtn.FlatAppearance.BorderSize = 0;
this.closeBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.closeBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(65)))));
this.closeBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.closeBtn.Font = new System.Drawing.Font("Marlett", 10F);
this.closeBtn.Location = new System.Drawing.Point(249, 0);
this.closeBtn.Margin = new System.Windows.Forms.Padding(0);
this.closeBtn.Name = "closeBtn";
this.closeBtn.Size = new System.Drawing.Size(31, 26);
this.closeBtn.TabIndex = 1;
this.closeBtn.TabStop = false;
this.closeBtn.Text = "r";
this.closeBtn.UseVisualStyleBackColor = true;
this.closeBtn.Click += new System.EventHandler(this.closeBtn_Click);
//
// installBtn
//
this.installBtn.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.installBtn.FlatAppearance.BorderSize = 0;
this.installBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(0)))), ((int)(((byte)(122)))), ((int)(((byte)(204)))));
this.installBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(63)))), ((int)(((byte)(63)))), ((int)(((byte)(65)))));
this.installBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.installBtn.Location = new System.Drawing.Point(192, 59);
this.installBtn.Margin = new System.Windows.Forms.Padding(0);
this.installBtn.Name = "installBtn";
this.installBtn.Size = new System.Drawing.Size(77, 30);
this.installBtn.TabIndex = 2;
this.installBtn.TabStop = false;
this.installBtn.Text = "Install";
this.installBtn.UseVisualStyleBackColor = true;
this.installBtn.Click += new System.EventHandler(this.installBtn_Click);
//
// messageLbl
//
this.messageLbl.AutoSize = true;
this.messageLbl.Location = new System.Drawing.Point(11, 68);
this.messageLbl.Margin = new System.Windows.Forms.Padding(2, 0, 2, 0);
this.messageLbl.Name = "messageLbl";
this.messageLbl.Size = new System.Drawing.Size(93, 13);
this.messageLbl.TabIndex = 3;
this.messageLbl.Text = "Upgrade available";
//
// appName
//
this.appName.AutoSize = true;
this.appName.Font = new System.Drawing.Font("Microsoft Sans Serif", 12F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.appName.Location = new System.Drawing.Point(13, 13);
this.appName.Name = "appName";
this.appName.Size = new System.Drawing.Size(80, 20);
this.appName.TabIndex = 4;
this.appName.Text = "AppName";
//
// countDownLbl
//
this.countDownLbl.AutoSize = true;
this.countDownLbl.BackColor = System.Drawing.Color.Transparent;
this.countDownLbl.Font = new System.Drawing.Font("Microsoft Sans Serif", 10F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.countDownLbl.ForeColor = System.Drawing.SystemColors.ControlDark;
this.countDownLbl.Location = new System.Drawing.Point(229, 5);
this.countDownLbl.Name = "countDownLbl";
this.countDownLbl.Size = new System.Drawing.Size(24, 17);
this.countDownLbl.TabIndex = 5;
this.countDownLbl.Tag = 10;
this.countDownLbl.Text = "10";
this.countDownLbl.TextAlign = System.Drawing.ContentAlignment.TopRight;
//
// autoCloseTimer
//
this.autoCloseTimer.Enabled = true;
this.autoCloseTimer.Interval = 1000;
this.autoCloseTimer.Tick += new System.EventHandler(this.autoCloseTimer_Tick);
//
// InstallerUx
//
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None;
this.BackColor = System.Drawing.Color.FromArgb(((int)(((byte)(45)))), ((int)(((byte)(45)))), ((int)(((byte)(48)))));
this.ClientSize = new System.Drawing.Size(278, 98);
this.ControlBox = false;
this.Controls.Add(this.countDownLbl);
this.Controls.Add(this.appName);
this.Controls.Add(this.messageLbl);
this.Controls.Add(this.installBtn);
this.Controls.Add(this.closeBtn);
this.ForeColor = System.Drawing.SystemColors.Control;
this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedToolWindow;
this.Location = new System.Drawing.Point(30, 0);
this.Name = "InstallerUx";
this.ShowIcon = false;
this.ShowInTaskbar = false;
this.StartPosition = System.Windows.Forms.FormStartPosition.Manual;
this.TopMost = true;
this.ResumeLayout(false);
this.PerformLayout();
}
#endregion
private System.Windows.Forms.Button closeBtn;
private System.Windows.Forms.Button installBtn;
private System.Windows.Forms.Label messageLbl;
private System.Windows.Forms.Label appName;
private System.Windows.Forms.Label countDownLbl;
private System.Windows.Forms.Timer autoCloseTimer;
}
}

View File

@ -1,126 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<metadata name="autoCloseTimer.TrayLocation" type="System.Drawing.Point, System.Drawing, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a">
<value>167, 17</value>
</metadata>
<metadata name="$this.TrayHeight" type="System.Int32, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089">
<value>87</value>
</metadata>
</root>

View File

@ -1,102 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace Katteker.AppStub
{
internal class Program
{
private Program()
{
CurrentDir = new DirectoryInfo(AppDomain.CurrentDomain.BaseDirectory);
ConfigFile = new IniFile(Path.Combine(CurrentDir.FullName, "app.ini"));
}
private DirectoryInfo CurrentDir { get; }
private IniFile ConfigFile { get; }
private Process MainProcess { get; set; }
[STAThread]
private static void Main(string[] args)
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
var p = new Program();
p.Run(args);
}
private void Run(string[] args)
{
StartExecutable(args);
StartUpdateInfo();
}
private static void StartUpdateInfo()
{
Application.Run(new InstallerUx("TestProgramm"));
}
private void StartExecutable(string[] args)
{
var dirEntries = CurrentDir.EnumerateDirectories().Where(x => x.Name.StartsWith("app-"))
.Select(x => new AppEntry(x)).ToList();
var latestVersion = dirEntries.OrderByDescending(x => x).FirstOrDefault();
if (latestVersion != null && ConfigFile.Exists)
{
try
{
var executable = ConfigFile.Read("Executable", "Main");
var a = args.Aggregate(string.Empty, (current, s) => current + s + " ").TrimEnd(' ');
MainProcess = new Process
{
StartInfo =
new ProcessStartInfo($"{latestVersion.DirInfo.FullName}\\{executable}")
{
Arguments = a,
WorkingDirectory = latestVersion.DirInfo.FullName,
UseShellExecute = false
}
};
MainProcess.Start();
Task.Run(() =>
DeleteOldVersionDirectories(dirEntries.Where(x =>
x.DirInfo.Name != latestVersion.DirInfo.Name)));
}
catch (Exception ex)
{
MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
else
{
MessageBox.Show("Error, File not found", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
private static void DeleteOldVersionDirectories(IEnumerable<AppEntry> dirEntries)
{
#if !DEBUG
foreach (var directoryInfo in dirEntries)
{
try
{
directoryInfo.DirInfo.Delete(true);
}
catch (Exception)
{
// silently ignore
}
}
#endif
}
}
}

View File

@ -1,42 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
//[assembly: AssemblyTitle("AppStub")]
//[assembly: AssemblyDescription("")]
//[assembly: AssemblyConfiguration("")]
//[assembly: AssemblyCompany("")]
//[assembly: AssemblyProduct("AppStub")]
//[assembly: AssemblyCopyright("Copyright © 2016")]
//[assembly: AssemblyTrademark("")]
//[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("af7579cc-c0b2-4e5a-b052-00d2991dc715")]
[assembly: AssemblyTitle("Katteker.AppStubEx")]
[assembly: AssemblyDescription("Katteker.AppStubEx")]
[assembly: AssemblyCompany("Holger Börchers")]
[assembly: AssemblyProduct("Katteker.AppStubEx")]
[assembly: AssemblyCopyright("Holger Börchers")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden.
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
//[assembly: AssemblyVersion("1.0.0.0")]
//[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,117 +0,0 @@
using System;
using System.Drawing;
using System.Runtime.InteropServices;
namespace Katteker.AppStub
{
public enum TaskbarPosition
{
Unknown = -1,
Left,
Top,
Right,
Bottom
}
public sealed class Taskbar
{
private const string ClassName = "Shell_TrayWnd";
public Taskbar()
{
var taskbarHandle = User32.FindWindow(ClassName, null);
var data = new APPBARDATA
{
cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA)),
hWnd = taskbarHandle
};
var result = Shell32.SHAppBarMessage(ABM.GetTaskbarPos, ref data);
if (result == IntPtr.Zero)
throw new InvalidOperationException();
Position = (TaskbarPosition) data.uEdge;
Bounds = Rectangle.FromLTRB(data.rc.left, data.rc.top, data.rc.right, data.rc.bottom);
data.cbSize = (uint) Marshal.SizeOf(typeof(APPBARDATA));
result = Shell32.SHAppBarMessage(ABM.GetState, ref data);
var state = result.ToInt32();
AlwaysOnTop = (state & ABS.AlwaysOnTop) == ABS.AlwaysOnTop;
AutoHide = (state & ABS.Autohide) == ABS.Autohide;
}
public Rectangle Bounds { get; }
public TaskbarPosition Position { get; private set; }
public Point Location => Bounds.Location;
public Size Size => Bounds.Size;
//Always returns false under Windows 7
public bool AlwaysOnTop { get; private set; }
public bool AutoHide { get; private set; }
}
public enum ABM : uint
{
New = 0x00000000,
Remove = 0x00000001,
QueryPos = 0x00000002,
SetPos = 0x00000003,
GetState = 0x00000004,
GetTaskbarPos = 0x00000005,
Activate = 0x00000006,
GetAutoHideBar = 0x00000007,
SetAutoHideBar = 0x00000008,
WindowPosChanged = 0x00000009,
SetState = 0x0000000A
}
public enum ABE : uint
{
Left = 0,
Top = 1,
Right = 2,
Bottom = 3
}
public static class ABS
{
public const int Autohide = 0x0000001;
public const int AlwaysOnTop = 0x0000002;
}
public static class Shell32
{
[DllImport("shell32.dll", SetLastError = true)]
public static extern IntPtr SHAppBarMessage(ABM dwMessage, [In] ref APPBARDATA pData);
}
public static class User32
{
[DllImport("user32.dll", SetLastError = true)]
public static extern IntPtr FindWindow(string lpClassName, string lpWindowName);
}
[StructLayout(LayoutKind.Sequential)]
public struct APPBARDATA
{
public uint cbSize;
public IntPtr hWnd;
public uint uCallbackMessage;
public ABE uEdge;
public RECT rc;
public int lParam;
}
[StructLayout(LayoutKind.Sequential)]
public struct RECT
{
public int left;
public int top;
public int right;
public int bottom;
}
}

View File

@ -1,26 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-11.0.0.0" newVersion="11.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NuGet.Frameworks" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.4" newVersion="4.5.0.4" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NuGet.Versioning" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.4" newVersion="4.5.0.4" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="NuGet.Packaging" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.5.0.4" newVersion="4.5.0.4" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@ -1,62 +0,0 @@
using System.ComponentModel;
using System.IO;
namespace KattekerCreator
{
public class ApplicationArguments
{
private string _changeLog;
private string _channel;
private string _outputDir;
private string _programFile;
private string _publishDir;
[DisplayName("Program")]
[Description("Path to the program file")]
public string ProgramFile
{
get => _programFile;
set => SetPropertyIfNotDefault(ref _programFile, Path.GetFullPath(value));
}
[DisplayName("Changelog")]
[Description("Filename of the changelog file")]
public string ChangeLog
{
get => _changeLog;
set => SetPropertyIfNotDefault(ref _changeLog, value);
}
[DisplayName("Channel")]
[Description("Channel of releasing.")]
public string Channel
{
get => _channel;
set => SetPropertyIfNotDefault(ref _channel, value);
}
[DisplayName("Out")]
[Description("Directory for the output")]
public string OutputDir
{
get => _outputDir;
set => SetPropertyIfNotDefault(ref _outputDir, value);
}
[DisplayName("Publish")]
[Description("Path for output from the point of view of the application.")]
public string PublishDir
{
get => _publishDir;
set => SetPropertyIfNotDefault(ref _publishDir, value);
}
private static bool SetPropertyIfNotDefault<T>(ref T field, T value)
{
if (Equals(value, field)) return false;
if (!Equals(field, default(T))) return false;
field = value;
return true;
}
}
}

View File

@ -1,95 +0,0 @@
using System;
using System.Drawing;
using System.IO;
using System.Linq;
using Katteker;
using Semver;
using TsudaKageyu;
using Vestris.ResourceLib;
namespace KattekerCreator
{
public class AssemblyFileInfo
{
private readonly string _company;
private readonly string _copyright;
private readonly string _description;
private readonly string _productName;
public AssemblyFileInfo(string fileName, string tempDir)
{
FileInfo = new FileInfo(fileName);
using (var resourceInfo = new ResourceInfo())
{
resourceInfo.Load(fileName);
if (resourceInfo.ResourceTypes.All(x => x.ResourceType != Kernel32.ResourceTypes.RT_VERSION)) return;
var versionResource = (VersionResource) resourceInfo[Kernel32.ResourceTypes.RT_VERSION].First();
var stringFileInfo = ((StringFileInfo) versionResource[nameof(StringFileInfo)]).Strings
.FirstOrDefault().Value;
AssemblyIconPath = GetAssemblyIcon(fileName, tempDir);
if (stringFileInfo.Strings.ContainsKey("CompanyName"))
_company = stringFileInfo.Strings["CompanyName"].StringValue.TrimEnd('\0');
if (stringFileInfo.Strings.ContainsKey("FileDescription"))
_description = stringFileInfo.Strings["FileDescription"].StringValue.TrimEnd('\0');
if (stringFileInfo.Strings.ContainsKey("LegalCopyright"))
_copyright = stringFileInfo.Strings["LegalCopyright"].StringValue.TrimEnd('\0');
if (stringFileInfo.Strings.ContainsKey("ProductName"))
_productName = stringFileInfo.Strings["ProductName"].StringValue.TrimEnd('\0');
if (!stringFileInfo.Strings.ContainsKey("ProductVersion")) return;
AssemblyVersion =
GetSemanticVersion(stringFileInfo.Strings["ProductVersion"].StringValue.TrimEnd('\0'));
}
}
public string AssemblyIconPath { get; }
public SemVersion AssemblyVersion { get; private set; }
public string Company => _company ?? string.Empty;
public string Copyright => _copyright ?? string.Empty;
public string Description => _description ?? string.Empty;
public FileInfo FileInfo { get; }
public string ProductName => _productName ?? Description;
private static string GetAssemblyIcon(string programFile, string tempDir)
{
var applicationIcon = Path.Combine(tempDir, "application.ico");
if (string.IsNullOrWhiteSpace(programFile)) throw new ApplicationException("Program not set.");
if (!File.Exists(programFile)) throw new ApplicationException("Program not found.");
if (File.Exists(applicationIcon)) File.Delete(applicationIcon);
using (var fileStream = new FileStream(applicationIcon, FileMode.CreateNew))
{
try
{
var ie = new IconExtractor(programFile);
using (var icon = ie.GetIcon(0))
{
icon?.Save(fileStream);
}
}
catch (Exception)
{
using (var icon = Icon.ExtractAssociatedIcon(programFile))
{
icon?.Save(fileStream);
}
}
}
return applicationIcon;
}
private static SemVersion GetSemanticVersion(string productVersion)
{
productVersion = productVersion.Replace(',', '.');
if (SemVersion.TryParse(productVersion, out var semanticVersion))
return semanticVersion?.Change(build: string.Empty);
Version.TryParse(productVersion, out var version);
return SemVersion.Parse(version.ToString(3));
}
}
}

View File

@ -1,51 +0,0 @@
using System;
namespace KattekerCreator.Helper
{
public static class Log
{
private const string Info = "INFO";
private const string Error = "ERROR";
public static void WriteInfoLine(string text)
{
using (var c = new ConsoleWithOtherColor())
{
c.WriteLine($"{Info} [{DateTime.Now:G}] {text}");
}
}
public static void WriteErrorLine(string text)
{
using (var c = new ConsoleWithOtherColor(ConsoleColor.DarkRed))
{
c.WriteLine($"{Error} [{DateTime.Now:G}] {text}");
}
}
}
public class ConsoleWithOtherColor : IDisposable
{
public ConsoleWithOtherColor()
{
}
private readonly ConsoleColor? _defaultColor;
public ConsoleWithOtherColor(ConsoleColor color)
{
_defaultColor = Console.ForegroundColor;
Console.ForegroundColor = color;
}
public void WriteLine(string text)
{
Console.WriteLine(text);
}
public void Dispose()
{
if (_defaultColor != null) Console.ForegroundColor = _defaultColor.Value;
}
}
}

View File

@ -1,166 +0,0 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Reflection;
namespace KattekerCreator.Helper
{
public class SimpleCommandLineParser<TObject> where TObject : new()
{
private TObject _parsedObject;
public SimpleCommandLineParser(IEnumerable<string> args)
{
Parse(args);
}
private IDictionary<string, string[]> Arguments { get; } = new Dictionary<string, string[]>();
public bool Contains(string name) => Arguments.ContainsKey(name);
public TObject GetObject()
{
if (!EqualityComparer<TObject>.Default.Equals(_parsedObject, default(TObject)))
return _parsedObject;
_parsedObject = new TObject();
try
{
LoopProperties(pi =>
{
var displayName = GetDisplayName(pi);
if (displayName == null) return;
if (!Arguments.TryGetValue(displayName.ToLowerInvariant(), out var argument)) return;
if (pi.PropertyType == typeof(bool))
{
pi.SetValue(_parsedObject, true);
return;
}
if (pi.PropertyType.IsArray)
pi.SetValue(_parsedObject, argument);
else
pi.SetValue(_parsedObject, argument.FirstOrDefault());
});
}
catch (Exception e)
{
Log.WriteErrorLine("Error parsing commandline arguments: " + e.Message);
ShowHelp();
}
return _parsedObject;
}
public void ShowHelp(TextWriter textWriter = null)
{
if (textWriter == null) textWriter = Console.Out;
var executable = Assembly.GetExecutingAssembly().GetName().Name + ".exe";
var assemblyTitle = ((AssemblyTitleAttribute) Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyTitleAttribute), false))?.Title ?? executable;
var assemblyDescription = ((AssemblyDescriptionAttribute) Attribute.GetCustomAttribute(Assembly.GetExecutingAssembly(), typeof(AssemblyDescriptionAttribute), false))?.Description;
textWriter.WriteLine();
textWriter.WriteLine(assemblyTitle);
textWriter.WriteLine();
textWriter.WriteLine(assemblyDescription);
textWriter.WriteLine();
textWriter.WriteLine(executable + " <options>");
textWriter.WriteLine();
var dict = new Dictionary<string, string>();
LoopProperties(pi =>
{
var displayName = GetDisplayName(pi);
if (displayName == null) return;
var description = GetDescription(pi);
if (pi.PropertyType == typeof(bool)) description = "(Switch) " + description;
dict.Add(displayName, description);
});
var longestWord = dict.Keys.Max(x => x.Length);
foreach (var kv in dict)
{
textWriter.Write("-" + kv.Key.PadRight(longestWord + 3, ' '));
textWriter.WriteLine(kv.Value);
}
textWriter.WriteLine();
textWriter.WriteLine("A switch will be set to true, if it will called.");
textWriter.WriteLine($"Example: {executable} <Switch>");
textWriter.WriteLine();
textWriter.WriteLine("A parameter will be set.");
textWriter.WriteLine($"Example: {executable} <Key> \"Value\"");
}
/// <summary>
/// Shows the current set options.
/// </summary>
/// <param name="textWriter">If not set Console.Out will be set.</param>
public void ShowProgramArguments(TextWriter textWriter = null)
{
if (textWriter == null) textWriter = Console.Out;
LoopProperties(pi =>
{
var displayName = GetDisplayName(pi) ?? pi.Name;
var value = pi.GetValue(_parsedObject);
textWriter.Write(displayName.PadRight(20, ' '));
if (value == null)
{
textWriter.WriteLine("<NOT SET>");
}
else
{
if (value.GetType().IsArray)
{
var arrayAsString = ((IEnumerable) value)
.Cast<object>()
.Aggregate(string.Empty, (current, x) => current + x?.ToString() + ", ");
textWriter.WriteLine(arrayAsString);
}
else
{
textWriter.WriteLine(value.ToString());
}
}
});
}
private static TAttribute GetAttribute<TAttribute>(MemberInfo memberInfo) where TAttribute : Attribute =>
(TAttribute) Attribute.GetCustomAttribute(memberInfo, typeof(TAttribute));
private static string GetDescription(MemberInfo memberInfo) => GetAttribute<DescriptionAttribute>(memberInfo)?.Description;
private static string GetDisplayName(MemberInfo memberInfo) => GetAttribute<DisplayNameAttribute>(memberInfo)?.DisplayName;
private static void LoopProperties(Action<PropertyInfo> action)
{
var properties = typeof(TObject).GetProperties(BindingFlags.Public | BindingFlags.Instance);
foreach (var propertyInfo in properties)
action.Invoke(propertyInfo);
}
private void Parse(IEnumerable<string> args)
{
var currentName = "";
var values = new List<string>();
foreach (var arg in args)
{
if (arg.StartsWith("-", StringComparison.Ordinal))
{
if (!string.IsNullOrWhiteSpace(currentName))
Arguments[currentName.ToLowerInvariant()] = values.ToArray();
values.Clear();
currentName = arg.Substring(1);
}
else if (string.IsNullOrWhiteSpace(currentName))
{
Arguments[arg] = new string[0];
}
else
{
values.Add(arg);
}
}
if (currentName != "")
Arguments[currentName.ToLowerInvariant()] = values.ToArray();
}
}
}

View File

@ -1,105 +0,0 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Vestris.ResourceLib;
namespace KattekerCreator.Helper
{
public static class Utils
{
public static bool CheckFileExistens(string filePath)
{
if (File.Exists(filePath)) return true;
var file = filePath.Replace(Directory.GetParent(filePath) + "\\", "");
Console.WriteLine("Checking the prerequisites has failed.");
Console.WriteLine($"{file} is missing. Program exits now.");
Console.ReadKey();
return false;
}
public static string CreateTempDirectory()
{
string result;
do
{
result = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp", Environment.UserName,
Path.GetRandomFileName());
} while (Directory.Exists(result));
Directory.CreateDirectory(result);
return result;
}
public static bool IsFilesizeWrong(string filename)
{
var file = new FileInfo(filename);
return !file.Exists || file.Length < 524288;
}
public static void CopyResources(string inFile, string outFile)
{
using (var ri = new ResourceInfo())
{
ri.Load(inFile);
if (ri.ResourceTypes.Any(x => x.ResourceType == Kernel32.ResourceTypes.RT_GROUP_ICON))
{
var groupIcon = ri[Kernel32.ResourceTypes.RT_GROUP_ICON];
var iconDictionary = groupIcon.FirstOrDefault() as IconDirectoryResource;
iconDictionary?.SaveTo(outFile);
}
if (ri.ResourceTypes.Any(x => x.ResourceType == Kernel32.ResourceTypes.RT_VERSION))
{
var versionResource = (VersionResource)ri[Kernel32.ResourceTypes.RT_VERSION].First();
versionResource.Language = 0;
versionResource.SaveTo(outFile);
}
}
}
public static void DeleteTempDir(string tempDir)
{
#if !DEBUG
try
{
Directory.Delete(tempDir, true);
}
catch (Exception)
{
//silently ignore
}
#endif
}
public static IEnumerable<FileInfo> EnumerateFiles(string programFile, IEnumerable<string> userdefinedFileExclusions = null)
{
if (string.IsNullOrWhiteSpace(programFile)) return null;
var directoryName = Path.GetDirectoryName(programFile);
if (directoryName == null) return null;
var files = new DirectoryInfo(directoryName).EnumerateFiles("*.*", SearchOption.AllDirectories);
var filter = FileExclusions(userdefinedFileExclusions).ToArray();
return files.Where(x => !filter.Any(y => x.Name.EndsWith(y, StringComparison.Ordinal)));
}
private static IEnumerable<string> FileExclusions(IEnumerable<string> userdefinedfileExclusions = null)
{
yield return ".pdb";
yield return ".tmp";
yield return ".obj";
yield return ".pch";
yield return ".vshost.exe";
yield return ".vshost.exe.config";
yield return ".vshost.exe.manifest";
yield return "squirrelHelperInfo.json";
yield return "Katteker.config";
if (userdefinedfileExclusions == null) yield break;
foreach (var fileExclusion in userdefinedfileExclusions)
{
yield return fileExclusion;
}
}
}
}

View File

@ -1,103 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="12.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{53D065EB-8818-4F60-9EBE-75705E1BB00D}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>KattekerCreator</RootNamespace>
<AssemblyName>KattekerCreator</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>..\bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>..\bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Drawing" />
<Reference Include="System.IO.Compression" />
<Reference Include="System.Xml" />
<Reference Include="Vestris.ResourceLib, Version=1.6.422.0, Culture=neutral, PublicKeyToken=ec632d8ba5e5750d, processorArchitecture=MSIL">
<HintPath>..\packages\Vestris.ResourceLib.1.6.422\lib\Vestris.ResourceLib.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="ApplicationArguments.cs" />
<Compile Include="AssemblyFileInfo.cs" />
<Compile Include="Helper\Log.cs" />
<Compile Include="IconExtractor\IconExtractor.cs" />
<Compile Include="IconExtractor\IconUtil.cs" />
<Compile Include="IconExtractor\NativeMethods.cs" />
<Compile Include="PathFragments.cs" />
<Compile Include="PhysicalFile.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Helper\SimpleCommandLineParser.cs" />
<Compile Include="Helper\Utils.cs" />
<Compile Include="SetupTmpl.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>SetupTmpl.tt</DependentUpon>
</Compile>
<Compile Include="SetupTmplCode.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<Content Include="contrib\LoadingBar_Icon.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="contrib\uninstall.ico">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="SetupTmpl.tt">
<Generator>TextTemplatingFilePreprocessor</Generator>
<LastGenOutput>SetupTmpl.cs</LastGenOutput>
</Content>
</ItemGroup>
<ItemGroup>
<Service Include="{508349B6-6B84-4DF5-91F0-309BEEBAD82D}" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Katteker\Katteker.csproj">
<Project>{a45e1c59-ba9e-452c-a5e2-50de49d53e92}</Project>
<Name>Katteker</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -1,25 +0,0 @@
using System.IO;
using System.Linq;
namespace KattekerCreator
{
public class PathFragments
{
private readonly string[] _fragments;
public PathFragments(string path)
{
_fragments = path.Split(Path.DirectorySeparatorChar);
}
public int FragmentLength => _fragments.Length;
public override bool Equals(object obj) => string.Equals(ToString(), obj?.ToString());
public override int GetHashCode() => (_fragments != null ? _fragments.GetHashCode() : 0);
public override string ToString() => string.Join(Path.DirectorySeparatorChar.ToString(), _fragments.Take(_fragments.Length - 1));
protected bool Equals(PathFragments other) => Equals(_fragments, other._fragments);
}
}

View File

@ -1,14 +0,0 @@
namespace KattekerCreator
{
public class PhysicalFile
{
public PhysicalFile(string source, string target)
{
Source = source;
Target = target;
}
public string Source { get; }
public string Target { get; }
}
}

View File

@ -1,199 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using Katteker;
using KattekerCreator.Helper;
namespace KattekerCreator
{
public class Program
{
private const string _executable = @"C:\Program Files (x86)\NSIS\makensis.exe";
private readonly string _baseDirectory = AppDomain.CurrentDomain.BaseDirectory;
private ApplicationArguments _appArguments;
private AssemblyFileInfo _assemblyFileInfo;
private string _tempDir;
private Releases _releases;
private static int Main(string[] args)
{
var program = new Program();
try
{
return program.Run(args);
}
catch (Exception ex)
{
Log.WriteErrorLine(ex.Message);
if (ex.InnerException != null)
Log.WriteErrorLine(ex.InnerException.Message);
#if DEBUG
throw;
#else
return -1;
#endif
}
}
private int Run(string[] args)
{
//Parse App-Arguments
var parser = new SimpleCommandLineParser<ApplicationArguments>(args);
if (args.Length == 0)
{
parser.ShowHelp();
return 1924;
}
_appArguments = parser.GetObject();
//Create tempdir
_tempDir = Utils.CreateTempDirectory();
_releases = new Releases(_appArguments.OutputDir);
parser.ShowProgramArguments();
//Modify AppStub
var appStubFile = ModifyAppStub();
//Acquire infos from Executable.
_assemblyFileInfo = new AssemblyFileInfo(_appArguments.ProgramFile, _tempDir);
var configFile = CreateConfigFile();
//Generate NSIS-Script
var additionalFiles = new[]
{
new PhysicalFile(appStubFile, Path.GetFileName(_appArguments.ProgramFile)),
new PhysicalFile(configFile, Path.Combine($"app-{_assemblyFileInfo.AssemblyVersion}", Path.GetFileName(configFile)))
};
var templateFile = GenerateNsisTemplate(additionalFiles);
//Start makensis.exe
var setupFilePath = CompileSetupScript(templateFile);
//Copy to Output-Folder
CopyToOutputFolder(setupFilePath);
//Create/Modify RELEASE File
var releaseEntry = AddPackageToReleaseFile(setupFilePath);
//Copy installer as setup.exe
CopyAsSetup(setupFilePath, releaseEntry);
return 0;
}
private void CopyAsSetup(string setupFilePath, ReleaseEntry releaseEntry)
{
if (!_releases.IsLatestEntry(releaseEntry)) return;
var target = Path.Combine(_appArguments.OutputDir, Constants.SetupFile);
File.Delete(target);
File.Copy(setupFilePath, target);
}
private ReleaseEntry AddPackageToReleaseFile(string setupFilePath)
{
try
{
var result = _releases.Add(setupFilePath, _assemblyFileInfo.AssemblyVersion);
_releases.WriteReleaseFile();
return result;
}
catch (Exception e)
{
Log.WriteErrorLine(e.Message);
throw;
}
}
private void CopyToOutputFolder(string setupFilePath)
{
if (setupFilePath == null) throw new ArgumentNullException(nameof(setupFilePath));
var setupFile = Path.GetFileName(setupFilePath);
if (string.IsNullOrEmpty(setupFile)) throw new ArgumentException();
if (!File.Exists(setupFilePath)) throw new FileNotFoundException(setupFile);
if (!Directory.Exists(_appArguments.OutputDir)) Directory.CreateDirectory(_appArguments.OutputDir);
if (!string.IsNullOrEmpty(_appArguments.ChangeLog))
{
var changeLogPath = Path.Combine(Path.GetDirectoryName(_appArguments.ProgramFile), _appArguments.ChangeLog);
if (!File.Exists(changeLogPath)) throw new FileNotFoundException(changeLogPath);
File.Copy(changeLogPath, Path.Combine(_appArguments.OutputDir, _appArguments.ChangeLog), true);
}
File.Copy(setupFilePath, Path.Combine(_appArguments.OutputDir, setupFile), true);
}
private static string CompileSetupScript(string templateFile)
{
if (!File.Exists(_executable)) throw new FileNotFoundException("NSIS not installed properly.");
int exitcode;
using (var p = new Process())
{
p.StartInfo = new ProcessStartInfo
{
FileName = _executable,
Arguments = $"\"{templateFile}\"",
UseShellExecute = false
};
var sw = Stopwatch.StartNew();
p.Start();
p.WaitForExit();
exitcode = p.ExitCode;
Log.WriteInfoLine($"{Path.GetFileName(_executable)} has exited with Exitcode: {exitcode} (Took: {sw.ElapsedMilliseconds}ms)");
}
if (exitcode != 0) throw new Exception($"{Path.GetFileName(_executable)} has exited with Exitcode: {exitcode}");
return Path.ChangeExtension(templateFile, "exe");
}
private string CreateConfigFile()
{
var pathToFile = Path.Combine(_tempDir, Constants.KattekerConfig);
var kattekerConfig = new KattekerConfig
{
PublishDir = _appArguments.PublishDir ?? _appArguments.OutputDir,
Changelog = _appArguments.ChangeLog
};
kattekerConfig.WriteToFile(pathToFile);
return pathToFile;
}
private string ModifyAppStub()
{
var baseFile = new FileInfo(Path.Combine(_baseDirectory, Constants.ExecutionStub));
var targetFile = baseFile.CopyTo(Path.Combine(_tempDir, Constants.ExecutionStub));
Utils.CopyResources(_appArguments.ProgramFile, targetFile.FullName);
return targetFile.FullName;
}
private static string GenerateFilename(string name, string version, string extension, bool isDelta = false) => $"{name}-{version}-{(isDelta ? "delta" : "full")}.{extension}";
private string GenerateNsisTemplate(IEnumerable<PhysicalFile> additionalFiles)
{
try
{
var outFile = Path.Combine(_tempDir, GenerateFilename(_assemblyFileInfo.ProductName, _assemblyFileInfo.AssemblyVersion.ToString(), "nsi"));
var setupTmpl = new SetupTmpl
{
Executable = _assemblyFileInfo.FileInfo.Name,
AppName = _assemblyFileInfo.ProductName,
CompanyName = _assemblyFileInfo.Company,
Description = _assemblyFileInfo.Description,
IconPath = _assemblyFileInfo.AssemblyIconPath,
Version = _assemblyFileInfo.AssemblyVersion,
HelpUrl = "http://example.org", //Not used at the moment.
UserInterface = Path.Combine(_baseDirectory, "contrib", "LoadingBar_Icon.exe"),
UninstallIcon = Path.Combine(_baseDirectory, "contrib", "uninstall.ico"),
OutFile = Path.GetFileName(Path.ChangeExtension(outFile, "exe")),
ReleaseChannel = _appArguments.Channel
};
var path = Path.GetDirectoryName(_appArguments.ProgramFile) ?? string.Empty;
setupTmpl.Files.AddRange(additionalFiles);
var files = Utils.EnumerateFiles(_appArguments.ProgramFile).ToArray();
setupTmpl.InstallSize = (long) Math.Floor(files.Sum(x => x.Length) / 1024f);
setupTmpl.Files.AddRange(files.Select(x => new PhysicalFile(x.FullName, x.FullName.Replace(path, $"app-{_assemblyFileInfo.AssemblyVersion}"))));
var transformText = setupTmpl.TransformText();
File.WriteAllText(outFile, transformText);
return outFile;
}
catch (Exception e)
{
Log.WriteErrorLine(e.Message);
throw;
}
}
}
}

View File

@ -1,36 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("KattekerCreator")]
[assembly: AssemblyDescription("Creates Installation and Update packages.")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Holger Börchers")]
[assembly: AssemblyProduct("KattekerCreator")]
[assembly: AssemblyCopyright("Copyright © Holger Börchers")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf "false" werden die Typen in dieser Assembly unsichtbar
// für COM-Komponenten. Wenn Sie auf einen Typ in dieser Assembly von
// COM zugreifen müssen, legen Sie das ComVisible-Attribut für diesen Typ auf "true" fest.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("ef6af08f-1e5f-44c5-9be8-973b130f8086")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@ -1,103 +0,0 @@
!define APPNAME "Shutdown8"
!define EXECUTABLE "Shutdown8.exe"
!define COMPANYNAME "Bandisoft.com"
!define DESCRIPTION "NoDescription"
!define VERSION 1.8.0
!define HELPURL https://srv-lsimctrl01.enercon.de
!define INSTALLSIZE 155573
!define ISMANAGED 1
; exampleCmd: makensis.exe /DVERSION=1.0.0.5 /DNAME=WpfApp1 Setup.nsi
Name "${APPNAME}"
OutFile "${APPNAME}-${VERSION}.exe"
InstallDir "$LOCALAPPDATA\${APPNAME}"
RequestExecutionLevel user
SetCompressor /SOLID lzma
SilentUnInstall silent
; Subcaption 3 " "
XPStyle on
AutoCloseWindow true
ChangeUI all "${NSISDIR}\Contrib\UIs\sdbarker_tiny.exe"
Icon "${NSISDIR}\Contrib\Graphics\Icons\nsis3-install.ico"
UninstallIcon "${NSISDIR}\Contrib\Graphics\Icons\nsis3-uninstall.ico"
ShowInstDetails nevershow
ShowUninstDetails nevershow
BrandingText "${COMPANYNAME}"
;--------------------------------
; The stuff to install
Section "install" ;No components page, name is not important
DetailPrint 'Installing ${APPNAME}. Please wait...'
SetShellVarContext current
SetDetailsPrint None
SetOutPath $INSTDIR\app-${VERSION}
; Put file there
File /r /x *.pdb /x *.obj /x *.pch /x *.vshost.exe /x *.vshost.exe.* Release\*.*
SetOutPath $INSTDIR
File "/oname=${Executable}" AppStub.exe
File Rabbit.Shared.dll
WriteINIStr $INSTDIR\app.ini Main Executable "${EXECUTABLE}"
WriteINIStr $INSTDIR\app.ini Main AppName "${APPNAME}"
WriteINIStr $INSTDIR\app.ini Main IsManaged ${ISMANAGED}
WriteUninstaller "$INSTDIR\uninstall.exe"
; Desktop
CreateShortCut "$DESKTOP\${APPNAME}.lnk" "$INSTDIR\${Executable}"
# Start Menu
CreateDirectory "$SMPROGRAMS\${COMPANYNAME}"
CreateShortCut "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk" "$INSTDIR\${Executable}"
# Update pinned Taskbar
IfFileExists "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\${APPNAME}.lnk" 0 +2
CreateShortCut "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\${APPNAME}.lnk" "$INSTDIR\${Executable}"
SetOutPath $INSTDIR\app-${VERSION}
StrCpy $0 ${EXECUTABLE} -4
IfFileExists "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\$0.lnk" 0 +2
CreateShortCut "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\$0.lnk" "$INSTDIR\app-${VERSION}\${EXECUTABLE}"
# Registry information for add/remove programs
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayName" "${APPNAME}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "UninstallString" "$\"$INSTDIR\uninstall.exe$\""
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "QuietUninstallString" "$\"$INSTDIR\uninstall.exe$\" /S"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "InstallLocation" "$\"$INSTDIR$\""
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayIcon" "$\"$INSTDIR\app-${VERSION}\${EXECUTABLE}$\""
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "Publisher" "${COMPANYNAME}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "HelpLink" "${HELPURL}"
WriteRegStr HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "DisplayVersion" "${VERSION}"
# There is no option for modifying or repairing the install
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoModify" 1
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "NoRepair" 1
# Set the INSTALLSIZE constant (!defined at the top of this script) so Add/Remove Programs can accurately report the size
WriteRegDWORD HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}" "EstimatedSize" ${INSTALLSIZE}
SectionEnd ; end the section
Function .onInstSuccess
IfSilent +2
Exec '"$INSTDIR\${Executable}"'
FunctionEnd
Section "uninstall"
DetailPrint 'Please wait...'
SetShellVarContext current
SetDetailsPrint None
SetAutoClose true
# Remove Start Menu launcher
Delete "$SMPROGRAMS\${COMPANYNAME}\${APPNAME}.lnk"
Delete "$DESKTOP\${APPNAME}.lnk"
StrCpy $0 ${EXECUTABLE} -4
Delete "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\${APPNAME}.lnk"
Delete "$APPDATA\Microsoft\Internet Explorer\Quick Launch\User Pinned\TaskBar\$0.lnk"
# Try to remove the Start Menu folder - this will only happen if it is empty
RMDir "$SMPROGRAMS\${COMPANYNAME}"
# Always delete uninstaller as the last action
delete $INSTDIR\uninstall.exe
# Try to remove the install directory - this will only happen if it is empty
RMDir /r /REBOOTOK $INSTDIR
# Remove uninstaller information from the registry
DeleteRegKey HKCU "Software\Microsoft\Windows\CurrentVersion\Uninstall\${APPNAME}"
sectionEnd

View File

@ -1,51 +0,0 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Katteker;
using Semver;
namespace KattekerCreator
{
public partial class SetupTmpl
{
public string AppName
{
get => string.IsNullOrWhiteSpace(ReleaseChannel) ? _appName : $"{_appName}_{ReleaseChannel}";
set => _appName = value;
}
public string Executable { get; set; }
public string CompanyName { get; set; }
public string Description { get; set; }
public SemVersion Version { get; set; }
public Version LegacyVersion => Version.ToSystemVersion();
public string HelpUrl { get; set; }
public long InstallSize { get; set; }
public bool IsManaged { get; set; }
public string IconPath { get; set; }
public string SourcePath { get; set; } = string.Empty;
public List<PhysicalFile> Files { get; set; } = new List<PhysicalFile>();
private IEnumerable<string> Directories => DirectoriesToCreate();
public string UserInterface { get; set; }
public string OutFile { get; set; }
public string UninstallIcon { get; set; }
public string ReleaseChannel { get; set; }
private readonly List<PathFragments> _directoriesList = new List<PathFragments>();
private string _appName;
private IEnumerable<string> DirectoriesToCreate()
{
foreach (var physicalFile in Files)
{
var dirSplit = new PathFragments(physicalFile.Target);
if (dirSplit.FragmentLength > 1 && !_directoriesList.Contains(dirSplit))
{
_directoriesList.Add(dirSplit);
}
}
return _directoriesList.Select(x => x.ToString());
}
}
}

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Vestris.ResourceLib" version="1.6.422" targetFramework="net45" />
</packages>

View File

@ -1,19 +0,0 @@
<?xml version="1.0"?>
<package >
<metadata>
<id>$id$</id>
<version>$version$</version>
<title>$id$</title>
<authors>$author$</authors>
<owners>$author$</owners>
<requireLicenseAcceptance>false</requireLicenseAcceptance>
<description>$description$</description>
<copyright>$copyright$</copyright>
</metadata>
<files>
<file src="bin\$configuration$\*.dll" target="lib\net45" />
<file src="bin\$configuration$\*.config" target="lib\net45" exclude="bin\$configuration$\*.vshost.exe.config" />
<file src="bin\$configuration$\*.exe" target="lib\net45" exclude="bin\$configuration$\*.vshost.exe" />
<file src="..\packages\squirrel.windows.0.99.1.1\tools\Squirrel.exe" target="lib\net45" />
</files>
</package>

View File

@ -1,9 +0,0 @@
<Application x:Class="Example.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:Example"
StartupUri="MainWindow.xaml">
<Application.Resources>
</Application.Resources>
</Application>

View File

@ -1,11 +0,0 @@
using System.Windows;
namespace Example
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
}
}

View File

@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{DE9CFDEB-40B8-447D-9959-31BA78512CED}</ProjectGuid>
<OutputType>WinExe</OutputType>
<RootNamespace>Example</RootNamespace>
<AssemblyName>Example</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<WarningLevel>4</WarningLevel>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<Prefer32Bit>false</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>x64</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>nsis3-install.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup>
<StartupObject>Example.App</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Data" />
<Reference Include="System.Xml" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xaml">
<RequiredTargetFramework>4.0</RequiredTargetFramework>
</Reference>
<Reference Include="WindowsBase" />
<Reference Include="PresentationCore" />
<Reference Include="PresentationFramework" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Include="App.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</ApplicationDefinition>
<Page Include="MainWindow.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
<Compile Include="MainWindow.xaml.cs">
<DependentUpon>MainWindow.xaml</DependentUpon>
<SubType>Code</SubType>
</Compile>
</ItemGroup>
<ItemGroup>
<Compile Include="Properties\AssemblyInfo.cs">
<SubType>Code</SubType>
</Compile>
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
<DesignTime>True</DesignTime>
<DependentUpon>Resources.resx</DependentUpon>
</Compile>
<Compile Include="Properties\Settings.Designer.cs">
<AutoGen>True</AutoGen>
<DependentUpon>Settings.settings</DependentUpon>
<DesignTimeSharedInput>True</DesignTimeSharedInput>
</Compile>
<EmbeddedResource Include="Properties\Resources.resx">
<Generator>ResXFileCodeGenerator</Generator>
<LastGenOutput>Resources.Designer.cs</LastGenOutput>
</EmbeddedResource>
<None Include="changelog.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="Properties\Settings.settings">
<Generator>SettingsSingleFileGenerator</Generator>
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
</None>
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Katteker.Gui\Katteker.Gui.csproj">
<Project>{07e2de31-80a0-43da-b307-1ca47cd930a1}</Project>
<Name>Katteker.Gui</Name>
</ProjectReference>
<ProjectReference Include="..\Katteker\Katteker.csproj">
<Project>{a45e1c59-ba9e-452c-a5e2-50de49d53e92}</Project>
<Name>Katteker</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<Resource Include="nsis3-install.ico" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,18 +0,0 @@
<Window
x:Class="Example.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Example"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
Title="MainWindow"
Width="800"
Height="450"
Background="Chartreuse"
ContentRendered="MainWindow_OnContentRendered"
mc:Ignorable="d">
<StackPanel>
<Button Margin="10" FontSize="24" Content="Update" Click="ButtonBase_OnClick"></Button>
<TextBlock Text=":-(" FontSize="60" HorizontalAlignment="Center" />
</StackPanel>
</Window>

View File

@ -1,32 +0,0 @@
using System;
using System.Reflection;
using System.Windows;
using Katteker.Gui;
namespace Example
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
var version = GetType().Assembly.GetName().Version.ToString();
var a = Assembly.GetExecutingAssembly();
a.ManifestModule.GetPEKind(out var peKind, out var machine);
Title = $"{version} | {peKind} | {machine}";
}
private async void MainWindow_OnContentRendered(object sender, EventArgs e)
{
await Wrapper.CheckForUpdateAsync(true).ConfigureAwait(false);
}
private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
await Wrapper.CheckForUpdateAsync().ConfigureAwait(false);
}
}
}

View File

@ -1,53 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
using System.Windows;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("Example")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Enercon GmbH")]
[assembly: AssemblyProduct("Example")]
[assembly: AssemblyCopyright("Copyright © Enercon GmbH 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
//In order to begin building localizable applications, set
//<UICulture>CultureYouAreCodingWith</UICulture> in your .csproj file
//inside a <PropertyGroup>. For example, if you are using US english
//in your source files, set the <UICulture> to en-US. Then uncomment
//the NeutralResourceLanguage attribute below. Update the "en-US" in
//the line below to match the UICulture setting in the project file.
//[assembly: NeutralResourcesLanguage("en-US", UltimateResourceFallbackLocation.Satellite)]
[assembly: ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// 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("1.0.48")]
[assembly: AssemblyFileVersion("1.0.48")]

View File

@ -1,63 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Example.Properties {
using System;
/// <summary>
/// A strongly-typed resource class, for looking up localized strings, etc.
/// </summary>
// This class was auto-generated by the StronglyTypedResourceBuilder
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
private static global::System.Resources.ResourceManager resourceMan;
private static global::System.Globalization.CultureInfo resourceCulture;
[global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")]
internal Resources() {
}
/// <summary>
/// Returns the cached ResourceManager instance used by this class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Example.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;
}
}
/// <summary>
/// Overrides the current thread's CurrentUICulture property for all
/// resource lookups using this strongly typed resource class.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
internal static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
}
}

View File

@ -1,117 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>

View File

@ -1,26 +0,0 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
// Runtime Version:4.0.30319.42000
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Example.Properties {
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.6.0.0")]
internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase {
private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings())));
public static Settings Default {
get {
return defaultInstance;
}
}
}
}

View File

@ -1,7 +0,0 @@
<?xml version='1.0' encoding='utf-8'?>
<SettingsFile xmlns="uri:settings" CurrentProfile="(Default)">
<Profiles>
<Profile Name="(Default)" />
</Profiles>
<Settings />
</SettingsFile>

16
ExampleCore/App.xaml Normal file
View File

@ -0,0 +1,16 @@
<dryioc:PrismApplication
x:Class="ExampleCore.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:dryioc="http://prismlibrary.com/"
xmlns:ui="http://schemas.modernwpf.com/2019">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ui:ThemeResources />
<ui:XamlControlsResources />
<!-- Other merged dictionaries here -->
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</dryioc:PrismApplication>

25
ExampleCore/App.xaml.cs Normal file
View File

@ -0,0 +1,25 @@
using Prism.Ioc;
using System.Windows;
using System.Windows.Forms;
namespace ExampleCore
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App
{
public App()
{
System.Windows.Forms.Application.SetHighDpiMode(HighDpiMode.SystemAware);
System.Windows.Forms.Application.EnableVisualStyles();
System.Windows.Forms.Application.SetCompatibleTextRenderingDefault(false);
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
//nothing
}
protected override Window CreateShell() => Container.Resolve<MainWindow>();
}
}

View File

@ -0,0 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<UseWPF>true</UseWPF>
<UseWindowsForms>true</UseWindowsForms>
<ApplicationIcon>nsis3-install.ico</ApplicationIcon>
<Version>1.3.14</Version>
<Nullable>enable</Nullable>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="nsis3-install.ico" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Emoji.Wpf" Version="0.3.0" />
<PackageReference Include="ModernWpfUI" Version="0.9.3" />
<PackageReference Include="Prism.Core" Version="8.0.0.1909" />
<PackageReference Include="Prism.DryIoc" Version="8.0.0.1909" />
<PackageReference Include="Prism.Wpf" Version="8.0.0.1909" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\src\Katteker\Katteker.csproj" />
</ItemGroup>
<ItemGroup>
<Resource Include="nsis3-install.ico" />
</ItemGroup>
<ItemGroup>
<ApplicationDefinition Update="App.xaml">
<SubType>Designer</SubType>
</ApplicationDefinition>
</ItemGroup>
<ItemGroup>
<None Update="changelog.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<Page Update="MainWindow.xaml">
<SubType>Designer</SubType>
</Page>
</ItemGroup>
</Project>

View File

@ -0,0 +1 @@
{"Publish":"\\\\srv-lsimctrl01\\e$\\Squirrel\\TT","Changelog":null,"Channel":" Dev"}

View File

@ -0,0 +1,62 @@
<Window
x:Class="ExampleCore.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:b="http://schemas.microsoft.com/xaml/behaviors"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:emoji="clr-namespace:Emoji.Wpf;assembly=Emoji.Wpf"
xmlns:local="clr-namespace:ExampleCore"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:prism="http://prismlibrary.com/"
xmlns:system="clr-namespace:System;assembly=System.Runtime"
xmlns:ui="http://schemas.modernwpf.com/2019"
Title="{x:Static local:MainWindowViewModel.WindowTitle}"
Width="800"
Height="500"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}"
prism:ViewModelLocator.AutoWireViewModel="True"
ui:WindowHelper.UseModernWindowStyle="True"
TextOptions.TextFormattingMode="Display"
TextOptions.TextRenderingMode="Auto"
mc:Ignorable="d">
<Window.Resources>
<system:Boolean x:Key="True">True</system:Boolean>
<system:Boolean x:Key="False">False</system:Boolean>
</Window.Resources>
<b:Interaction.Triggers>
<b:EventTrigger EventName="ContentRendered">
<b:InvokeCommandAction Command="{Binding UpdateCommand}" CommandParameter="{StaticResource True}" />
</b:EventTrigger>
</b:Interaction.Triggers>
<ScrollViewer>
<StackPanel>
<StackPanel.Resources>
<Style BasedOn="{StaticResource {x:Type Button}}" TargetType="Button">
<Setter Property="Height" Value="45" />
<Setter Property="Margin" Value="10" />
<Setter Property="FontSize" Value="24" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
</Style>
</StackPanel.Resources>
<Button
Command="{Binding UpdateCommand}"
CommandParameter="{StaticResource False}"
Content="Update" />
<Button Command="{Binding OpenFolderDialogCommand}" Content="Open Folder Dialog" />
<Button Command="{Binding OpenFileDialogCommand}" Content="Open File Dialog" />
<emoji:TextBlock
Margin="20"
HorizontalAlignment="Center"
FontSize="60"
Text="😂" />
<GroupBox Margin="10" Header="Command line parameters">
<TextBlock
Background="WhiteSmoke"
FontFamily="Consolas"
Text="{Binding CommandLineParameters}"
TextWrapping="Wrap" />
</GroupBox>
</StackPanel>
</ScrollViewer>
</Window>

View File

@ -0,0 +1,13 @@
namespace ExampleCore
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow
{
public MainWindow()
{
InitializeComponent();
}
}
}

View File

@ -0,0 +1,86 @@
using System;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Windows.Input;
using Katteker;
using Prism.Commands;
using Prism.Mvvm;
namespace ExampleCore
{
public class MainWindowViewModel : BindableBase
{
private readonly UpdateManager _updateManager;
public static string WindowTitle { get; } = "Example Core " + Assembly.GetExecutingAssembly().GetName().Version?.ToString(3);
public MainWindowViewModel()
{
UpdateManager.TryCreate(out _updateManager);
UpdateCommand = new DelegateCommand<bool?>(async x => await UpdateAsync(x.GetValueOrDefault()).ConfigureAwait(false));
OpenFolderDialogCommand = new DelegateCommand(OpenFolder);
OpenFileDialogCommand = new DelegateCommand(OpenFile);
}
private static void OpenFile()
{
using var openFile = new OpenFileDialog();
if (openFile.ShowDialog() == DialogResult.OK)
{
MessageBox.Show(openFile.FileName, WindowTitle);
}
}
private static void OpenFolder()
{
using var folderBrowser = new FolderBrowserDialog();
if (folderBrowser.ShowDialog() == DialogResult.OK)
{
MessageBox.Show(folderBrowser.SelectedPath, WindowTitle);
}
}
private async Task UpdateAsync(bool startup)
{
try
{
var updates = await _updateManager.CheckForUpdatesAsync().ConfigureAwait(false);
if (updates.Any())
{
var dialogResult = MessageBox.Show("Update available, update now?", WindowTitle,
MessageBoxButtons.YesNo,
MessageBoxIcon.Information);
if (dialogResult == DialogResult.Yes && await _updateManager.UpdateAppAsync().ConfigureAwait(false))
{
dialogResult = MessageBox.Show("The update is ready to install. Do you want to install it now?",
WindowTitle,
MessageBoxButtons.YesNo, MessageBoxIcon.Question);
if (dialogResult == DialogResult.Yes) System.Windows.Application.Current.Shutdown();
}
}
else if (!startup)
{
MessageBox.Show("No Update available.", WindowTitle, MessageBoxButtons.OK,
MessageBoxIcon.Information);
}
}
catch (Exception e)
{
if (startup)
{
MessageBox.Show(e.Message, WindowTitle, MessageBoxButtons.OK, MessageBoxIcon.Error);
}
}
}
public ICommand UpdateCommand { get; }
public ICommand OpenFolderDialogCommand { get; }
public ICommand OpenFileDialogCommand { get; }
public string CommandLineParameters => Environment.CommandLine;
}
}

View File

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
https://go.microsoft.com/fwlink/?LinkID=208121.
-->
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<PublishProtocol>FileSystem</PublishProtocol>
<Configuration>Release</Configuration>
<Platform>Any CPU</Platform>
<TargetFramework>net5.0-windows10.0.18362.0</TargetFramework>
<PublishDir>..\publish\</PublishDir>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
<SelfContained>true</SelfContained>
<_IsPortable>false</_IsPortable>
<PublishSingleFile>True</PublishSingleFile>
<PublishReadyToRun>True</PublishReadyToRun>
<PublishTrimmed>False</PublishTrimmed>
</PropertyGroup>
</Project>

View File

@ -0,0 +1,8 @@
{
"profiles": {
"ExampleCore": {
"commandName": "Project",
"commandLineArgs": "Dangerous Mouse"
}
}
}

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

@ -1,4 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="CommonMark.NET" version="0.15.1" targetFramework="net45" />
</packages>

View File

@ -1,17 +1,26 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2036
# Visual Studio Version 16
VisualStudioVersion = 16.0.28606.126
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KattekerCreator", "Creator\KattekerCreator.csproj", "{53D065EB-8818-4F60-9EBE-75705E1BB00D}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Katteker.UserInterface", "src\Katteker.Gui\Katteker.UserInterface.csproj", "{07E2DE31-80A0-43DA-B307-1CA47CD930A1}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Katteker", "Katteker\Katteker.csproj", "{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Katteker.Test", "src\Katteker.Test\Katteker.Test.csproj", "{76E9E47E-C810-4C13-BAC3-1F53CF4BCB92}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AppStub", "AppStub\AppStub.csproj", "{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "KattekerCreator", "src\KattekerCreator\KattekerCreator.csproj", "{0B728D86-CAB8-4259-925B-3CB37BE111ED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Example", "Example\Example.csproj", "{DE9CFDEB-40B8-447D-9959-31BA78512CED}"
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{148E4735-4CF1-4A24-B689-063DCD6B9A5B}"
ProjectSection(SolutionItems) = preProject
.editorconfig = .editorconfig
EndProjectSection
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Katteker.Gui", "Katteker.Gui\Katteker.Gui.csproj", "{07E2DE31-80A0-43DA-B307-1CA47CD930A1}"
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Katteker", "src\Katteker\Katteker.csproj", "{4CD50166-C3AB-4CC4-9694-951A3F33ADDB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExampleCore", "ExampleCore\ExampleCore.csproj", "{39AF52DA-AD79-46DD-87FC-A19D13CEB2AB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IconExtractor", "src\IconExtractor\IconExtractor.csproj", "{C65A4554-4EBB-4CEE-A73F-DBC3B07F001B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Katteker.Changelog", "src\Katteker.Changelog\Katteker.Changelog.csproj", "{7004EBBD-87AA-49E6-BF1C-FF933BA028FE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@ -19,26 +28,34 @@ Global
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{53D065EB-8818-4F60-9EBE-75705E1BB00D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{53D065EB-8818-4F60-9EBE-75705E1BB00D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{53D065EB-8818-4F60-9EBE-75705E1BB00D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{53D065EB-8818-4F60-9EBE-75705E1BB00D}.Release|Any CPU.Build.0 = Release|Any CPU
{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}.Release|Any CPU.Build.0 = Release|Any CPU
{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E746AE0F-BEEA-4C18-9ED8-2E708ED00A5B}.Release|Any CPU.Build.0 = Release|Any CPU
{DE9CFDEB-40B8-447D-9959-31BA78512CED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DE9CFDEB-40B8-447D-9959-31BA78512CED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DE9CFDEB-40B8-447D-9959-31BA78512CED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DE9CFDEB-40B8-447D-9959-31BA78512CED}.Release|Any CPU.Build.0 = Release|Any CPU
{07E2DE31-80A0-43DA-B307-1CA47CD930A1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07E2DE31-80A0-43DA-B307-1CA47CD930A1}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07E2DE31-80A0-43DA-B307-1CA47CD930A1}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07E2DE31-80A0-43DA-B307-1CA47CD930A1}.Release|Any CPU.Build.0 = Release|Any CPU
{76E9E47E-C810-4C13-BAC3-1F53CF4BCB92}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{76E9E47E-C810-4C13-BAC3-1F53CF4BCB92}.Debug|Any CPU.Build.0 = Debug|Any CPU
{76E9E47E-C810-4C13-BAC3-1F53CF4BCB92}.Release|Any CPU.ActiveCfg = Release|Any CPU
{76E9E47E-C810-4C13-BAC3-1F53CF4BCB92}.Release|Any CPU.Build.0 = Release|Any CPU
{0B728D86-CAB8-4259-925B-3CB37BE111ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B728D86-CAB8-4259-925B-3CB37BE111ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B728D86-CAB8-4259-925B-3CB37BE111ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B728D86-CAB8-4259-925B-3CB37BE111ED}.Release|Any CPU.Build.0 = Release|Any CPU
{4CD50166-C3AB-4CC4-9694-951A3F33ADDB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{4CD50166-C3AB-4CC4-9694-951A3F33ADDB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{4CD50166-C3AB-4CC4-9694-951A3F33ADDB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{4CD50166-C3AB-4CC4-9694-951A3F33ADDB}.Release|Any CPU.Build.0 = Release|Any CPU
{39AF52DA-AD79-46DD-87FC-A19D13CEB2AB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{39AF52DA-AD79-46DD-87FC-A19D13CEB2AB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{39AF52DA-AD79-46DD-87FC-A19D13CEB2AB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{39AF52DA-AD79-46DD-87FC-A19D13CEB2AB}.Release|Any CPU.Build.0 = Release|Any CPU
{C65A4554-4EBB-4CEE-A73F-DBC3B07F001B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{C65A4554-4EBB-4CEE-A73F-DBC3B07F001B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{C65A4554-4EBB-4CEE-A73F-DBC3B07F001B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{C65A4554-4EBB-4CEE-A73F-DBC3B07F001B}.Release|Any CPU.Build.0 = Release|Any CPU
{7004EBBD-87AA-49E6-BF1C-FF933BA028FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7004EBBD-87AA-49E6-BF1C-FF933BA028FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7004EBBD-87AA-49E6-BF1C-FF933BA028FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7004EBBD-87AA-49E6-BF1C-FF933BA028FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE

View File

@ -1,68 +0,0 @@
using System;
using System.IO;
using System.Net;
using System.Threading.Tasks;
namespace Katteker
{
public static class ChangelogHelper
{
public static string ChangelogAsHtml(this string text, string extension)
{
string result;
switch (extension)
{
case ".txt":
var plainText = WebUtility.HtmlEncode(text);
result = plainText.Replace(Environment.NewLine, "<br />");
break;
case ".md":
result = new MarkdownSharp.Markdown().Transform(text);
break;
default:
result = text;
break;
}
return result;
}
public static async Task<string> LoadChangelogAsync(string filename, string path)
{
if (!string.IsNullOrEmpty(filename) || !string.IsNullOrEmpty(path))
{
if (!path.EndsWith("/", StringComparison.Ordinal))
path += "/";
var webReq = WebRequest.Create(path + filename);
try
{
using (var response = await webReq.GetResponseAsync().ConfigureAwait(false))
using (var sr = new StreamReader(response.GetResponseStream()))
{
return await sr.ReadToEndAsync().ConfigureAwait(false);
}
}
catch (Exception)
{
try
{
var changelogFilename = Path.GetFileName(filename);
if (changelogFilename == null) return null;
var currentChangelogPath = Path.Combine(Environment.CurrentDirectory, changelogFilename);
if (File.Exists(currentChangelogPath))
{
return File.ReadAllText(currentChangelogPath);
}
}
catch (Exception)
{
// ignore;
}
}
}
return null;
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,537 +0,0 @@
using System;
#if !NETSTANDARD
using System.Globalization;
using System.Runtime.Serialization;
using System.Security.Permissions;
#endif
using System.Text.RegularExpressions;
namespace Semver
{
/// <summary>
/// A semantic version implementation.
/// Conforms to v2.0.0 of http://semver.org/
/// </summary>
#if NETSTANDARD
public sealed class SemVersion : IComparable<SemVersion>, IComparable
#else
[Serializable]
public sealed class SemVersion : IComparable<SemVersion>, IComparable, ISerializable
#endif
{
static Regex parseEx =
new Regex(@"^(?<major>\d+)" +
@"(\.(?<minor>\d+))?" +
@"(\.(?<patch>\d+))?" +
@"(\-(?<pre>[0-9A-Za-z\-\.]+))?" +
@"(\+(?<build>[0-9A-Za-z\-\.]+))?$",
#if NETSTANDARD
RegexOptions.CultureInvariant | RegexOptions.ExplicitCapture);
#else
RegexOptions.CultureInvariant | RegexOptions.Compiled | RegexOptions.ExplicitCapture);
#endif
#if !NETSTANDARD
/// <summary>
/// Initializes a new instance of the <see cref="SemVersion" /> class.
/// </summary>
/// <param name="info"></param>
/// <param name="context"></param>
/// <exception cref="ArgumentNullException"></exception>
private SemVersion(SerializationInfo info, StreamingContext context)
{
if (info == null) throw new ArgumentNullException("info");
var semVersion = Parse(info.GetString("SemVersion"));
Major = semVersion.Major;
Minor = semVersion.Minor;
Patch = semVersion.Patch;
Prerelease = semVersion.Prerelease;
Build = semVersion.Build;
}
#endif
/// <summary>
/// Initializes a new instance of the <see cref="SemVersion" /> class.
/// </summary>
/// <param name="major">The major version.</param>
/// <param name="minor">The minor version.</param>
/// <param name="patch">The patch version.</param>
/// <param name="prerelease">The prerelease version (eg. "alpha").</param>
/// <param name="build">The build eg ("nightly.232").</param>
public SemVersion(int major, int minor = 0, int patch = 0, string prerelease = "", string build = "")
{
this.Major = major;
this.Minor = minor;
this.Patch = patch;
this.Prerelease = prerelease ?? "";
this.Build = build ?? "";
}
/// <summary>
/// Initializes a new instance of the <see cref="SemVersion"/> class.
/// </summary>
/// <param name="version">The <see cref="System.Version"/> that is used to initialize
/// the Major, Minor, Patch and Build properties.</param>
public SemVersion(Version version)
{
if (version == null)
throw new ArgumentNullException("version");
this.Major = version.Major;
this.Minor = version.Minor;
if (version.Revision >= 0)
{
this.Patch = version.Revision;
}
this.Prerelease = String.Empty;
if (version.Build > 0)
{
this.Build = version.Build.ToString();
}
else
{
this.Build = String.Empty;
}
}
/// <summary>
/// Parses the specified string to a semantic version.
/// </summary>
/// <param name="version">The version string.</param>
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
/// <returns>The SemVersion object.</returns>
/// <exception cref="System.InvalidOperationException">When a invalid version string is passed.</exception>
public static SemVersion Parse(string version, bool strict = false)
{
var match = parseEx.Match(version);
if (!match.Success)
throw new ArgumentException("Invalid version.", "version");
#if NETSTANDARD
var major = int.Parse(match.Groups["major"].Value);
#else
var major = int.Parse(match.Groups["major"].Value, CultureInfo.InvariantCulture);
#endif
var minorMatch = match.Groups["minor"];
int minor = 0;
if (minorMatch.Success)
{
#if NETSTANDARD
minor = int.Parse(minorMatch.Value);
#else
minor = int.Parse(minorMatch.Value, CultureInfo.InvariantCulture);
#endif
}
else if (strict)
{
throw new InvalidOperationException("Invalid version (no minor version given in strict mode)");
}
var patchMatch = match.Groups["patch"];
int patch = 0;
if (patchMatch.Success)
{
#if NETSTANDARD
patch = int.Parse(patchMatch.Value);
#else
patch = int.Parse(patchMatch.Value, CultureInfo.InvariantCulture);
#endif
}
else if (strict)
{
throw new InvalidOperationException("Invalid version (no patch version given in strict mode)");
}
var prerelease = match.Groups["pre"].Value;
var build = match.Groups["build"].Value;
return new SemVersion(major, minor, patch, prerelease, build);
}
/// <summary>
/// Parses the specified string to a semantic version.
/// </summary>
/// <param name="version">The version string.</param>
/// <param name="semver">When the method returns, contains a SemVersion instance equivalent
/// to the version string passed in, if the version string was valid, or <c>null</c> if the
/// version string was not valid.</param>
/// <param name="strict">If set to <c>true</c> minor and patch version are required, else they default to 0.</param>
/// <returns><c>False</c> when a invalid version string is passed, otherwise <c>true</c>.</returns>
public static bool TryParse(string version, out SemVersion semver, bool strict = false)
{
try
{
semver = Parse(version, strict);
return true;
}
catch (Exception)
{
semver = null;
return false;
}
}
/// <summary>
/// Tests the specified versions for equality.
/// </summary>
/// <param name="versionA">The first version.</param>
/// <param name="versionB">The second version.</param>
/// <returns>If versionA is equal to versionB <c>true</c>, else <c>false</c>.</returns>
public static bool Equals(SemVersion versionA, SemVersion versionB)
{
if (ReferenceEquals(versionA, null))
return ReferenceEquals(versionB, null);
return versionA.Equals(versionB);
}
/// <summary>
/// Compares the specified versions.
/// </summary>
/// <param name="versionA">The version to compare to.</param>
/// <param name="versionB">The version to compare against.</param>
/// <returns>If versionA &lt; versionB <c>&lt; 0</c>, if versionA &gt; versionB <c>&gt; 0</c>,
/// if versionA is equal to versionB <c>0</c>.</returns>
public static int Compare(SemVersion versionA, SemVersion versionB)
{
if (ReferenceEquals(versionA, null))
return ReferenceEquals(versionB, null) ? 0 : -1;
return versionA.CompareTo(versionB);
}
/// <summary>
/// Make a copy of the current instance with optional altered fields.
/// </summary>
/// <param name="major">The major version.</param>
/// <param name="minor">The minor version.</param>
/// <param name="patch">The patch version.</param>
/// <param name="prerelease">The prerelease text.</param>
/// <param name="build">The build text.</param>
/// <returns>The new version object.</returns>
public SemVersion Change(int? major = null, int? minor = null, int? patch = null,
string prerelease = null, string build = null)
{
return new SemVersion(
major ?? this.Major,
minor ?? this.Minor,
patch ?? this.Patch,
prerelease ?? this.Prerelease,
build ?? this.Build);
}
/// <summary>
/// Gets the major version.
/// </summary>
/// <value>
/// The major version.
/// </value>
public int Major { get; private set; }
/// <summary>
/// Gets the minor version.
/// </summary>
/// <value>
/// The minor version.
/// </value>
public int Minor { get; private set; }
/// <summary>
/// Gets the patch version.
/// </summary>
/// <value>
/// The patch version.
/// </value>
public int Patch { get; private set; }
/// <summary>
/// Gets the pre-release version.
/// </summary>
/// <value>
/// The pre-release version.
/// </value>
public string Prerelease { get; private set; }
/// <summary>
/// Gets the build version.
/// </summary>
/// <value>
/// The build version.
/// </value>
public string Build { get; private set; }
/// <summary>
/// Returns a <see cref="System.String" /> that represents this instance.
/// </summary>
/// <returns>
/// A <see cref="System.String" /> that represents this instance.
/// </returns>
public override string ToString()
{
var version = "" + Major + "." + Minor + "." + Patch;
if (!String.IsNullOrEmpty(Prerelease))
version += "-" + Prerelease;
if (!String.IsNullOrEmpty(Build))
version += "+" + Build;
return version;
}
/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates
/// whether the current instance precedes, follows, or occurs in the same position in the sort order as the
/// other object.
/// </summary>
/// <param name="obj">An object to compare with this instance.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared.
/// The return value has these meanings: Value Meaning Less than zero
/// This instance precedes <paramref name="obj" /> in the sort order.
/// Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. i
/// Greater than zero This instance follows <paramref name="obj" /> in the sort order.
/// </returns>
public int CompareTo(object obj)
{
return CompareTo((SemVersion)obj);
}
/// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates
/// whether the current instance precedes, follows, or occurs in the same position in the sort order as the
/// other object.
/// </summary>
/// <param name="other">An object to compare with this instance.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared.
/// The return value has these meanings: Value Meaning Less than zero
/// This instance precedes <paramref name="other" /> in the sort order.
/// Zero This instance occurs in the same position in the sort order as <paramref name="other" />. i
/// Greater than zero This instance follows <paramref name="other" /> in the sort order.
/// </returns>
public int CompareTo(SemVersion other)
{
if (ReferenceEquals(other, null))
return 1;
var r = this.CompareByPrecedence(other);
if (r != 0)
return r;
r = CompareComponent(this.Build, other.Build);
return r;
}
/// <summary>
/// Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build information.
/// </summary>
/// <param name="other">The semantic version.</param>
/// <returns><c>true</c> if the version precedence matches.</returns>
public bool PrecedenceMatches(SemVersion other)
{
return CompareByPrecedence(other) == 0;
}
/// <summary>
/// Compares to semantic versions by precedence. This does the same as a Equals, but ignores the build information.
/// </summary>
/// <param name="other">The semantic version.</param>
/// <returns>
/// A value that indicates the relative order of the objects being compared.
/// The return value has these meanings: Value Meaning Less than zero
/// This instance precedes <paramref name="other" /> in the version precedence.
/// Zero This instance has the same precedence as <paramref name="other" />. i
/// Greater than zero This instance has creater precedence as <paramref name="other" />.
/// </returns>
public int CompareByPrecedence(SemVersion other)
{
if (ReferenceEquals(other, null))
return 1;
var r = this.Major.CompareTo(other.Major);
if (r != 0) return r;
r = this.Minor.CompareTo(other.Minor);
if (r != 0) return r;
r = this.Patch.CompareTo(other.Patch);
if (r != 0) return r;
r = CompareComponent(this.Prerelease, other.Prerelease, true);
return r;
}
static int CompareComponent(string a, string b, bool lower = false)
{
var aEmpty = String.IsNullOrEmpty(a);
var bEmpty = String.IsNullOrEmpty(b);
if (aEmpty && bEmpty)
return 0;
if (aEmpty)
return lower ? 1 : -1;
if (bEmpty)
return lower ? -1 : 1;
var aComps = a.Split('.');
var bComps = b.Split('.');
var minLen = Math.Min(aComps.Length, bComps.Length);
for (int i = 0; i < minLen; i++)
{
var ac = aComps[i];
var bc = bComps[i];
int anum, bnum;
var isanum = Int32.TryParse(ac, out anum);
var isbnum = Int32.TryParse(bc, out bnum);
int r;
if (isanum && isbnum)
{
r = anum.CompareTo(bnum);
if (r != 0) return anum.CompareTo(bnum);
}
else
{
if (isanum)
return -1;
if (isbnum)
return 1;
r = String.CompareOrdinal(ac, bc);
if (r != 0)
return r;
}
}
return aComps.Length.CompareTo(bComps.Length);
}
/// <summary>
/// Determines whether the specified <see cref="System.Object" /> is equal to this instance.
/// </summary>
/// <param name="obj">The <see cref="System.Object" /> to compare with this instance.</param>
/// <returns>
/// <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
/// </returns>
public override bool Equals(object obj)
{
if (ReferenceEquals(obj, null))
return false;
if (ReferenceEquals(this, obj))
return true;
var other = (SemVersion)obj;
return this.Major == other.Major &&
this.Minor == other.Minor &&
this.Patch == other.Patch &&
string.Equals(this.Prerelease, other.Prerelease, StringComparison.Ordinal) &&
string.Equals(this.Build, other.Build, StringComparison.Ordinal);
}
/// <summary>
/// Returns a hash code for this instance.
/// </summary>
/// <returns>
/// A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table.
/// </returns>
public override int GetHashCode()
{
unchecked
{
int result = this.Major.GetHashCode();
result = result * 31 + this.Minor.GetHashCode();
result = result * 31 + this.Patch.GetHashCode();
result = result * 31 + this.Prerelease.GetHashCode();
result = result * 31 + this.Build.GetHashCode();
return result;
}
}
#if !NETSTANDARD
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
public void GetObjectData(SerializationInfo info, StreamingContext context)
{
if (info == null) throw new ArgumentNullException("info");
info.AddValue("SemVersion", ToString());
}
#endif
/// <summary>
/// Implicit conversion from string to SemVersion.
/// </summary>
/// <param name="version">The semantic version.</param>
/// <returns>The SemVersion object.</returns>
public static implicit operator SemVersion(string version)
{
return SemVersion.Parse(version);
}
/// <summary>
/// The override of the equals operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is equal to right <c>true</c>, else <c>false</c>.</returns>
public static bool operator ==(SemVersion left, SemVersion right)
{
return SemVersion.Equals(left, right);
}
/// <summary>
/// The override of the un-equal operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is not equal to right <c>true</c>, else <c>false</c>.</returns>
public static bool operator !=(SemVersion left, SemVersion right)
{
return !SemVersion.Equals(left, right);
}
/// <summary>
/// The override of the greater operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is greater than right <c>true</c>, else <c>false</c>.</returns>
public static bool operator >(SemVersion left, SemVersion right)
{
return SemVersion.Compare(left, right) > 0;
}
/// <summary>
/// The override of the greater than or equal operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is greater than or equal to right <c>true</c>, else <c>false</c>.</returns>
public static bool operator >=(SemVersion left, SemVersion right)
{
return left == right || left > right;
}
/// <summary>
/// The override of the less operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is less than right <c>true</c>, else <c>false</c>.</returns>
public static bool operator <(SemVersion left, SemVersion right)
{
return SemVersion.Compare(left, right) < 0;
}
/// <summary>
/// The override of the less than or equal operator.
/// </summary>
/// <param name="left">The left value.</param>
/// <param name="right">The right value.</param>
/// <returns>If left is less than or equal to right <c>true</c>, else <c>false</c>.</returns>
public static bool operator <=(SemVersion left, SemVersion right)
{
return left == right || left < right;
}
}
}

View File

@ -1,55 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{A45E1C59-BA9E-452C-A5E2-50DE49D53E92}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Katteker</RootNamespace>
<AssemblyName>Katteker</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Katteker.xml</DocumentationFile>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Runtime.Serialization" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="ChangelogHelper.cs" />
<Compile Include="Common\SemVersion.cs" />
<Compile Include="Constants.cs" />
<Compile Include="KattekerConfig.cs" />
<Compile Include="Common\MarkdownSharp.cs" />
<Compile Include="UpdateInfo.cs" />
<Compile Include="UpdateManager.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="ReleaseEntry.cs" />
<Compile Include="Releases.cs" />
<Compile Include="Utility.cs" />
<Compile Include="VersionExtension.cs" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@ -1,38 +0,0 @@
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Json;
namespace Katteker
{
[DataContract]
public class KattekerConfig
{
[DataMember]
public string PublishDir { get; set; }
[DataMember]
public string Changelog { get; set; }
public static KattekerConfig ReadFromFile(string path)
{
if (!File.Exists(path)) throw new FileNotFoundException();
var dataContractJsonSerializer = new DataContractJsonSerializer(typeof(KattekerConfig));
using (var fileStream = File.OpenRead(path))
{
var obj = dataContractJsonSerializer.ReadObject(fileStream);
return (KattekerConfig) obj;
}
}
public void WriteToFile(string path)
{
if (File.Exists(path)) File.Delete(path);
using (var fileStream = File.OpenWrite(path))
{
var dataContractJsonSerializer = new DataContractJsonSerializer(typeof(KattekerConfig));
dataContractJsonSerializer.WriteObject(fileStream, this);
}
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -1,35 +0,0 @@
using System.Reflection;
using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die einer Assembly zugeordnet sind.
[assembly: AssemblyTitle("Katteker")]
[assembly: AssemblyDescription("Katteker Client")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("Holger Börchers")]
[assembly: AssemblyProduct("Katteker")]
[assembly: AssemblyCopyright("Copyright © Holger Börchers 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Durch Festlegen von ComVisible auf FALSE werden die Typen in dieser Assembly
// für COM-Komponenten unsichtbar. Wenn Sie auf einen Typ in dieser Assembly von
// COM aus zugreifen müssen, sollten Sie das ComVisible-Attribut für diesen Typ auf "True" festlegen.
[assembly: ComVisible(false)]
// Die folgende GUID bestimmt die ID der Typbibliothek, wenn dieses Projekt für COM verfügbar gemacht wird
[assembly: Guid("a45e1c59-ba9e-452c-a5e2-50de49d53e92")]
// Versionsinformationen für eine Assembly bestehen aus den folgenden vier Werten:
//
// Hauptversion
// Nebenversion
// Buildnummer
// Revision
//
// Sie können alle Werte angeben oder Standardwerte für die Build- und Revisionsnummern verwenden,
// indem Sie "*" wie unten gezeigt eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.3")]
[assembly: AssemblyFileVersion("1.0.3")]

View File

@ -1,93 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using Semver;
namespace Katteker
{
public class ReleaseEntry : IComparable<ReleaseEntry>, IComparable
{
private const string FilenameRegex = @"(^.*)-((?:0|[1-9]\d*)\.(?:0|[1-9]\d*)\.(?:0|[1-9]\d*)(?:-(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*)?(?:\+[0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*)?).*-(full|delta)";
private const char Seperator = '|';
public ReleaseEntry(string filename, SemVersion version, long fileSize, bool isDelta, string sha1)
{
Filename = filename;
Version = version;
Filesize = fileSize;
IsDelta = isDelta;
SHA1 = sha1;
}
public ReleaseEntry(string line)
{
var elements = line?.Split(Seperator);
if (elements?.Length != 3) return;
SHA1 = elements[0];
Filename = elements[1];
Filesize = long.Parse(elements[2]);
var fileSegments = Regex.Match(Filename, FilenameRegex);
if (fileSegments.Groups.Count < 3) throw new ArgumentOutOfRangeException("Filename is not compilant.");
ApplicationName = fileSegments.Groups[1].Value;
Version = SemVersion.Parse(fileSegments.Groups[2].Value);
IsDelta = fileSegments.Groups[3].Value != "full";
}
public ReleaseEntry(string applicationName, SemVersion version)
{
ApplicationName = applicationName;
Version = version;
}
public SemVersion Version { get; }
public string SHA1 { get; }
public string Filename { get; }
public long Filesize { get; }
public bool IsDelta { get; }
public string ApplicationName { get; }
public string EntryAsString => $"{SHA1}{Seperator}{Filename}{Seperator}{Filesize}";
public override string ToString() => $"{ApplicationName} {Version}";
public int CompareTo(object obj) => CompareTo(obj as ReleaseEntry);
public int CompareTo(ReleaseEntry other)
{
if (ReferenceEquals(this, other)) return 0;
if (other is null) return 1;
var versionComparison = Comparer<SemVersion>.Default.Compare(Version, other.Version);
if (versionComparison != 0) return versionComparison;
return string.Compare(Filename, other.Filename, StringComparison.Ordinal);
}
public override bool Equals(object obj) => Equals(obj as ReleaseEntry);
protected bool Equals(ReleaseEntry other)
{
return Equals(Version, other.Version) && string.Equals(SHA1, other.SHA1) && string.Equals(Filename, other.Filename) && Filesize == other.Filesize && IsDelta == other.IsDelta;
}
public override int GetHashCode()
{
unchecked
{
var hashCode = (Version != null ? Version.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (SHA1 != null ? SHA1.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ (Filename != null ? Filename.GetHashCode() : 0);
hashCode = (hashCode * 397) ^ Filesize.GetHashCode();
hashCode = (hashCode * 397) ^ IsDelta.GetHashCode();
return hashCode;
}
}
public static bool operator ==(ReleaseEntry left, ReleaseEntry right)
{
return Equals(left, right);
}
public static bool operator !=(ReleaseEntry left, ReleaseEntry right)
{
return !Equals(left, right);
}
}
}

View File

@ -1,204 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Threading.Tasks;
namespace Katteker
{
/// <summary>
/// Update manager, which handles the updates.
/// </summary>
public class UpdateManager
{
private static readonly string _baseDir = AppDomain.CurrentDomain.BaseDirectory;
private static KattekerConfig _config;
private readonly string _applicationName;
private readonly string _packageDir;
private readonly string _rootAppDirectory;
private readonly string _urlOrPath;
private Releases _releases;
private UpdateManager(string urlOrPath, string applicationName, string rootDirectory)
{
_urlOrPath = urlOrPath;
_applicationName = applicationName;
_rootAppDirectory = rootDirectory;
var packageDir = Path.Combine(rootDirectory, Constants.PackageFolder);
if (!Directory.Exists(packageDir)) Directory.CreateDirectory(packageDir);
_packageDir = packageDir;
}
/// <summary>
/// Filename of the changelog.
/// </summary>
public string ChangelogFilename => _config.Changelog;
/// <summary>
/// Url or path where the update files are located.
/// </summary>
public string UrlOrPath => _urlOrPath;
/// <summary>
/// Create the update manager.
/// </summary>
/// <param name="urlOrPath">path to the publishing directory</param>
/// <param name="applicationName">name of the application to update.</param>
/// <param name="rootDirectory">root directory.</param>
/// <returns>the update manager.</returns>
public static UpdateManager Create(string urlOrPath = null, string applicationName = null, string rootDirectory = null)
{
_config = ReadConfigFile();
urlOrPath = urlOrPath ?? _config.PublishDir;
var appName = applicationName ?? Utility.GetApplicationName();
var rootAppDirectory = Path.Combine(rootDirectory ?? Utility.GetLocalAppDataDirectory(), appName);
return new UpdateManager(urlOrPath, appName, rootAppDirectory);
}
/// <summary>
/// Try to create the update manager.
/// </summary>
/// <param name="manager">update manager</param>
/// <param name="urlOrPath">path to the publishing directory</param>
/// <param name="applicationName">name of the application to update.</param>
/// <param name="rootDirectory">root directory.</param>
/// <returns>true if the creation success, false otherwise.</returns>
public static bool TryCreate(out UpdateManager manager, string urlOrPath = null, string applicationName = null, string rootDirectory = null)
{
try
{
manager = Create(urlOrPath, applicationName, rootDirectory);
return true;
}
catch (Exception)
{
manager = default(UpdateManager);
return false;
}
}
public async Task<IEnumerable<ReleaseEntry>> CheckForUpdateAsync()
{
_releases = Utility.IsWebUrl(_urlOrPath) ? await DownloadIndexAsync(_urlOrPath).ConfigureAwait(false) : GetFromFilesystem(_urlOrPath);
var updateInfo = new UpdateInfo(_applicationName, _releases);
return updateInfo.ReleasesToApply;
}
/// <summary>
/// Restart the application.
/// </summary>
/// <param name="exeToStart"></param>
/// <param name="arguments"></param>
public void RestartApp(string exeToStart = null, string arguments = null)
{
exeToStart = exeToStart ?? Path.GetFileName(Assembly.GetEntryAssembly().Location);
var program = Path.Combine(_rootAppDirectory, exeToStart);
if (File.Exists(program))
{
Process.Start(program, arguments);
Thread.Sleep(500);
Environment.Exit(0);
}
}
/// <summary>
/// Update application.
/// </summary>
/// <param name="progress">The updating process.</param>
/// <returns></returns>
public async Task<bool> UpdateAppAsync(IProgress<int> progress = null)
{
progress?.Report(0);
var updateEntries = (await CheckForUpdateAsync().ConfigureAwait(false)).ToArray();
var update = updateEntries.LastOrDefault();
if (update == null) return false;
progress?.Report(30);
return await UpdateAppImplAsync(update, progress).ConfigureAwait(false);
}
private static async Task<Releases> DownloadIndexAsync(string urlOrPath)
{
var url = urlOrPath.TrimEnd('/');
url += "/" + Constants.Release;
var content = await new WebClient().DownloadStringTaskAsync(url).ConfigureAwait(false);
var lines = content.Split(new[] {'\r', '\n'}, StringSplitOptions.RemoveEmptyEntries);
return new Releases(lines);
}
private static Releases GetFromFilesystem(string urlOrPath) => new Releases(urlOrPath);
private static KattekerConfig ReadConfigFile()
{
var configPath = Path.Combine(_baseDir, Constants.KattekerConfig);
if (!File.Exists(configPath)) throw new FileNotFoundException("Configuration file not found.", configPath);
return KattekerConfig.ReadFromFile(configPath);
}
private static bool VerifyFileChecksum(string targetFile, string lastEntrySha1)
{
var hash = Utility.ComputeFileHash(targetFile);
return lastEntrySha1.Equals(hash);
}
private Task KillAppStubAsync()
{
foreach (var process in Process.GetProcessesByName(_applicationName))
{
var path = Path.GetDirectoryName(process.MainModule.FileName);
if (_rootAppDirectory.Equals(path))
{
process.Kill();
return Task.Delay(500);
}
}
return Task.FromResult(true);
}
private async Task PutFileInPackageFolderAsync(string filename)
{
var targetFile = Path.Combine(_packageDir, filename);
File.Delete(targetFile);
if (Utility.IsWebUrl(_urlOrPath))
{
var url = _urlOrPath.TrimEnd('/');
url += "/" + filename;
await new WebClient().DownloadFileTaskAsync(new Uri(url), targetFile).ConfigureAwait(false);
}
else
{
File.Copy(Path.Combine(_urlOrPath, filename), targetFile);
}
}
private async Task<bool> UpdateAppImplAsync(ReleaseEntry lastEntry, IProgress<int> progress)
{
var targetFile = Path.Combine(_packageDir, lastEntry.Filename);
//download file.
await PutFileInPackageFolderAsync(lastEntry.Filename).ConfigureAwait(false);
progress?.Report(60);
if (!VerifyFileChecksum(targetFile, lastEntry.SHA1)) throw new FileLoadException();
progress?.Report(70);
await KillAppStubAsync().ConfigureAwait(false);
progress?.Report(80);
using (var updater = new Process())
{
updater.StartInfo = new ProcessStartInfo(targetFile, "/S");
updater.Start();
updater.WaitForExit();
}
progress?.Report(100);
return true;
}
}
}

View File

@ -1,55 +0,0 @@
using System;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
namespace Katteker
{
/// <summary>
/// Utilities.
/// </summary>
public static class Utility
{
internal static string GetLocalAppDataDirectory()
{
return Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
}
internal static string GetApplicationName()
{
return Assembly.GetEntryAssembly().GetName().Name;
}
/// <summary>
/// Is true if the url is a web-address. False otherwise.
/// </summary>
/// <param name="urlOrPath"></param>
/// <returns></returns>
public static bool IsWebUrl(string urlOrPath)
{
var uri = new Uri(urlOrPath);
return uri.Scheme == "http" || uri.Scheme == "https";
}
/// <summary>
/// Compute file hash with SHA1.
/// If the file is greater than 5 MB, the hash will only computed with the first 5 MB.
/// </summary>
/// <param name="filename"></param>
/// <returns></returns>
public static string ComputeFileHash(string filename)
{
string sha1;
var fileInfo = new FileInfo(filename);
using (var fileStream = fileInfo.OpenRead())
{
var buffer = new byte[5242880];
fileStream.Read(buffer, 0, buffer.Length);
var sha1Managed = new SHA1Managed();
sha1 = Convert.ToBase64String(sha1Managed.ComputeHash(buffer));
}
return sha1;
}
}
}

View File

@ -1,40 +0,0 @@
using System;
using System.Reflection;
using Semver;
namespace Katteker
{
/// <summary>
/// Extension methods for the App-Version.
/// </summary>
public static class VersionExtension
{
/// <summary>
/// Get the current Version of Application.
/// </summary>
public static SemVersion GetCurrentVersion
{
get
{
var assemblyVersion = Assembly.GetEntryAssembly().GetName().Version.ToString(3);
var getCurrentVersion = SemVersion.Parse(assemblyVersion);
var informalVersion = Assembly.GetEntryAssembly().GetCustomAttribute<AssemblyInformationalVersionAttribute>()?.InformationalVersion;
if (informalVersion != null && SemVersion.TryParse(informalVersion, out var semVersion))
return semVersion;
return getCurrentVersion;
}
}
/// <summary>
/// Convert to cenventional System.Version instance.
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static Version ToSystemVersion(this SemVersion value) => new Version(value.Major, value.Minor, value.Patch, 0);
/// <summary>
/// Get the current Version of Application.
/// </summary>
public static string GetFullVersion => GetCurrentVersion.ToString();
}
}

View File

@ -1,7 +1,9 @@
SquirrelKiller (aka Wombat)
[Katteker](https://nds.wikipedia.org/wiki/Katteker)
=============
Idee: [Converting between RTF and HTML](https://code.msdn.microsoft.com/Converting-between-RTF-and-aaa02a6e)
Um den WebBrowser los zu werden.
Ziele:
Ziele
-------------
- Automatische Updates, auch für nicht verwaltete Software.
- Popup unten rechts mit Informationen über Update.
@ -11,17 +13,19 @@ Ziele:
- AppStub übernimmt die Resourcen der Executable. (Icon, Name, Version, Copyright, Beschreibung, etc)
[ResourceLib C# File Resource Management Library](https://github.com/dblock/resourcelib)
Creator:
Creator
-------------
- Auf dotnet core portieren?
- T4-Engine ersetzen: https://github.com/toddams/RazorLight
- Informationen der Anwendung auslesen
- Name,
- Version,
- ...
- Name,
- Version,
- ...
- AppStub kopieren & konfigurieren
- Installer erstellen
- RELEASE Datei updaten
AppStub:
AppStub
-------------
- Anwendung starten
- Im Mutex ausführen

45
app-stub/.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,45 @@
{
// Use IntelliSense to learn about possible attributes.
// Hover to view descriptions of existing attributes.
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"type": "lldb",
"request": "launch",
"name": "Debug executable 'app-stub'",
"cargo": {
"args": [
"build",
"--bin=app-stub",
"--package=app-stub"
],
"filter": {
"name": "app-stub",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
},
{
"type": "lldb",
"request": "launch",
"name": "Debug unit tests in executable 'app-stub'",
"cargo": {
"args": [
"test",
"--no-run",
"--bin=app-stub",
"--package=app-stub"
],
"filter": {
"name": "app-stub",
"kind": "bin"
}
},
"args": [],
"cwd": "${workspaceFolder}"
}
]
}

168
app-stub/Cargo.lock generated Normal file
View File

@ -0,0 +1,168 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "app-stub"
version = "0.2.0"
dependencies = [
"itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"semver 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)",
"simplelog 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "autocfg"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "cfg-if"
version = "0.1.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "chrono"
version = "0.4.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
"time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "either"
version = "1.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "itertools"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"either 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "libc"
version = "0.2.77"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "log"
version = "0.4.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-integer"
version = "0.1.43"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
"num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "num-traits"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "semver-parser"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "simplelog"
version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)",
"log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)",
"termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "termcolor"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "time"
version = "0.1.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)",
"wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "wasi"
version = "0.10.0+wasi-snapshot-preview1"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
"winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
dependencies = [
"winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum autocfg 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "cdb031dd78e28731d87d56cc8ffef4a8f36ca26c38fe2de700543e627f8a464a"
"checksum cfg-if 0.1.10 (registry+https://github.com/rust-lang/crates.io-index)" = "4785bdd1c96b2a846b2bd7cc02e86b6b3dbf14e7e53446c4f54c92a361040822"
"checksum chrono 0.4.15 (registry+https://github.com/rust-lang/crates.io-index)" = "942f72db697d8767c22d46a598e01f2d3b475501ea43d0db4f16d90259182d0b"
"checksum either 1.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "cd56b59865bce947ac5958779cfa508f6c3b9497cc762b7e24a12d11ccde2c4f"
"checksum itertools 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "284f18f85651fe11e8a991b2adb42cb078325c996ed026d994719efcfca1d54b"
"checksum libc 0.2.77 (registry+https://github.com/rust-lang/crates.io-index)" = "f2f96b10ec2560088a8e76961b00d47107b3a625fecb76dedb29ee7ccbf98235"
"checksum log 0.4.11 (registry+https://github.com/rust-lang/crates.io-index)" = "4fabed175da42fed1fa0746b0ea71f412aa9d35e76e95e59b192c64b9dc2bf8b"
"checksum num-integer 0.1.43 (registry+https://github.com/rust-lang/crates.io-index)" = "8d59457e662d541ba17869cf51cf177c0b5f0cbf476c66bdc90bf1edac4f875b"
"checksum num-traits 0.2.12 (registry+https://github.com/rust-lang/crates.io-index)" = "ac267bcc07f48ee5f8935ab0d24f316fb722d7a1292e2913f0cc196b29ffd611"
"checksum semver 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "394cec28fa623e00903caf7ba4fa6fb9a0e260280bb8cdbbba029611108a0190"
"checksum semver-parser 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3"
"checksum simplelog 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "2b2736f58087298a448859961d3f4a0850b832e72619d75adc69da7993c2cd3c"
"checksum termcolor 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f"
"checksum time 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "6db9e6914ab8b1ae1c260a4ae7a49b6c5611b40328a735b21862567685e73255"
"checksum wasi 0.10.0+wasi-snapshot-preview1 (registry+https://github.com/rust-lang/crates.io-index)" = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f"
"checksum winapi 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)" = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419"
"checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
"checksum winapi-util 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
"checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

13
app-stub/Cargo.toml Normal file
View File

@ -0,0 +1,13 @@
[package]
name = "app-stub"
version = "0.2.0"
authors = ["Holger Börchers <holgerb83@gmail.com>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
semver = "0.10.0"
log = "0.4.11"
simplelog = "0.8.0"
itertools = "0.9.0"

120
app-stub/src/main.rs Normal file
View File

@ -0,0 +1,120 @@
#![windows_subsystem = "windows"]
use itertools::Itertools;
use log::{error, info};
use semver::Version;
use simplelog::*;
use std::collections::BTreeMap;
use std::env;
use std::ffi::OsString;
use std::fs;
use std::fs::File;
use std::option::Option;
use std::path::{Path, PathBuf};
fn main() {
if env::var("APPSTUB_DEBUG").is_ok() {
CombinedLogger::init(vec![
TermLogger::new(LevelFilter::Error, Config::default(), TerminalMode::Mixed),
WriteLogger::new(
LevelFilter::Info,
Config::default(),
File::create("app-stub.log").unwrap(),
),
])
.unwrap();
}
info!("Search for folders");
let app_folders = get_all_app_folders();
if let Some(executed_version) = execute_application(&app_folders) {
delete_old_versions(&app_folders, &executed_version);
}
}
fn execute_application(app_folders: &BTreeMap<Version, PathBuf>) -> Option<&Version> {
if let Some(executable_name) = get_executable_name() {
info!("Executable name: {:?}", executable_name);
if let Some(programm_to_start) = app_folders.iter().next_back() {
let folder = programm_to_start.1;
let mut path: PathBuf = PathBuf::from(folder);
path.push(Path::new(&executable_name));
info!("Path to start: {:?}", path);
let arguments = env::args().skip(1).format(" ");
info!("Arguments: {:?}", arguments);
let process = std::process::Command::new(path.as_os_str())
.args(env::args().skip(1))
.current_dir(folder)
.spawn();
match process {
Ok(out) => info!("{:?}", out),
Err(error) => error!("{:?}", error),
}
return Some(programm_to_start.0);
}
}
return None;
}
fn delete_old_versions(app_folders: &BTreeMap<Version, PathBuf>, executed_version: &Version) {
for app_folder in app_folders {
if app_folder.0 != executed_version {
info!("Foler to remove: {:?}", app_folder.1);
let remove_dir_all = std::fs::remove_dir_all(&app_folder.1);
match remove_dir_all {
Ok(out) => info!("{:?}", out),
Err(error) => error!("{:?}", error),
}
}
}
}
fn get_semantic_version(path: PathBuf) -> Option<Version> {
let last_component = path.components().last();
let folder_name = last_component?.as_os_str().to_str();
if folder_name?.to_lowercase().starts_with("app-") {
let strip_folder_name = folder_name?.get(4..folder_name?.len());
let parsed_semver = Version::parse(strip_folder_name?);
if let Ok(parsed_semver) = parsed_semver {
return Some(parsed_semver);
}
}
return None;
}
fn get_executable_name() -> Option<OsString> {
if let Ok(current_exe) = env::current_exe() {
if let Some(file_name) = current_exe.file_name() {
return Some(file_name.to_os_string());
}
}
return None;
}
fn get_all_app_folders() -> BTreeMap<Version, PathBuf> {
let mut app_folders: BTreeMap<Version, PathBuf> = BTreeMap::new();
if let Ok(current_exe) = env::current_exe() {
info!("Current executable: {:?}", current_exe);
if let Some(parent_dir) = current_exe.parent() {
info!("Parent directory: {:?}", parent_dir);
if let Ok(entries) = fs::read_dir(parent_dir) {
for entry in entries {
if let Ok(entry) = entry {
if let Ok(file_type) = entry.file_type() {
if file_type.is_dir() {
let semantic = get_semantic_version(entry.path());
if let Some(semantic) = semantic {
info!("Found folder (Version {:?}): {:?}", semantic, entry);
app_folders.insert(semantic, entry.path());
}
}
}
}
}
}
}
}
info!("Totally found {:?} folders", app_folders.len());
return app_folders;
}

6
nuget.config Normal file
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<packageSources>
<add key="nuget.org" value="https://api.nuget.org/v3/index.json" protocolVersion="3" />
</packageSources>
</configuration>

View File

@ -32,6 +32,7 @@ using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
// ReSharper disable All
namespace TsudaKageyu
{
@ -98,10 +99,8 @@ namespace TsudaKageyu
// Create an Icon from the .ico file in memory.
using (var ms = new MemoryStream(iconData[index]))
{
return new Icon(ms);
}
using var ms = new MemoryStream(iconData[index]);
return new Icon(ms);
}
/// <summary>
@ -112,8 +111,10 @@ namespace TsudaKageyu
public Icon[] GetAllIcons()
{
var icons = new List<Icon>();
for (int i = 0; i < Count; ++i)
for (var i = 0; i < Count; ++i)
{
icons.Add(GetIcon(i));
}
return icons.ToArray();
}
@ -128,7 +129,7 @@ namespace TsudaKageyu
if (index < 0 || Count <= index)
throw new ArgumentOutOfRangeException("index");
if (outputStream == null)
if (outputStream is null)
throw new ArgumentNullException("outputStream");
var data = iconData[index];
@ -137,10 +138,10 @@ namespace TsudaKageyu
private void Initialize(string fileName)
{
if (fileName == null)
if (fileName is null)
throw new ArgumentNullException("fileName");
IntPtr hModule = IntPtr.Zero;
var hModule = IntPtr.Zero;
try
{
hModule = NativeMethods.LoadLibraryEx(fileName, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
@ -153,7 +154,7 @@ namespace TsudaKageyu
var tmpData = new List<byte[]>();
ENUMRESNAMEPROC callback = (h, t, name, l) =>
bool callback(IntPtr h, IntPtr t, IntPtr name, IntPtr l)
{
// Refer to the following URL for the data structures used here:
// http://msdn.microsoft.com/en-us/library/ms997538.aspx
@ -165,8 +166,8 @@ namespace TsudaKageyu
// Calculate the size of an entire .icon file.
int count = BitConverter.ToUInt16(dir, 4); // GRPICONDIR.idCount
int len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
var len = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (var i = 0; i < count; ++i)
len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes
using (var dst = new BinaryWriter(new MemoryStream(len)))
@ -175,13 +176,13 @@ namespace TsudaKageyu
dst.Write(dir, 0, 6);
int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
var picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
for (int i = 0; i < count; ++i)
for (var i = 0; i < count; ++i)
{
// Load the picture.
ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
var id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);
// Copy GRPICONDIRENTRY to ICONDIRENTRY.
@ -204,7 +205,7 @@ namespace TsudaKageyu
}
return true;
};
}
NativeMethods.EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
iconData = tmpData.ToArray();
@ -220,23 +221,23 @@ namespace TsudaKageyu
{
// Load the binary data from the specified resource.
IntPtr hResInfo = NativeMethods.FindResource(hModule, name, type);
var hResInfo = NativeMethods.FindResource(hModule, name, type);
if (hResInfo == IntPtr.Zero)
throw new Win32Exception();
IntPtr hResData = NativeMethods.LoadResource(hModule, hResInfo);
var hResData = NativeMethods.LoadResource(hModule, hResInfo);
if (hResData == IntPtr.Zero)
throw new Win32Exception();
IntPtr pResData = NativeMethods.LockResource(hResData);
var pResData = NativeMethods.LockResource(hResData);
if (pResData == IntPtr.Zero)
throw new Win32Exception();
uint size = NativeMethods.SizeofResource(hModule, hResInfo);
var size = NativeMethods.SizeofResource(hModule, hResInfo);
if (size == 0)
throw new Win32Exception();
byte[] buf = new byte[size];
var buf = new byte[size];
Marshal.Copy(pResData, buf, 0, buf.Length);
return buf;
@ -253,7 +254,7 @@ namespace TsudaKageyu
string fileName;
{
var buf = new StringBuilder(MAX_PATH);
int len = NativeMethods.GetMappedFileName(
var len = NativeMethods.GetMappedFileName(
NativeMethods.GetCurrentProcess(), hModule, buf, buf.Capacity);
if (len == 0)
throw new Win32Exception();
@ -264,11 +265,11 @@ namespace TsudaKageyu
// Convert the device name to drive name like:
// "C:\\Windows\\System32\\shell32.dll"
for (char c = 'A'; c <= 'Z'; ++c)
for (var c = 'A'; c <= 'Z'; ++c)
{
var drive = c + ":";
var buf = new StringBuilder(MAX_PATH);
int len = NativeMethods.QueryDosDevice(drive, buf, buf.Capacity);
var len = NativeMethods.QueryDosDevice(drive, buf, buf.Capacity);
if (len == 0)
continue;

View File

@ -0,0 +1,13 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<RootNamespace>TsudaKageyu</RootNamespace>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="System.Drawing.Common" Version="5.0.0" />
</ItemGroup>
</Project>

View File

@ -31,6 +31,7 @@ using System.Drawing;
using System.IO;
using System.Reflection;
using System.Reflection.Emit;
// ReSharper disable All
namespace TsudaKageyu
{
@ -64,7 +65,7 @@ namespace TsudaKageyu
/// <returns>An array of System.Drawing.Icon.</returns>
public static Icon[] Split(Icon icon)
{
if (icon == null)
if (icon is null)
throw new ArgumentNullException("icon");
// Get an .ico file in memory, then split it into separate icons.
@ -114,7 +115,7 @@ namespace TsudaKageyu
/// <returns>A System.Drawing.Bitmap Object.</returns>
public static Bitmap ToBitmap(Icon icon)
{
if (icon == null)
if (icon is null)
throw new ArgumentNullException("icon");
// Quick workaround: Create an .ico file in memory, then load it as a Bitmap.
@ -141,7 +142,7 @@ namespace TsudaKageyu
/// </remarks>
public static int GetBitCount(Icon icon)
{
if (icon == null)
if (icon is null)
throw new ArgumentNullException("icon");
// Get an .ico file in memory, then read the header.
@ -185,7 +186,7 @@ namespace TsudaKageyu
private static byte[] GetIconData(Icon icon)
{
var data = getIconData(icon);
if (data != null)
if (data is not null)
{
return data;
}

View File

@ -29,6 +29,7 @@ using System;
using System.Runtime.InteropServices;
using System.Security;
using System.Text;
// ReSharper disable All
namespace TsudaKageyu
{

View File

@ -0,0 +1,32 @@
using System;
using System.Net;
namespace Katteker.Changelog
{
public static class ChangelogExtension
{
/// <summary>
/// Format the Changelog as Html compliant file.
/// </summary>
public static string AsHtml(this ChangelogFile value)
{
string result;
switch (value.ChangelogFileType)
{
case ChangelogFileType.TextFile:
var plainText = WebUtility.HtmlEncode(value.Content);
result = plainText?.Replace(Environment.NewLine, "<br />");
break;
case ChangelogFileType.MarkdownFile:
result = new MarkdownSharp.Markdown().Transform(value.Content);
break;
default:
result = value.Content;
break;
}
return result;
}
}
}

View File

@ -0,0 +1,16 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net452;netstandard2.0</TargetFrameworks>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\Katteker\Katteker.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="MarkdownSharp" Version="2.0.5" />
</ItemGroup>
</Project>

View File

@ -0,0 +1,22 @@
//------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//------------------------------------------------------------------------------
using System;
using System.Reflection;
[assembly: System.Reflection.AssemblyCompanyAttribute("Holger B<>rchers")]
[assembly: System.Reflection.AssemblyConfigurationAttribute("Release")]
[assembly: System.Reflection.AssemblyFileVersionAttribute("1.1.5.0")]
[assembly: System.Reflection.AssemblyInformationalVersionAttribute("1.1.5")]
[assembly: System.Reflection.AssemblyProductAttribute("Katteker")]
[assembly: System.Reflection.AssemblyTitleAttribute("Katteker")]
[assembly: System.Reflection.AssemblyVersionAttribute("1.1.5.0")]
// Generated by the MSBuild WriteCodeFragment class.

View File

@ -7,12 +7,15 @@
<ProjectGuid>{07E2DE31-80A0-43DA-B307-1CA47CD930A1}</ProjectGuid>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Katteker.Gui</RootNamespace>
<AssemblyName>Katteker.Gui</AssemblyName>
<TargetFrameworkVersion>v4.5</TargetFrameworkVersion>
<RootNamespace>Katteker</RootNamespace>
<AssemblyName>Katteker.UserInterface</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<SolutionDir Condition="$(SolutionDir) == '' Or $(SolutionDir) == '*Undefined*'">..\</SolutionDir>
<RestorePackages>true</RestorePackages>
<NuGetPackageImportStamp>
</NuGetPackageImportStamp>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
@ -22,7 +25,8 @@
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Debug\Katteker.Gui.xml</DocumentationFile>
<DocumentationFile>bin\Debug\Katteker.UserInterface.xml</DocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
@ -31,7 +35,8 @@
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<DocumentationFile>bin\Release\Katteker.Gui.xml</DocumentationFile>
<DocumentationFile>bin\Release\Katteker.UserInterface.xml</DocumentationFile>
<LangVersion>latest</LangVersion>
</PropertyGroup>
<ItemGroup>
<Reference Include="Microsoft.CSharp" />
@ -42,7 +47,8 @@
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Wrapper.cs" />
<Compile Include="NativeMethods.cs" />
<Compile Include="UserInterface.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="Properties\Resources.Designer.cs">
<AutoGen>True</AutoGen>
@ -70,11 +76,20 @@
</EmbeddedResource>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Katteker.Changelog\Katteker.Changelog.csproj">
<Project>{7004ebbd-87aa-49e6-bf1c-ff933ba028fe}</Project>
<Name>Katteker.Changelog</Name>
</ProjectReference>
<ProjectReference Include="..\Katteker\Katteker.csproj">
<Project>{a45e1c59-ba9e-452c-a5e2-50de49d53e92}</Project>
<Project>{4cd50166-c3ab-4cc4-9694-951a3f33addb}</Project>
<Name>Katteker</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Semver">
<Version>2.0.6</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<PropertyGroup>
<PostBuildEvent>

View File

@ -0,0 +1,41 @@
using System;
using System.Runtime.InteropServices;
// ReSharper disable InconsistentNaming
namespace Katteker
{
/// <summary>
/// Native methods.
/// </summary>
internal static class NativeMethods
{
/// <summary>
/// Hit Test Caption
/// </summary>
internal const int HTCAPTION = 0x2;
/// <summary>
/// Posted when the user presses the left mouse button while the cursor is within the nonclient area of a window.
/// </summary>
internal const int WM_NCLBUTTONDOWN = 0xA1;
/// <summary>
/// Release the capture
/// </summary>
[DllImport("User32.dll")]
internal static extern bool ReleaseCapture();
/// <summary>
/// Send message
/// </summary>
[DllImport("User32.dll")]
internal static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
/// <summary>
/// Set Process API aware
/// </summary>
[DllImport("User32.dll")]
internal static extern bool SetProcessDPIAware();
}
}

View File

@ -4,11 +4,11 @@ using System.Runtime.InteropServices;
// Allgemeine Informationen über eine Assembly werden über die folgenden
// Attribute gesteuert. Ändern Sie diese Attributwerte, um die Informationen zu ändern,
// die mit einer Assembly verknüpft sind.
[assembly: AssemblyTitle("Katteker.Gui")]
[assembly: AssemblyTitle("Katteker.UserInterface")]
[assembly: AssemblyDescription("Helps Applications to integrate Katteker")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("WRD GmbH")]
[assembly: AssemblyProduct("Katteker.Gui")]
[assembly: AssemblyProduct("Katteker.UserInterface")]
[assembly: AssemblyCopyright("Copyright © Enercon GmbH 2015-2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
@ -31,5 +31,5 @@ using System.Runtime.InteropServices;
// Sie können alle Werte angeben oder die standardmäßigen Build- und Revisionsnummern
// übernehmen, indem Sie "*" eingeben:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0")]
[assembly: AssemblyFileVersion("1.0.0")]
[assembly: AssemblyVersion("1.1.5")]
[assembly: AssemblyFileVersion("1.1.5")]

View File

@ -8,7 +8,7 @@
// </auto-generated>
//------------------------------------------------------------------------------
namespace Katteker.Gui.Properties {
namespace Katteker.Properties {
using System;
@ -19,7 +19,7 @@ namespace Katteker.Gui.Properties {
// class via a tool like ResGen or Visual Studio.
// To add or remove a member, edit your .ResX file then rerun ResGen
// with the /str option, or rebuild your VS project.
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "15.0.0.0")]
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "16.0.0.0")]
[global::System.Diagnostics.DebuggerNonUserCodeAttribute()]
[global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()]
internal class Resources {
@ -39,7 +39,7 @@ namespace Katteker.Gui.Properties {
internal static global::System.Resources.ResourceManager ResourceManager {
get {
if (object.ReferenceEquals(resourceMan, null)) {
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Katteker.Gui.Properties.Resources", typeof(Resources).Assembly);
global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Katteker.Properties.Resources", typeof(Resources).Assembly);
resourceMan = temp;
}
return resourceMan;

View File

@ -1,6 +1,6 @@
using System;
namespace Katteker.Gui
namespace Katteker
{
/// <summary>
/// Shows the Update Window.
@ -65,7 +65,7 @@ namespace Katteker.Gui
//
this.mainSplitContainer.Panel2.Controls.Add(this.splitContainer3);
this.mainSplitContainer.Size = new System.Drawing.Size(698, 438);
this.mainSplitContainer.SplitterDistance = 30;
this.mainSplitContainer.SplitterDistance = 45;
this.mainSplitContainer.TabIndex = 7;
this.mainSplitContainer.TabStop = false;
//
@ -89,7 +89,7 @@ namespace Katteker.Gui
this.titleLayoutPanel.Name = "titleLayoutPanel";
this.titleLayoutPanel.RowCount = 1;
this.titleLayoutPanel.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F));
this.titleLayoutPanel.Size = new System.Drawing.Size(698, 30);
this.titleLayoutPanel.Size = new System.Drawing.Size(698, 45);
this.titleLayoutPanel.TabIndex = 0;
this.titleLayoutPanel.MouseDown += new System.Windows.Forms.MouseEventHandler(this.Titlebar_MouseDown);
//
@ -104,7 +104,7 @@ namespace Katteker.Gui
this.closeWindowBtn.Location = new System.Drawing.Point(658, 0);
this.closeWindowBtn.Margin = new System.Windows.Forms.Padding(0);
this.closeWindowBtn.Name = "closeWindowBtn";
this.closeWindowBtn.Size = new System.Drawing.Size(40, 30);
this.closeWindowBtn.Size = new System.Drawing.Size(40, 45);
this.closeWindowBtn.TabIndex = 3;
this.closeWindowBtn.TabStop = false;
this.closeWindowBtn.Text = "";
@ -120,7 +120,7 @@ namespace Katteker.Gui
this.maximizeBtn.Location = new System.Drawing.Point(618, 0);
this.maximizeBtn.Margin = new System.Windows.Forms.Padding(0);
this.maximizeBtn.Name = "maximizeBtn";
this.maximizeBtn.Size = new System.Drawing.Size(40, 30);
this.maximizeBtn.Size = new System.Drawing.Size(40, 45);
this.maximizeBtn.TabIndex = 2;
this.maximizeBtn.TabStop = false;
this.maximizeBtn.Text = "□";
@ -133,7 +133,7 @@ namespace Katteker.Gui
this.titlebar.Font = new System.Drawing.Font("Segoe UI", 14.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.titlebar.Location = new System.Drawing.Point(123, 0);
this.titlebar.Name = "titlebar";
this.titlebar.Size = new System.Drawing.Size(452, 30);
this.titlebar.Size = new System.Drawing.Size(452, 45);
this.titlebar.TabIndex = 0;
this.titlebar.Text = "Updater";
this.titlebar.TextAlign = System.Drawing.ContentAlignment.MiddleCenter;
@ -148,7 +148,7 @@ namespace Katteker.Gui
this.minimizeBtn.Location = new System.Drawing.Point(578, 0);
this.minimizeBtn.Margin = new System.Windows.Forms.Padding(0);
this.minimizeBtn.Name = "minimizeBtn";
this.minimizeBtn.Size = new System.Drawing.Size(40, 30);
this.minimizeBtn.Size = new System.Drawing.Size(40, 45);
this.minimizeBtn.TabIndex = 1;
this.minimizeBtn.TabStop = false;
this.minimizeBtn.Text = "—";
@ -161,7 +161,7 @@ namespace Katteker.Gui
this.label1.Font = new System.Drawing.Font("Segoe UI Symbol", 18F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
this.label1.Location = new System.Drawing.Point(3, 0);
this.label1.Name = "label1";
this.label1.Size = new System.Drawing.Size(114, 30);
this.label1.Size = new System.Drawing.Size(114, 45);
this.label1.TabIndex = 4;
this.label1.Text = "⛽";
this.label1.TextAlign = System.Drawing.ContentAlignment.MiddleLeft;
@ -185,8 +185,8 @@ namespace Katteker.Gui
this.splitContainer3.Panel2.Controls.Add(this.progressBar1);
this.splitContainer3.Panel2.Controls.Add(this.closeBtn);
this.splitContainer3.Panel2.Controls.Add(this.updBtn);
this.splitContainer3.Size = new System.Drawing.Size(698, 404);
this.splitContainer3.SplitterDistance = 344;
this.splitContainer3.Size = new System.Drawing.Size(698, 389);
this.splitContainer3.SplitterDistance = 329;
this.splitContainer3.TabIndex = 7;
this.splitContainer3.TabStop = false;
//
@ -200,7 +200,7 @@ namespace Katteker.Gui
this.changelogBrowser.MinimumSize = new System.Drawing.Size(19, 18);
this.changelogBrowser.Name = "changelogBrowser";
this.changelogBrowser.ScriptErrorsSuppressed = true;
this.changelogBrowser.Size = new System.Drawing.Size(698, 344);
this.changelogBrowser.Size = new System.Drawing.Size(698, 329);
this.changelogBrowser.TabIndex = 7;
this.changelogBrowser.TabStop = false;
this.changelogBrowser.WebBrowserShortcutsEnabled = false;
@ -223,14 +223,12 @@ namespace Katteker.Gui
this.closeBtn.FlatAppearance.BorderColor = System.Drawing.Color.FromArgb(((int)(((byte)(171)))), ((int)(((byte)(171)))), ((int)(((byte)(171)))));
this.closeBtn.FlatAppearance.MouseDownBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(146)))), ((int)(((byte)(192)))), ((int)(((byte)(224)))));
this.closeBtn.FlatAppearance.MouseOverBackColor = System.Drawing.Color.FromArgb(((int)(((byte)(205)))), ((int)(((byte)(230)))), ((int)(((byte)(247)))));
this.closeBtn.FlatStyle = System.Windows.Forms.FlatStyle.Flat;
this.closeBtn.ForeColor = System.Drawing.SystemColors.ControlText;
this.closeBtn.Location = new System.Drawing.Point(507, 14);
this.closeBtn.Name = "closeBtn";
this.closeBtn.Size = new System.Drawing.Size(179, 30);
this.closeBtn.TabIndex = 7;
this.closeBtn.Text = "Close";
this.closeBtn.UseVisualStyleBackColor = false;
//
// updBtn
//
@ -263,7 +261,7 @@ namespace Katteker.Gui
//
// UpdateWindow
//
this.AutoScaleDimensions = new System.Drawing.SizeF(7F, 15F);
this.AutoScaleDimensions = new System.Drawing.SizeF(10F, 25F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(700, 440);
this.ControlBox = false;

View File

@ -1,59 +1,46 @@
using System;
using System.Drawing;
using System.IO;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using Katteker.Gui.Properties;
using Katteker.Changelog;
using Katteker.Properties;
using Katteker.Types;
namespace Katteker.Gui
namespace Katteker
{
public sealed partial class UpdateWindow : Form
internal sealed partial class UpdateWindow : Form
{
private readonly ReleaseEntry? _entry;
private readonly UpdateManager _updateManager;
private readonly ReleaseEntry _entry;
private const int HTCAPTION = 0x2;
private const int WM_NCLBUTTONDOWN = 0xA1;
/// <summary>
/// The Update Window
/// The Update Window
/// </summary>
public UpdateWindow(UpdateManager updateManager, ReleaseEntry entry)
internal UpdateWindow(UpdateManager updateManager, ReleaseEntry? entry)
{
_updateManager = updateManager;
_entry = entry;
Font = SystemFonts.MessageBoxFont;
Application.EnableVisualStyles();
if (Environment.OSVersion.Version.Major >= 6)
SetProcessDPIAware();
NativeMethods.SetProcessDPIAware();
InitializeComponent();
}
private string Changelog => _updateManager.ChangelogFilename;
private string PublishPath => _updateManager.UrlOrPath;
/// <inheritdoc />
/// <summary>
/// Clean up any resources being used.
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing)
{
components?.Dispose();
}
if (disposing) components?.Dispose();
base.Dispose(disposing);
}
[DllImport("User32.dll")]
private static extern bool ReleaseCapture();
[DllImport("User32.dll")]
private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
[DllImport("user32.dll")]
private static extern bool SetProcessDPIAware();
private void CloseBtn_Click(object sender, EventArgs e)
{
Close();
@ -76,9 +63,10 @@ namespace Katteker.Gui
MaximizeBtn_Click(sender, e);
return;
}
if (e.Button != MouseButtons.Left) return;
ReleaseCapture();
SendMessage(Handle, WM_NCLBUTTONDOWN, HTCAPTION, 0);
NativeMethods.ReleaseCapture();
NativeMethods.SendMessage(Handle, NativeMethods.WM_NCLBUTTONDOWN, NativeMethods.HTCAPTION, 0);
}
@ -96,31 +84,34 @@ namespace Katteker.Gui
private async void UpdateWindow_Load(object sender, EventArgs e)
{
var changelogContent = await ChangelogHelper.LoadChangelogAsync(Changelog, PublishPath).ConfigureAwait(false);
changelogContent = changelogContent.ChangelogAsHtml(Path.GetExtension(Changelog));
Invoke(new Action(() => changelogBrowser.DocumentText = changelogContent));
if (_entry == null)
var changelogContent = "No changelog provided.";
if (Changelog is not null)
{
Invoke(new Action(() => { WriteTitle(Resources.No_update_available); }));
var changelogFile = await ChangelogFile.LoadChangelogAsync(Changelog, PublishPath).ConfigureAwait(false);
changelogContent = changelogFile.AsHtml();
}
InvokeOnGui(() => changelogBrowser.DocumentText = changelogContent);
if (_entry is null)
{
WriteTitle(Resources.No_update_available);
}
else
{
var latest = _entry.Version;
Invoke(new Action(() =>
{
WriteTitle(Resources.You_can_update_to_Version + latest);
updBtn.Visible = true;
}));
var latest = _entry?.Version;
WriteTitle(Resources.You_can_update_to_Version + latest);
InvokeOnGui(() => updBtn.Visible = true);
}
}
private async void UpdBtn_Click(object sender, EventArgs e)
{
Invoke(new Action(() => progressBar1.Visible = true));
InvokeOnGui(() => progressBar1.Visible = true);
try
{
var progress = new Progress<int>(x => Invoke(new Action(() => { progressBar1.Value = x; })));
var progress = new Progress<int>(x => InvokeOnGui(() => progressBar1.Value = x));
await _updateManager.UpdateAppAsync(progress).ConfigureAwait(false);
WriteTitle(Resources.You_re_up_to_date);
@ -131,33 +122,48 @@ namespace Katteker.Gui
MessageBoxIcon.Question);
if (messResult == DialogResult.Yes)
{
DialogResult = DialogResult.OK;
Close();
InvokeOnGui(() =>
{
DialogResult = DialogResult.OK;
Close();
});
return;
}
}
catch (Exception ex)
{
MessageBox.Show(Resources.CouldNotUpdateYourApplication + Environment.NewLine + ex.Message, Gui.Properties.Resources.Updater, MessageBoxButtons.OK, MessageBoxIcon.Error);
MessageBox.Show(Resources.CouldNotUpdateYourApplication + Environment.NewLine + ex.Message,
Resources.Updater, MessageBoxButtons.OK, MessageBoxIcon.Error);
WriteTitle(Resources.Updater);
}
}
finally
InvokeOnGui(() =>
{
Invoke(new Action(() =>
{
progressBar1.Visible = false;
updBtn.Visible = false;
}));
}
progressBar1.Visible = false;
updBtn.Visible = false;
});
}
private void WriteTitle(string text)
{
Invoke(new Action(() =>
InvokeOnGui(() =>
{
Text = text;
titlebar.Text = text;
}));
});
}
private void InvokeOnGui(Action action)
{
if (Disposing || IsDisposed) return;
if (InvokeRequired)
{
Invoke(action);
}
else
{
action();
}
}
}
}

View File

@ -2,14 +2,15 @@
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
using Katteker.Gui.Properties;
using Katteker.Properties;
using Katteker.Types;
namespace Katteker.Gui
namespace Katteker
{
/// <summary>
/// The wrapper to add Squirrel-capability to older Programs.
/// The wrapper to add Katteker-capability to older Programs.
/// </summary>
public static class Wrapper
public static class UserInterface
{
private static UpdateManager _manager;
@ -26,7 +27,7 @@ namespace Katteker.Gui
/// <returns>Task</returns>
public static async Task CheckForUpdateAsync(bool isStartup)
{
if (_manager == null && !UpdateManager.TryCreate(out _manager))
if (_manager is null && !UpdateManager.TryCreate(out _manager))
{
if (!isStartup)
{
@ -37,8 +38,8 @@ namespace Katteker.Gui
return;
}
var releases = (await _manager.CheckForUpdateAsync().ConfigureAwait(false)).ToArray();
if (releases.Any() || !isStartup)
var releases = await _manager.CheckForUpdatesAsync().ConfigureAwait(false);
if (releases.Count > 0 || !isStartup)
{
var thread = new Thread(ThreadProcess);
thread.SetApartmentState(ApartmentState.STA);
@ -49,14 +50,12 @@ namespace Katteker.Gui
private static void ThreadProcess(object argument)
{
var entry = (ReleaseEntry) argument;
using (var window = new UpdateWindow(_manager, entry))
var entry = (ReleaseEntry)argument;
using var window = new UpdateWindow(_manager, entry);
var dialogResult = window.ShowDialog();
if (dialogResult == DialogResult.OK)
{
var dialogResult = window.ShowDialog();
if (dialogResult == DialogResult.OK)
{
_manager.RestartApp();
}
_manager.RestartApp();
}
}
}

View File

@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="NuGet.Core" publicKeyToken="31bf3856ad364e35" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-2.8.50926.602" newVersion="2.8.50926.602"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Mono.Cecil" publicKeyToken="0738eb9f132ed756" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-0.9.5.0" newVersion="0.9.5.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="DeltaCompressionDotNet.MsDelta" publicKeyToken="46b2138a390abf55" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-1.1.0.0" newVersion="1.1.0.0"/>
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="SharpCompress" publicKeyToken="afb0a02973931d96" culture="neutral"/>
<bindingRedirect oldVersion="0.0.0.0-0.19.2.0" newVersion="0.19.2.0"/>
</dependentAssembly>
</assemblyBinding>
</runtime>
<startup><supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/></startup></configuration>

View File

@ -0,0 +1,85 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="nunit" Version="3.13.0" />
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.8.3" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\Katteker\Katteker.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="testdata\Autofac.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Autofac.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\changelog.md">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Example.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Example.exe.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Example.vshost.exe">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Katteker.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Katteker.UserInterface.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Katteker.UserInterface.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Katteker.UserInterface.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Microsoft.Practices.ServiceLocation.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Microsoft.Practices.ServiceLocation.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.Autofac.Wpf.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.Autofac.Wpf.dll.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.Autofac.Wpf.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.Wpf.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.Wpf.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\Prism.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\squirrelHelperInfo.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="testdata\System.Windows.Interactivity.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@ -0,0 +1,71 @@
using Katteker.Utilities;
using System;
using System.IO;
using System.Reflection;
using NUnit.Framework;
using Semver;
namespace Katteker.Test
{
[TestFixture]
public class KattekerLibTest
{
private static readonly string BaseDir = AppDomain.CurrentDomain.BaseDirectory;
private static readonly string ExamplePath = Path.Combine(BaseDir, "testdata");
private static readonly string ExampleFile = Path.Combine(ExamplePath, "Example.exe");
private static readonly string AutofacFile = Path.Combine(ExamplePath, "Autofac.dll");
[Test]
public void Sha1ChecksumOfFile()
{
var actual = Utility.ComputeFileHash(ExampleFile);
const string expected = "maFpV7FK3EtnU2G5+q2nZ1E3YKY=";
Assert.AreEqual(expected, actual);
}
[Test]
public void CheckIfStringIsWebUrl()
{
const string test1 = "http://TolleUrl.de/Test";
const string test2 = "https://TolleUrl.de/Test";
const string test3 = "C:\\Test";
const string test4 = "furz";
Assert.True(Utility.IsWebUrl(test1));
Assert.True(Utility.IsWebUrl(test2));
Assert.False(Utility.IsWebUrl(test3));
Assert.Throws<UriFormatException>(() => Utility.IsWebUrl(test4));
}
[Test]
public void CheckRightAssemblyName()
{
const string expected = "Example";
var actual = Utility.GetApplicationName(Assembly.LoadFile(ExampleFile));
Assert.AreEqual(expected, actual);
}
[Test]
public void CheckAssemblyVersionStuff()
{
var expected = new Semver.SemVersion(3, 5);
var actual = VersionUtils.GetCurrentVersion(Assembly.LoadFile(AutofacFile));
Assert.AreEqual(expected, actual);
}
[Test]
public void CheckToSystemVersion()
{
var expected = new Version(1, 2, 3, 0);
var actual = new SemVersion(1, 2, 3, "alpha122").ToSystemVersion();
Assert.AreEqual(expected, actual);
}
[Test]
public void TestGetLocalAppDataDirectory()
{
var expected = Utility.GetLocalAppDataDirectory();
Assert.IsTrue(expected.Contains("AppData\\Local\\Programs"));
}
}
}

BIN
src/Katteker.Test/testdata/Autofac.dll vendored Normal file

Binary file not shown.

6923
src/Katteker.Test/testdata/Autofac.xml vendored Normal file

File diff suppressed because it is too large Load Diff

BIN
src/Katteker.Test/testdata/Example.exe vendored Normal file

Binary file not shown.

Binary file not shown.

Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More