merged from work
24
KattekerCreator/Exceptions/KattekerCreatorException.cs
Normal file
@ -0,0 +1,24 @@
|
||||
using System;
|
||||
using System.Runtime.Serialization;
|
||||
|
||||
namespace KattekerCreator.Exceptions
|
||||
{
|
||||
internal class KattekerCreatorException : Exception
|
||||
{
|
||||
public KattekerCreatorException()
|
||||
{
|
||||
}
|
||||
|
||||
public KattekerCreatorException(string message) : base(message)
|
||||
{
|
||||
}
|
||||
|
||||
public KattekerCreatorException(string message, Exception innerException) : base(message, innerException)
|
||||
{
|
||||
}
|
||||
|
||||
protected KattekerCreatorException(SerializationInfo info, StreamingContext context) : base(info, context)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
58
KattekerCreator/Helper/Log.cs
Normal file
@ -0,0 +1,58 @@
|
||||
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 (new ConsoleWithOtherColor())
|
||||
{
|
||||
ConsoleWithOtherColor.WriteLine($"{Info} [{DateTime.Now:G}] {text}");
|
||||
}
|
||||
}
|
||||
|
||||
public static void WriteErrorLine(string text)
|
||||
{
|
||||
using (new ConsoleWithOtherColor(ConsoleColor.DarkRed))
|
||||
{
|
||||
ConsoleWithOtherColor.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 static void WriteLine(string text)
|
||||
{
|
||||
Console.WriteLine(text);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (!disposing) return;
|
||||
if (_defaultColor != null) Console.ForegroundColor = _defaultColor.Value;
|
||||
}
|
||||
}
|
||||
}
|
157
KattekerCreator/Helper/Utils.cs
Normal file
@ -0,0 +1,157 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using KattekerCreator.Exceptions;
|
||||
using Minimatch;
|
||||
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 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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the signtool.exe command line. Returns "" if no certificate string is provided.
|
||||
/// </summary>
|
||||
/// <param name="certificate"></param>
|
||||
/// <param name="password"></param>
|
||||
/// <param name="filename"></param>
|
||||
/// <returns></returns>
|
||||
public static string GetSignToolCommandLine(string certificate, string password, string filename)
|
||||
{
|
||||
return string.IsNullOrWhiteSpace(certificate)
|
||||
? string.Empty
|
||||
: $"\"{GetSignTool()}\" {GetSignToolParameters(certificate, password, filename)}";
|
||||
}
|
||||
|
||||
public static string GetSignToolParameters(string certificate, string password, string filename)
|
||||
{
|
||||
return $"sign /fd SHA256 /t http://timestamp.digicert.com /f \"{certificate}\" /p {password} {filename}";
|
||||
}
|
||||
|
||||
public static string GetSignTool()
|
||||
{
|
||||
return Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "contrib", "signtool.exe");
|
||||
}
|
||||
|
||||
|
||||
public static void DeleteTempDir(string tempDir)
|
||||
{
|
||||
#if !DEBUG
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempDir, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//silently ignore
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
public static IList<FileInfo> EnumerateFiles(string path, IEnumerable<string> userdefinedFileExclusions = null)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(path)) throw new ArgumentNullException(nameof(path));
|
||||
var result = new DirectoryInfo(path).EnumerateFiles("*.*", SearchOption.AllDirectories).ToList();
|
||||
var minimatchOptions = new Options { AllowWindowsPaths = true };
|
||||
foreach (var pattern in FileExclusions(userdefinedFileExclusions))
|
||||
{
|
||||
var matcher = new Minimatcher(pattern, minimatchOptions);
|
||||
for (var index = result.Count - 1; index >= 0; index--)
|
||||
{
|
||||
if (matcher.IsMatch(result[index].Name))
|
||||
{
|
||||
result.Remove(result[index]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
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 "squirrelHelperInfo.json";
|
||||
yield return "Katteker.config";
|
||||
|
||||
if (userdefinedfileExclusions == null) yield break;
|
||||
foreach (var fileExclusion in userdefinedfileExclusions)
|
||||
{
|
||||
yield return fileExclusion;
|
||||
}
|
||||
}
|
||||
|
||||
public static void SignExecutable(string certificate, string password, string filename)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(certificate))
|
||||
{
|
||||
var exitCode = ExecuteProcess(GetSignTool(), GetSignToolParameters(certificate, password, filename));
|
||||
if (exitCode != 0) throw new KattekerCreatorException("AppStub could not signed.");
|
||||
}
|
||||
}
|
||||
|
||||
public static int ExecuteProcess(string executable, string arguments)
|
||||
{
|
||||
int exitCode;
|
||||
using (var p = new Process())
|
||||
{
|
||||
p.StartInfo = new ProcessStartInfo
|
||||
{
|
||||
FileName = executable,
|
||||
Arguments = arguments,
|
||||
UseShellExecute = false
|
||||
};
|
||||
var sw = Stopwatch.StartNew();
|
||||
p.Start();
|
||||
p.WaitForExit();
|
||||
exitCode = p.ExitCode;
|
||||
Log.WriteInfoLine($"{Path.GetFileName(executable)} has exited with exit code: {exitCode} (Took: {sw.ElapsedMilliseconds}ms)");
|
||||
}
|
||||
|
||||
return exitCode;
|
||||
}
|
||||
}
|
||||
}
|
283
KattekerCreator/IconExtractor/IconExtractor.cs
Normal file
@ -0,0 +1,283 @@
|
||||
/*
|
||||
* IconExtractor/IconUtil for .NET
|
||||
* Copyright (C) 2014 Tsuda Kageyu. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace TsudaKageyu
|
||||
{
|
||||
public class IconExtractor
|
||||
{
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Constants
|
||||
|
||||
// Flags for LoadLibraryEx().
|
||||
|
||||
private const uint LOAD_LIBRARY_AS_DATAFILE = 0x00000002;
|
||||
|
||||
// Resource types for EnumResourceNames().
|
||||
|
||||
private readonly static IntPtr RT_ICON = (IntPtr)3;
|
||||
private readonly static IntPtr RT_GROUP_ICON = (IntPtr)14;
|
||||
|
||||
private const int MAX_PATH = 260;
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Fields
|
||||
|
||||
private byte[][] iconData = null; // Binary data of each icon.
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Public properties
|
||||
|
||||
/// <summary>
|
||||
/// Gets the full path of the associated file.
|
||||
/// </summary>
|
||||
public string FileName
|
||||
{
|
||||
get;
|
||||
private set;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the count of the icons in the associated file.
|
||||
/// </summary>
|
||||
public int Count
|
||||
{
|
||||
get { return iconData.Length; }
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the IconExtractor class from the specified file name.
|
||||
/// </summary>
|
||||
/// <param name="fileName">The file to extract icons from.</param>
|
||||
public IconExtractor(string fileName)
|
||||
{
|
||||
Initialize(fileName);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts an icon from the file.
|
||||
/// </summary>
|
||||
/// <param name="index">Zero based index of the icon to be extracted.</param>
|
||||
/// <returns>A System.Drawing.Icon object.</returns>
|
||||
/// <remarks>Always returns new copy of the Icon. It should be disposed by the user.</remarks>
|
||||
public Icon GetIcon(int index)
|
||||
{
|
||||
if (index < 0 || Count <= index)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
|
||||
// Create an Icon from the .ico file in memory.
|
||||
|
||||
using (var ms = new MemoryStream(iconData[index]))
|
||||
{
|
||||
return new Icon(ms);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extracts all the icons from the file.
|
||||
/// </summary>
|
||||
/// <returns>An array of System.Drawing.Icon objects.</returns>
|
||||
/// <remarks>Always returns new copies of the Icons. They should be disposed by the user.</remarks>
|
||||
public Icon[] GetAllIcons()
|
||||
{
|
||||
var icons = new List<Icon>();
|
||||
for (int i = 0; i < Count; ++i)
|
||||
icons.Add(GetIcon(i));
|
||||
|
||||
return icons.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Save an icon to the specified output Stream.
|
||||
/// </summary>
|
||||
/// <param name="index">Zero based index of the icon to be saved.</param>
|
||||
/// <param name="outputStream">The Stream to save to.</param>
|
||||
public void Save(int index, Stream outputStream)
|
||||
{
|
||||
if (index < 0 || Count <= index)
|
||||
throw new ArgumentOutOfRangeException("index");
|
||||
|
||||
if (outputStream == null)
|
||||
throw new ArgumentNullException("outputStream");
|
||||
|
||||
var data = iconData[index];
|
||||
outputStream.Write(data, 0, data.Length);
|
||||
}
|
||||
|
||||
private void Initialize(string fileName)
|
||||
{
|
||||
if (fileName == null)
|
||||
throw new ArgumentNullException("fileName");
|
||||
|
||||
IntPtr hModule = IntPtr.Zero;
|
||||
try
|
||||
{
|
||||
hModule = NativeMethods.LoadLibraryEx(fileName, IntPtr.Zero, LOAD_LIBRARY_AS_DATAFILE);
|
||||
if (hModule == IntPtr.Zero)
|
||||
throw new Win32Exception();
|
||||
|
||||
FileName = GetFileName(hModule);
|
||||
|
||||
// Enumerate the icon resource and build .ico files in memory.
|
||||
|
||||
var tmpData = new List<byte[]>();
|
||||
|
||||
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
|
||||
|
||||
// RT_GROUP_ICON resource consists of a GRPICONDIR and GRPICONDIRENTRY's.
|
||||
|
||||
var dir = GetDataFromResource(hModule, RT_GROUP_ICON, name);
|
||||
|
||||
// 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)
|
||||
len += BitConverter.ToInt32(dir, 6 + 14 * i + 8); // GRPICONDIRENTRY.dwBytesInRes
|
||||
|
||||
using (var dst = new BinaryWriter(new MemoryStream(len)))
|
||||
{
|
||||
// Copy GRPICONDIR to ICONDIR.
|
||||
|
||||
dst.Write(dir, 0, 6);
|
||||
|
||||
int picOffset = 6 + 16 * count; // sizeof(ICONDIR) + sizeof(ICONDIRENTRY) * count
|
||||
|
||||
for (int i = 0; i < count; ++i)
|
||||
{
|
||||
// Load the picture.
|
||||
|
||||
ushort id = BitConverter.ToUInt16(dir, 6 + 14 * i + 12); // GRPICONDIRENTRY.nID
|
||||
var pic = GetDataFromResource(hModule, RT_ICON, (IntPtr)id);
|
||||
|
||||
// Copy GRPICONDIRENTRY to ICONDIRENTRY.
|
||||
|
||||
dst.Seek(6 + 16 * i, SeekOrigin.Begin);
|
||||
|
||||
dst.Write(dir, 6 + 14 * i, 8); // First 8bytes are identical.
|
||||
dst.Write(pic.Length); // ICONDIRENTRY.dwBytesInRes
|
||||
dst.Write(picOffset); // ICONDIRENTRY.dwImageOffset
|
||||
|
||||
// Copy a picture.
|
||||
|
||||
dst.Seek(picOffset, SeekOrigin.Begin);
|
||||
dst.Write(pic, 0, pic.Length);
|
||||
|
||||
picOffset += pic.Length;
|
||||
}
|
||||
|
||||
tmpData.Add(((MemoryStream)dst.BaseStream).ToArray());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
NativeMethods.EnumResourceNames(hModule, RT_GROUP_ICON, callback, IntPtr.Zero);
|
||||
|
||||
iconData = tmpData.ToArray();
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (hModule != IntPtr.Zero)
|
||||
NativeMethods.FreeLibrary(hModule);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] GetDataFromResource(IntPtr hModule, IntPtr type, IntPtr name)
|
||||
{
|
||||
// Load the binary data from the specified resource.
|
||||
|
||||
IntPtr hResInfo = NativeMethods.FindResource(hModule, name, type);
|
||||
if (hResInfo == IntPtr.Zero)
|
||||
throw new Win32Exception();
|
||||
|
||||
IntPtr hResData = NativeMethods.LoadResource(hModule, hResInfo);
|
||||
if (hResData == IntPtr.Zero)
|
||||
throw new Win32Exception();
|
||||
|
||||
IntPtr pResData = NativeMethods.LockResource(hResData);
|
||||
if (pResData == IntPtr.Zero)
|
||||
throw new Win32Exception();
|
||||
|
||||
uint size = NativeMethods.SizeofResource(hModule, hResInfo);
|
||||
if (size == 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
byte[] buf = new byte[size];
|
||||
Marshal.Copy(pResData, buf, 0, buf.Length);
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
private string GetFileName(IntPtr hModule)
|
||||
{
|
||||
// Alternative to GetModuleFileName() for the module loaded with
|
||||
// LOAD_LIBRARY_AS_DATAFILE option.
|
||||
|
||||
// Get the file name in the format like:
|
||||
// "\\Device\\HarddiskVolume2\\Windows\\System32\\shell32.dll"
|
||||
|
||||
string fileName;
|
||||
{
|
||||
var buf = new StringBuilder(MAX_PATH);
|
||||
int len = NativeMethods.GetMappedFileName(
|
||||
NativeMethods.GetCurrentProcess(), hModule, buf, buf.Capacity);
|
||||
if (len == 0)
|
||||
throw new Win32Exception();
|
||||
|
||||
fileName = buf.ToString();
|
||||
}
|
||||
|
||||
// Convert the device name to drive name like:
|
||||
// "C:\\Windows\\System32\\shell32.dll"
|
||||
|
||||
for (char c = 'A'; c <= 'Z'; ++c)
|
||||
{
|
||||
var drive = c + ":";
|
||||
var buf = new StringBuilder(MAX_PATH);
|
||||
int len = NativeMethods.QueryDosDevice(drive, buf, buf.Capacity);
|
||||
if (len == 0)
|
||||
continue;
|
||||
|
||||
var devPath = buf.ToString();
|
||||
if (fileName.StartsWith(devPath))
|
||||
return (drive + fileName.Substring(devPath.Length));
|
||||
}
|
||||
|
||||
return fileName;
|
||||
}
|
||||
}
|
||||
}
|
202
KattekerCreator/IconExtractor/IconUtil.cs
Normal file
@ -0,0 +1,202 @@
|
||||
/*
|
||||
* IconExtractor/IconUtil for .NET
|
||||
* Copyright (C) 2014 Tsuda Kageyu. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
|
||||
namespace TsudaKageyu
|
||||
{
|
||||
public static class IconUtil
|
||||
{
|
||||
private delegate byte[] GetIconDataDelegate(Icon icon);
|
||||
|
||||
static GetIconDataDelegate getIconData;
|
||||
|
||||
static IconUtil()
|
||||
{
|
||||
// Create a dynamic method to access Icon.iconData private field.
|
||||
|
||||
var dm = new DynamicMethod(
|
||||
"GetIconData", typeof(byte[]), new Type[] { typeof(Icon) }, typeof(Icon));
|
||||
var fi = typeof(Icon).GetField(
|
||||
"iconData", BindingFlags.Instance | BindingFlags.NonPublic);
|
||||
var gen = dm.GetILGenerator();
|
||||
gen.Emit(OpCodes.Ldarg_0);
|
||||
gen.Emit(OpCodes.Ldfld, fi);
|
||||
gen.Emit(OpCodes.Ret);
|
||||
|
||||
getIconData = (GetIconDataDelegate)dm.CreateDelegate(typeof(GetIconDataDelegate));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Split an Icon consists of multiple icons into an array of Icon each
|
||||
/// consists of single icons.
|
||||
/// </summary>
|
||||
/// <param name="icon">A System.Drawing.Icon to be split.</param>
|
||||
/// <returns>An array of System.Drawing.Icon.</returns>
|
||||
public static Icon[] Split(Icon icon)
|
||||
{
|
||||
if (icon == null)
|
||||
throw new ArgumentNullException("icon");
|
||||
|
||||
// Get an .ico file in memory, then split it into separate icons.
|
||||
|
||||
var src = GetIconData(icon);
|
||||
|
||||
var splitIcons = new List<Icon>();
|
||||
{
|
||||
int count = BitConverter.ToUInt16(src, 4);
|
||||
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
int length = BitConverter.ToInt32(src, 6 + 16 * i + 8); // ICONDIRENTRY.dwBytesInRes
|
||||
int offset = BitConverter.ToInt32(src, 6 + 16 * i + 12); // ICONDIRENTRY.dwImageOffset
|
||||
|
||||
using (var dst = new BinaryWriter(new MemoryStream(6 + 16 + length)))
|
||||
{
|
||||
// Copy ICONDIR and set idCount to 1.
|
||||
|
||||
dst.Write(src, 0, 4);
|
||||
dst.Write((short)1);
|
||||
|
||||
// Copy ICONDIRENTRY and set dwImageOffset to 22.
|
||||
|
||||
dst.Write(src, 6 + 16 * i, 12); // ICONDIRENTRY except dwImageOffset
|
||||
dst.Write(22); // ICONDIRENTRY.dwImageOffset
|
||||
|
||||
// Copy a picture.
|
||||
|
||||
dst.Write(src, offset, length);
|
||||
|
||||
// Create an icon from the in-memory file.
|
||||
|
||||
dst.BaseStream.Seek(0, SeekOrigin.Begin);
|
||||
splitIcons.Add(new Icon(dst.BaseStream));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return splitIcons.ToArray();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts an Icon to a GDI+ Bitmap preserving the transparent area.
|
||||
/// </summary>
|
||||
/// <param name="icon">An System.Drawing.Icon to be converted.</param>
|
||||
/// <returns>A System.Drawing.Bitmap Object.</returns>
|
||||
public static Bitmap ToBitmap(Icon icon)
|
||||
{
|
||||
if (icon == null)
|
||||
throw new ArgumentNullException("icon");
|
||||
|
||||
// Quick workaround: Create an .ico file in memory, then load it as a Bitmap.
|
||||
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
icon.Save(ms);
|
||||
using (var bmp = (Bitmap)Image.FromStream(ms))
|
||||
{
|
||||
return new Bitmap(bmp);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the bit depth of an Icon.
|
||||
/// </summary>
|
||||
/// <param name="icon">An System.Drawing.Icon object.</param>
|
||||
/// <returns>Bit depth of the icon.</returns>
|
||||
/// <remarks>
|
||||
/// This method takes into account the PNG header.
|
||||
/// If the icon has multiple variations, this method returns the bit
|
||||
/// depth of the first variation.
|
||||
/// </remarks>
|
||||
public static int GetBitCount(Icon icon)
|
||||
{
|
||||
if (icon == null)
|
||||
throw new ArgumentNullException("icon");
|
||||
|
||||
// Get an .ico file in memory, then read the header.
|
||||
|
||||
var data = GetIconData(icon);
|
||||
if (data.Length >= 51
|
||||
&& data[22] == 0x89 && data[23] == 0x50 && data[24] == 0x4e && data[25] == 0x47
|
||||
&& data[26] == 0x0d && data[27] == 0x0a && data[28] == 0x1a && data[29] == 0x0a
|
||||
&& data[30] == 0x00 && data[31] == 0x00 && data[32] == 0x00 && data[33] == 0x0d
|
||||
&& data[34] == 0x49 && data[35] == 0x48 && data[36] == 0x44 && data[37] == 0x52)
|
||||
{
|
||||
// The picture is PNG. Read IHDR chunk.
|
||||
|
||||
switch (data[47])
|
||||
{
|
||||
case 0:
|
||||
return data[46];
|
||||
case 2:
|
||||
return data[46] * 3;
|
||||
case 3:
|
||||
return data[46];
|
||||
case 4:
|
||||
return data[46] * 2;
|
||||
case 6:
|
||||
return data[46] * 4;
|
||||
default:
|
||||
// NOP
|
||||
break;
|
||||
}
|
||||
}
|
||||
else if (data.Length >= 22)
|
||||
{
|
||||
// The picture is not PNG. Read ICONDIRENTRY structure.
|
||||
|
||||
return BitConverter.ToUInt16(data, 12);
|
||||
}
|
||||
|
||||
throw new ArgumentException("The icon is corrupt. Couldn't read the header.", "icon");
|
||||
}
|
||||
|
||||
private static byte[] GetIconData(Icon icon)
|
||||
{
|
||||
var data = getIconData(icon);
|
||||
if (data != null)
|
||||
{
|
||||
return data;
|
||||
}
|
||||
else
|
||||
{
|
||||
using (var ms = new MemoryStream())
|
||||
{
|
||||
icon.Save(ms);
|
||||
return ms.ToArray();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
81
KattekerCreator/IconExtractor/NativeMethods.cs
Normal file
@ -0,0 +1,81 @@
|
||||
/*
|
||||
* IconExtractor/IconUtil for .NET
|
||||
* Copyright (C) 2014 Tsuda Kageyu. All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
|
||||
* TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
|
||||
* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER
|
||||
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
|
||||
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
|
||||
* PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
|
||||
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
|
||||
* NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Security;
|
||||
using System.Text;
|
||||
|
||||
namespace TsudaKageyu
|
||||
{
|
||||
internal static class NativeMethods
|
||||
{
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr LoadLibraryEx(string lpFileName, IntPtr hFile, uint dwFlags);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool FreeLibrary(IntPtr hModule);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern bool EnumResourceNames(IntPtr hModule, IntPtr lpszType, ENUMRESNAMEPROC lpEnumFunc, IntPtr lParam);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr FindResource(IntPtr hModule, IntPtr lpName, IntPtr lpType);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr LoadResource(IntPtr hModule, IntPtr hResInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr LockResource(IntPtr hResData);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern uint SizeofResource(IntPtr hModule, IntPtr hResInfo);
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern IntPtr GetCurrentProcess();
|
||||
|
||||
[DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern int QueryDosDevice(string lpDeviceName, StringBuilder lpTargetPath, int ucchMax);
|
||||
|
||||
[DllImport("psapi.dll", SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
public static extern int GetMappedFileName(IntPtr hProcess, IntPtr lpv, StringBuilder lpFilename, int nSize);
|
||||
}
|
||||
|
||||
[UnmanagedFunctionPointer(CallingConvention.Winapi, SetLastError = true, CharSet = CharSet.Unicode)]
|
||||
[SuppressUnmanagedCodeSecurity]
|
||||
internal delegate bool ENUMRESNAMEPROC(IntPtr hModule, IntPtr lpszType, IntPtr lpszName, IntPtr lParam);
|
||||
}
|
75
KattekerCreator/KattekerCreator.csproj
Normal file
@ -0,0 +1,75 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<ApplicationIcon>app.ico</ApplicationIcon>
|
||||
<PublishTrimmed>true</PublishTrimmed>
|
||||
<PublishReadyToRun>true</PublishReadyToRun>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|AnyCPU'">
|
||||
<OutputPath>..\bin\Debug\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|AnyCPU'">
|
||||
<OutputPath>..\bin\Release\</OutputPath>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="nsis\**\*.*">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="contrib\AppStub.exe.config" />
|
||||
<None Remove="contrib\AppStub.pdb" />
|
||||
<None Remove="SetupTemplate.tt" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="SetupTemplate.tt">
|
||||
<LastGenOutput>SetupTemplate.cs</LastGenOutput>
|
||||
<Generator>TextTemplatingFilePreprocessor</Generator>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="McMaster.Extensions.CommandLineUtils" Version="2.4.4" />
|
||||
<PackageReference Include="System.Drawing.Common" Version="4.7.0" />
|
||||
<PackageReference Include="Vestris.ResourceLib" Version="2.1.0" />
|
||||
<PackageReference Include="YamlDotNet.NetCore" Version="1.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Katteker\Katteker.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{508349b6-6b84-4df5-91f0-309beebad82d}" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="SetupTemplate.cs">
|
||||
<DependentUpon>SetupTemplate.tt</DependentUpon>
|
||||
<DesignTime>True</DesignTime>
|
||||
<AutoGen>True</AutoGen>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="contrib\AppStub.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="contrib\LoadingBar_Icon.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="contrib\signtool.exe">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="contrib\uninstall.ico">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
</Project>
|
4
KattekerCreator/KattekerCreatorCore.csproj
Normal file
@ -0,0 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup />
|
||||
</Project>
|
178
KattekerCreator/Program.cs
Normal file
@ -0,0 +1,178 @@
|
||||
using Katteker;
|
||||
using KattekerCreator.Helper;
|
||||
using KattekerCreator.Types;
|
||||
using McMaster.Extensions.CommandLineUtils;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace KattekerCreator
|
||||
{
|
||||
internal class Program : ProgramArguments
|
||||
{
|
||||
private static readonly string BaseDirectory = AppDomain.CurrentDomain.BaseDirectory;
|
||||
private static string MakeNsis => Path.Combine(BaseDirectory, "nsis", "makensis.exe");
|
||||
private AssemblyFileInfo _assemblyFileInfo;
|
||||
private TemporaryDirectory _tempDir;
|
||||
private Releases _releases;
|
||||
|
||||
static int Main(string[] args)
|
||||
{
|
||||
return CommandLineApplication.Execute<Program>(args);
|
||||
}
|
||||
|
||||
protected override int OnExecute(CommandLineApplication app)
|
||||
{
|
||||
//Override commandline arguments, if 'ConfigurationPath' is set.
|
||||
if (TryReadConfigFile(ConfigurationPath, out var dictionary))
|
||||
{
|
||||
OverridePropertyValues(this, dictionary);
|
||||
}
|
||||
|
||||
//Create temp-dir
|
||||
using (_tempDir = TemporaryDirectory.Create())
|
||||
{
|
||||
_releases = new Releases(OutputDir);
|
||||
|
||||
//Modify AppStub
|
||||
var appStubFile = ModifyAppStub();
|
||||
//Acquire infos from Executable.
|
||||
_assemblyFileInfo = new AssemblyFileInfo(ProgramFile, Version, _tempDir.Path);
|
||||
var configFile = CreateConfigFile();
|
||||
|
||||
//Generate NSIS-Script
|
||||
var additionalFiles = new[]
|
||||
{
|
||||
new PhysicalFile(appStubFile, Path.GetFileName(ProgramFile)),
|
||||
new PhysicalFile(configFile, Path.Combine($"app-{_assemblyFileInfo.AssemblyVersion}", Path.GetFileName(configFile) ?? string.Empty))
|
||||
};
|
||||
var templateFile = GenerateNsisTemplate(additionalFiles);
|
||||
//Start makensis.exe
|
||||
var setupFilePath = CompileSetupScript(templateFile);
|
||||
//TODO Sign setup
|
||||
Utils.SignExecutable(CertificatePath, CertificatePassword, setupFilePath);
|
||||
//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 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(OutputDir)) Directory.CreateDirectory(OutputDir);
|
||||
if (!string.IsNullOrEmpty(ChangeLog))
|
||||
{
|
||||
var changeLogFilename = Path.GetFileName(ChangeLog);
|
||||
|
||||
if (!File.Exists(ChangeLog)) throw new FileNotFoundException(ChangeLog);
|
||||
File.Copy(ChangeLog, Path.Combine(OutputDir, changeLogFilename), true);
|
||||
}
|
||||
File.Copy(setupFilePath, Path.Combine(OutputDir, setupFile), true);
|
||||
}
|
||||
|
||||
|
||||
private string ModifyAppStub()
|
||||
{
|
||||
var baseFile = Path.Combine(BaseDirectory, "contrib", Constants.ExecutionStub);
|
||||
var targetFile = Path.Combine(_tempDir.Path, Constants.ExecutionStub);
|
||||
File.Copy(baseFile, targetFile);
|
||||
Utils.CopyResources(ProgramFile, targetFile);
|
||||
Utils.SignExecutable(CertificatePath, CertificatePassword, targetFile);
|
||||
return targetFile;
|
||||
}
|
||||
|
||||
private string CreateConfigFile()
|
||||
{
|
||||
var pathToFile = Path.Combine(_tempDir.Path, Constants.KattekerConfig);
|
||||
var kattekerConfig = new KattekerConfig
|
||||
{
|
||||
Publish = PublishDir ?? OutputDir,
|
||||
Changelog = Path.GetFileName(ChangeLog),
|
||||
Channel = Channel
|
||||
};
|
||||
kattekerConfig.WriteToFile(pathToFile);
|
||||
return pathToFile;
|
||||
}
|
||||
|
||||
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 assemblyName = Path.GetFileNameWithoutExtension(_assemblyFileInfo.FileInfo.Name);
|
||||
var outFile = Path.Combine(_tempDir.Path, GenerateFilename(assemblyName, _assemblyFileInfo.AssemblyVersion.ToString(), "nsi"));
|
||||
var setupTemplate = new SetupTemplate
|
||||
{
|
||||
Executable = _assemblyFileInfo.FileInfo.Name,
|
||||
AssemblyName = assemblyName,
|
||||
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 = Channel
|
||||
};
|
||||
var path = Path.GetDirectoryName(ProgramFile) ?? string.Empty;
|
||||
setupTemplate.Files.AddRange(additionalFiles);
|
||||
var files = Utils.EnumerateFiles(path, Filter).ToArray();
|
||||
setupTemplate.InstallSize = (long)Math.Floor(files.Sum(x => x.Length) / 1024f);
|
||||
setupTemplate.Files.AddRange(files.Select(x => new PhysicalFile(x.FullName, x.FullName.Replace(path, $"app-{_assemblyFileInfo.AssemblyVersion}"))));
|
||||
var transformText = setupTemplate.TransformText();
|
||||
File.WriteAllText(outFile, transformText);
|
||||
return outFile;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Log.WriteErrorLine(e.Message);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private static string CompileSetupScript(string templateFile)
|
||||
{
|
||||
if (!File.Exists(MakeNsis)) throw new FileNotFoundException("NSIS not installed properly.");
|
||||
var exitCode = Utils.ExecuteProcess(MakeNsis, $"\"{templateFile}\"");
|
||||
|
||||
if (exitCode != 0) throw new Exception($"{Path.GetFileName(MakeNsis)} has exited with exit code: {exitCode}");
|
||||
return Path.ChangeExtension(templateFile, "exe");
|
||||
}
|
||||
|
||||
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 CopyAsSetup(string setupFilePath, ReleaseEntry releaseEntry)
|
||||
{
|
||||
if (!_releases.IsLatestEntry(releaseEntry)) return;
|
||||
var target = Path.Combine(OutputDir, Constants.SetupFile);
|
||||
File.Delete(target);
|
||||
File.Copy(setupFilePath, target);
|
||||
}
|
||||
}
|
||||
}
|
94
KattekerCreator/ProgramArguments.cs
Normal file
@ -0,0 +1,94 @@
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel.DataAnnotations;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using McMaster.Extensions.CommandLineUtils;
|
||||
|
||||
namespace KattekerCreator
|
||||
{
|
||||
[Command(Name = "KattekerCreator", Description = "Creates Installation and Update packages.")]
|
||||
[HelpOption("-?")]
|
||||
public abstract class ProgramArguments
|
||||
{
|
||||
private string _changeLog;
|
||||
private string _programFile;
|
||||
private string _outputDir;
|
||||
|
||||
[Argument(0, Description = "Path to the program file")]
|
||||
[FileExists]
|
||||
[Required]
|
||||
public string ProgramFile
|
||||
{
|
||||
get => _programFile;
|
||||
set => _programFile = Path.GetFullPath(value);
|
||||
}
|
||||
|
||||
[Option("-L|--changelog", Description = "Path of the changelog file")]
|
||||
[FileExists]
|
||||
public string ChangeLog
|
||||
{
|
||||
get => _changeLog;
|
||||
set => _changeLog = Path.GetFullPath(value);
|
||||
}
|
||||
|
||||
[Option("-C|--channel", Description = "Channel of releasing")]
|
||||
public string Channel { get; set; }
|
||||
|
||||
[Option("-O|--output", Description = "Directory for the output")]
|
||||
public string OutputDir
|
||||
{
|
||||
get => _outputDir;
|
||||
set => _outputDir = Path.GetFullPath(value);
|
||||
}
|
||||
|
||||
[Option("-P|--publish", Description = "Path for output from the point of view of the application")]
|
||||
public string PublishDir { get; set; }
|
||||
|
||||
[Option("-V|--version", Description = "Override version number of the application")]
|
||||
public string Version { get; set; }
|
||||
|
||||
[Option("-F|--filter", Description = "Filter parameter. Supports minimatch pattern. (see: https://bit.ly/2EhFoP7)")]
|
||||
public string FilterAsString { get; set; }
|
||||
|
||||
[Option("-S|--sign", Description = "Sign setup with certificate")]
|
||||
public string CertificatePath { get; set; }
|
||||
|
||||
[Option("-Sp|--signPassword", Description = "Password for certificate, if necessary")]
|
||||
public string CertificatePassword { get; set; }
|
||||
|
||||
[Option("-G|--config", Description = "Path to the configuration file. Configured settings in file will override all other settings.")]
|
||||
[FileExists]
|
||||
protected string ConfigurationPath { get; set; }
|
||||
|
||||
protected abstract int OnExecute(CommandLineApplication app);
|
||||
|
||||
protected IEnumerable<string> Filter => string.IsNullOrWhiteSpace(FilterAsString) ? Enumerable.Empty<string>() : FilterAsString.Split(';');
|
||||
|
||||
public static void OverridePropertyValues(object obj, IDictionary<string, string> dictionary)
|
||||
{
|
||||
var properties = obj.GetType().GetProperties().Where(x => x.CustomAttributes.Any(y => y.AttributeType == typeof(OptionAttribute)));
|
||||
foreach (var property in properties)
|
||||
{
|
||||
if (dictionary.TryGetValue(property.Name, out var value))
|
||||
{
|
||||
property.SetValue(obj, value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryReadConfigFile(string configurationPath, out IDictionary<string, string> args)
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(configurationPath) && File.Exists(configurationPath))
|
||||
{
|
||||
var contents = File.ReadAllText(configurationPath);
|
||||
var deserializer = new YamlDotNet.Serialization.DeserializerBuilder().Build();
|
||||
args = deserializer.Deserialize<Dictionary<string, string>>(contents);
|
||||
return true;
|
||||
}
|
||||
|
||||
args = default;
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
<?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>netcoreapp3.0</TargetFramework>
|
||||
<PublishDir>\\srv-et01\e$\BuildTools\Katteker</PublishDir>
|
||||
<RuntimeIdentifier>win-x64</RuntimeIdentifier>
|
||||
<SelfContained>true</SelfContained>
|
||||
<_IsPortable>false</_IsPortable>
|
||||
</PropertyGroup>
|
||||
</Project>
|
8
KattekerCreator/Properties/launchSettings.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"profiles": {
|
||||
"KattekerCreator": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "\"E:\\BuildTools\\Katteker\\KattekerCreator.exe\" \"$(build.artifactstagingdirectory)\\bin\\$(BuildConfiguration)\\TfsMigrationTool.exe\" -O \"\\\\srv-lsimctrl01\\Squirrel\\TfsMigrationTool\" -P \"https://srv-lsimctrl01.enercon.de/squirrel/TfsMigrationTool\" -F \"**\\*.xml\" -S \"E:\\BuildTools\\certificate\\WRD_Code_Signing_Certificate_2019.pfx\" -Sp dpLRlzn7.Q,S"
|
||||
}
|
||||
}
|
||||
}
|
53
KattekerCreator/SetupTemplate.Code.cs
Normal file
@ -0,0 +1,53 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Katteker;
|
||||
using KattekerCreator.Types;
|
||||
using Semver;
|
||||
|
||||
namespace KattekerCreator
|
||||
{
|
||||
public partial class SetupTemplate
|
||||
{
|
||||
public string AppName
|
||||
{
|
||||
get => _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; }
|
||||
public string AssemblyName { 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());
|
||||
}
|
||||
}
|
||||
}
|
516
KattekerCreator/SetupTemplate.cs
Normal file
@ -0,0 +1,516 @@
|
||||
// ------------------------------------------------------------------------------
|
||||
// <auto-generated>
|
||||
// This code was generated by a tool.
|
||||
// Runtime Version: 16.0.0.0
|
||||
//
|
||||
// Changes to this file may cause incorrect behavior and will be lost if
|
||||
// the code is regenerated.
|
||||
// </auto-generated>
|
||||
// ------------------------------------------------------------------------------
|
||||
namespace KattekerCreator
|
||||
{
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Collections.Generic;
|
||||
using System;
|
||||
|
||||
/// <summary>
|
||||
/// Class to produce the template output
|
||||
/// </summary>
|
||||
|
||||
#line 1 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
|
||||
public partial class SetupTemplate : SetupTemplateBase
|
||||
{
|
||||
#line hidden
|
||||
/// <summary>
|
||||
/// Create the template output
|
||||
/// </summary>
|
||||
public virtual string TransformText()
|
||||
{
|
||||
this.Write("Unicode true\r\nManifestDPIAware true\r\n!define APPNAME \"");
|
||||
|
||||
#line 8 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(AppName));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\n!define EXECUTABLE \"");
|
||||
|
||||
#line 9 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(Executable));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\n!define COMPANYNAME \"");
|
||||
|
||||
#line 10 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(CompanyName));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\n!define DESCRIPTION \"");
|
||||
|
||||
#line 11 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(Description));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\n!define ASSEMBLYNAME \"");
|
||||
|
||||
#line 12 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(AssemblyName));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\n!define VERSION ");
|
||||
|
||||
#line 13 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(Version.ToString()));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n!define HELPURL ");
|
||||
|
||||
#line 14 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(HelpUrl));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n!define INSTALLSIZE ");
|
||||
|
||||
#line 15 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(InstallSize));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n!define ISMANAGED ");
|
||||
|
||||
#line 16 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(IsManaged ? 1 : 0));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n; exampleCmd: makensis.exe /DVERSION=1.0.0.5 /DNAME=WpfApp1 Setup.nsi\r\n\r\nName \"" +
|
||||
"${APPNAME}\"\r\nOutFile \"");
|
||||
|
||||
#line 20 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(OutFile));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\nInstallDir \"$LOCALAPPDATA\\Programs\\${ASSEMBLYNAME}\"\r\nRequestExecutionLevel use" +
|
||||
"r\r\nSetCompressor /SOLID lzma\r\nSilentUnInstall silent\r\n; Subcaption 3 \" \"\r\nXPStyl" +
|
||||
"e on\r\nAutoCloseWindow true\r\nChangeUI all \"");
|
||||
|
||||
#line 28 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(UserInterface));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\nIcon \"");
|
||||
|
||||
#line 29 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(IconPath));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\"\r\nUninstallIcon \"${NSISDIR}\\Contrib\\Graphics\\Icons\\nsis3-uninstall.ico\"\r\nShowIns" +
|
||||
"tDetails nevershow \r\nShowUninstDetails nevershow \r\nBrandingText \"${COMPANYNAME}\"" +
|
||||
"\r\n\r\nVIProductVersion ");
|
||||
|
||||
#line 35 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(LegacyVersion.ToString(4)));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write(@"
|
||||
VIAddVersionKey ProductName ""${APPNAME}""
|
||||
VIAddVersionKey Comments """"
|
||||
VIAddVersionKey CompanyName ""${COMPANYNAME}""
|
||||
VIAddVersionKey LegalCopyright ""${COMPANYNAME}""
|
||||
VIAddVersionKey FileDescription ""${DESCRIPTION}""
|
||||
VIAddVersionKey FileVersion ""${VERSION}""
|
||||
VIAddVersionKey ProductVersion ""${VERSION}""
|
||||
VIAddVersionKey OriginalFilename """);
|
||||
|
||||
#line 43 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture(OutFile));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write(@"""
|
||||
|
||||
;--------------------------------
|
||||
; The stuff to install
|
||||
Section ""install"" ;No components page, name is not important
|
||||
DetailPrint 'Installing ${APPNAME}. Please wait...'
|
||||
SetShellVarContext current
|
||||
SetDetailsPrint None
|
||||
IfSilent +2
|
||||
RMDir /r $INSTDIR
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Create sub-directories
|
||||
");
|
||||
|
||||
#line 56 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
foreach(var directory in Directories) {
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 56 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture($" CreateDirectory \"$INSTDIR\\{directory}\"{Environment.NewLine}"));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 56 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n ; Put file there\r\n");
|
||||
|
||||
#line 59 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
foreach(var file in Files) {
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 59 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
this.Write(this.ToStringHelper.ToStringWithCulture($" File \"/oname={file.Target}\" \"{file.Source}\"{Environment.NewLine}"));
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
|
||||
#line 59 "C:\Strukturberechnung_del\Repos\Katteker\KattekerCreator\SetupTemplate.tt"
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
this.Write("\r\n WriteUninstaller \"$INSTDIR\\uninstall.exe\"\r\n ; Desktop\r\n CreateShortCu" +
|
||||
"t \"$DESKTOP\\${APPNAME}.lnk\" \"$INSTDIR\\${EXECUTABLE}\"\r\n \r\n # Start Menu\r\n " +
|
||||
" CreateDirectory \"$SMPROGRAMS\\${COMPANYNAME}\"\r\n CreateShortCut \"$SMPROGRAMS\\" +
|
||||
"${COMPANYNAME}\\${APPNAME}.lnk\" \"$INSTDIR\\${EXECUTABLE}\"\r\n\r\n # Update pinned T" +
|
||||
"askbar\r\n IfFileExists \"$APPDATA\\Microsoft\\Internet Explorer\\Quick Launch\\User" +
|
||||
" Pinned\\TaskBar\\${APPNAME}.lnk\" 0 +2\r\n CreateShortCut \"$APPDATA\\Microsoft\\Int" +
|
||||
"ernet Explorer\\Quick Launch\\User Pinned\\TaskBar\\${APPNAME}.lnk\" \"$INSTDIR\\${EXEC" +
|
||||
"UTABLE}\"\r\n SetOutPath $INSTDIR\\app-${VERSION}\r\n StrCpy $0 ${EXECUTABLE} -4" +
|
||||
"\r\n IfFileExists \"$APPDATA\\Microsoft\\Internet Explorer\\Quick Launch\\User Pinne" +
|
||||
"d\\TaskBar\\$0.lnk\" 0 +2\r\n CreateShortCut \"$APPDATA\\Microsoft\\Internet Explorer" +
|
||||
"\\Quick Launch\\User Pinned\\TaskBar\\$0.lnk\" \"$INSTDIR\\app-${VERSION}\\${EXECUTABLE}" +
|
||||
"\"\r\n \r\n # Registry information for add/remove programs\r\n WriteRegStr HKC" +
|
||||
"U \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"DisplayName\"" +
|
||||
" \"${APPNAME}\"\r\n WriteRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\U" +
|
||||
"ninstall\\${APPNAME}\" \"UninstallString\" \"$\\\"$INSTDIR\\uninstall.exe$\\\"\"\r\n Write" +
|
||||
"RegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"Qu" +
|
||||
"ietUninstallString\" \"$\\\"$INSTDIR\\uninstall.exe$\\\" /S\"\r\n WriteRegStr HKCU \"Sof" +
|
||||
"tware\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"InstallLocation\" \"" +
|
||||
"$\\\"$INSTDIR$\\\"\"\r\n WriteRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion" +
|
||||
"\\Uninstall\\${APPNAME}\" \"DisplayIcon\" \"$\\\"$INSTDIR\\app-${VERSION}\\${EXECUTABLE}$\\" +
|
||||
"\"\"\r\n WriteRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${" +
|
||||
"APPNAME}\" \"Publisher\" \"${COMPANYNAME}\"\r\n ; WriteRegStr HKCU \"Software\\Microso" +
|
||||
"ft\\Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"HelpLink\" \"${HELPURL}\"\r\n Wri" +
|
||||
"teRegStr HKCU \"Software\\Microsoft\\Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"" +
|
||||
"DisplayVersion\" \"${VERSION}\"\r\n # There is no option for modifying or repairin" +
|
||||
"g the install\r\n WriteRegDWORD HKCU \"Software\\Microsoft\\Windows\\CurrentVersion" +
|
||||
"\\Uninstall\\${APPNAME}\" \"NoModify\" 1\r\n WriteRegDWORD HKCU \"Software\\Microsoft\\" +
|
||||
"Windows\\CurrentVersion\\Uninstall\\${APPNAME}\" \"NoRepair\" 1\r\n # Set the INSTALL" +
|
||||
"SIZE constant (!defined at the top of this script) so Add/Remove Programs can ac" +
|
||||
"curately report the size\r\n WriteRegDWORD HKCU \"Software\\Microsoft\\Windows\\Cur" +
|
||||
"rentVersion\\Uninstall\\${APPNAME}\" \"EstimatedSize\" ${INSTALLSIZE}\r\nSectionEnd ; e" +
|
||||
"nd the section\r\n\r\nFunction .onInstSuccess\r\n IfSilent +2\r\n Exec \'\"$INSTDIR\\" +
|
||||
"${EXECUTABLE}\"\'\r\nFunctionEnd\r\n\r\nSection \"uninstall\"\r\n DetailPrint \'Please wai" +
|
||||
"t...\'\r\n SetShellVarContext current\r\n SetDetailsPrint None\r\n SetAutoClos" +
|
||||
"e true\r\n \r\n # Remove Start Menu launcher\r\n Delete \"$SMPROGRAMS\\${COMPAN" +
|
||||
"YNAME}\\${APPNAME}.lnk\"\r\n Delete \"$DESKTOP\\${APPNAME}.lnk\"\r\n StrCpy $0 ${EX" +
|
||||
"ECUTABLE} -4\r\n Delete \"$APPDATA\\Microsoft\\Internet Explorer\\Quick Launch\\User" +
|
||||
" Pinned\\TaskBar\\${APPNAME}.lnk\"\r\n Delete \"$APPDATA\\Microsoft\\Internet Explore" +
|
||||
"r\\Quick Launch\\User Pinned\\TaskBar\\$0.lnk\"\r\n # Try to remove the Start Menu f" +
|
||||
"older - this will only happen if it is empty\r\n RMDir \"$SMPROGRAMS\\${COMPANYNA" +
|
||||
"ME}\"\r\n\r\n # Always delete uninstaller as the last action\r\n delete $INSTDIR\\" +
|
||||
"uninstall.exe\r\n\r\n # Try to remove the install directory - this will only happ" +
|
||||
"en if it is empty\r\n RMDir /r /REBOOTOK $INSTDIR\r\n\r\n # Remove uninstaller i" +
|
||||
"nformation from the registry\r\n DeleteRegKey HKCU \"Software\\Microsoft\\Windows\\" +
|
||||
"CurrentVersion\\Uninstall\\${APPNAME}\"\r\nsectionEnd");
|
||||
return this.GenerationEnvironment.ToString();
|
||||
}
|
||||
}
|
||||
|
||||
#line default
|
||||
#line hidden
|
||||
#region Base class
|
||||
/// <summary>
|
||||
/// Base class for this transformation
|
||||
/// </summary>
|
||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.TextTemplating", "16.0.0.0")]
|
||||
public class SetupTemplateBase
|
||||
{
|
||||
#region Fields
|
||||
private global::System.Text.StringBuilder generationEnvironmentField;
|
||||
private global::System.CodeDom.Compiler.CompilerErrorCollection errorsField;
|
||||
private global::System.Collections.Generic.List<int> indentLengthsField;
|
||||
private string currentIndentField = "";
|
||||
private bool endsWithNewline;
|
||||
private global::System.Collections.Generic.IDictionary<string, object> sessionField;
|
||||
#endregion
|
||||
#region Properties
|
||||
/// <summary>
|
||||
/// The string builder that generation-time code is using to assemble generated output
|
||||
/// </summary>
|
||||
protected System.Text.StringBuilder GenerationEnvironment
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((this.generationEnvironmentField == null))
|
||||
{
|
||||
this.generationEnvironmentField = new global::System.Text.StringBuilder();
|
||||
}
|
||||
return this.generationEnvironmentField;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.generationEnvironmentField = value;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// The error collection for the generation process
|
||||
/// </summary>
|
||||
public System.CodeDom.Compiler.CompilerErrorCollection Errors
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((this.errorsField == null))
|
||||
{
|
||||
this.errorsField = new global::System.CodeDom.Compiler.CompilerErrorCollection();
|
||||
}
|
||||
return this.errorsField;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// A list of the lengths of each indent that was added with PushIndent
|
||||
/// </summary>
|
||||
private System.Collections.Generic.List<int> indentLengths
|
||||
{
|
||||
get
|
||||
{
|
||||
if ((this.indentLengthsField == null))
|
||||
{
|
||||
this.indentLengthsField = new global::System.Collections.Generic.List<int>();
|
||||
}
|
||||
return this.indentLengthsField;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the current indent we use when adding lines to the output
|
||||
/// </summary>
|
||||
public string CurrentIndent
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.currentIndentField;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Current transformation session
|
||||
/// </summary>
|
||||
public virtual global::System.Collections.Generic.IDictionary<string, object> Session
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.sessionField;
|
||||
}
|
||||
set
|
||||
{
|
||||
this.sessionField = value;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
#region Transform-time helpers
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string textToAppend)
|
||||
{
|
||||
if (string.IsNullOrEmpty(textToAppend))
|
||||
{
|
||||
return;
|
||||
}
|
||||
// If we're starting off, or if the previous text ended with a newline,
|
||||
// we have to append the current indent first.
|
||||
if (((this.GenerationEnvironment.Length == 0)
|
||||
|| this.endsWithNewline))
|
||||
{
|
||||
this.GenerationEnvironment.Append(this.currentIndentField);
|
||||
this.endsWithNewline = false;
|
||||
}
|
||||
// Check if the current text ends with a newline
|
||||
if (textToAppend.EndsWith(global::System.Environment.NewLine, global::System.StringComparison.CurrentCulture))
|
||||
{
|
||||
this.endsWithNewline = true;
|
||||
}
|
||||
// This is an optimization. If the current indent is "", then we don't have to do any
|
||||
// of the more complex stuff further down.
|
||||
if ((this.currentIndentField.Length == 0))
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend);
|
||||
return;
|
||||
}
|
||||
// Everywhere there is a newline in the text, add an indent after it
|
||||
textToAppend = textToAppend.Replace(global::System.Environment.NewLine, (global::System.Environment.NewLine + this.currentIndentField));
|
||||
// If the text ends with a newline, then we should strip off the indent added at the very end
|
||||
// because the appropriate indent will be added when the next time Write() is called
|
||||
if (this.endsWithNewline)
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend, 0, (textToAppend.Length - this.currentIndentField.Length));
|
||||
}
|
||||
else
|
||||
{
|
||||
this.GenerationEnvironment.Append(textToAppend);
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Write text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string textToAppend)
|
||||
{
|
||||
this.Write(textToAppend);
|
||||
this.GenerationEnvironment.AppendLine();
|
||||
this.endsWithNewline = true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void Write(string format, params object[] args)
|
||||
{
|
||||
this.Write(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
/// <summary>
|
||||
/// Write formatted text directly into the generated output
|
||||
/// </summary>
|
||||
public void WriteLine(string format, params object[] args)
|
||||
{
|
||||
this.WriteLine(string.Format(global::System.Globalization.CultureInfo.CurrentCulture, format, args));
|
||||
}
|
||||
/// <summary>
|
||||
/// Raise an error
|
||||
/// </summary>
|
||||
public void Error(string message)
|
||||
{
|
||||
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
|
||||
error.ErrorText = message;
|
||||
this.Errors.Add(error);
|
||||
}
|
||||
/// <summary>
|
||||
/// Raise a warning
|
||||
/// </summary>
|
||||
public void Warning(string message)
|
||||
{
|
||||
System.CodeDom.Compiler.CompilerError error = new global::System.CodeDom.Compiler.CompilerError();
|
||||
error.ErrorText = message;
|
||||
error.IsWarning = true;
|
||||
this.Errors.Add(error);
|
||||
}
|
||||
/// <summary>
|
||||
/// Increase the indent
|
||||
/// </summary>
|
||||
public void PushIndent(string indent)
|
||||
{
|
||||
if ((indent == null))
|
||||
{
|
||||
throw new global::System.ArgumentNullException("indent");
|
||||
}
|
||||
this.currentIndentField = (this.currentIndentField + indent);
|
||||
this.indentLengths.Add(indent.Length);
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove the last indent that was added with PushIndent
|
||||
/// </summary>
|
||||
public string PopIndent()
|
||||
{
|
||||
string returnValue = "";
|
||||
if ((this.indentLengths.Count > 0))
|
||||
{
|
||||
int indentLength = this.indentLengths[(this.indentLengths.Count - 1)];
|
||||
this.indentLengths.RemoveAt((this.indentLengths.Count - 1));
|
||||
if ((indentLength > 0))
|
||||
{
|
||||
returnValue = this.currentIndentField.Substring((this.currentIndentField.Length - indentLength));
|
||||
this.currentIndentField = this.currentIndentField.Remove((this.currentIndentField.Length - indentLength));
|
||||
}
|
||||
}
|
||||
return returnValue;
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove any indentation
|
||||
/// </summary>
|
||||
public void ClearIndent()
|
||||
{
|
||||
this.indentLengths.Clear();
|
||||
this.currentIndentField = "";
|
||||
}
|
||||
#endregion
|
||||
#region ToString Helpers
|
||||
/// <summary>
|
||||
/// Utility class to produce culture-oriented representation of an object as a string.
|
||||
/// </summary>
|
||||
public class ToStringInstanceHelper
|
||||
{
|
||||
private System.IFormatProvider formatProviderField = global::System.Globalization.CultureInfo.InvariantCulture;
|
||||
/// <summary>
|
||||
/// Gets or sets format provider to be used by ToStringWithCulture method.
|
||||
/// </summary>
|
||||
public System.IFormatProvider FormatProvider
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.formatProviderField ;
|
||||
}
|
||||
set
|
||||
{
|
||||
if ((value != null))
|
||||
{
|
||||
this.formatProviderField = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// This is called from the compile/run appdomain to convert objects within an expression block to a string
|
||||
/// </summary>
|
||||
public string ToStringWithCulture(object objectToConvert)
|
||||
{
|
||||
if ((objectToConvert == null))
|
||||
{
|
||||
throw new global::System.ArgumentNullException("objectToConvert");
|
||||
}
|
||||
System.Type t = objectToConvert.GetType();
|
||||
System.Reflection.MethodInfo method = t.GetMethod("ToString", new System.Type[] {
|
||||
typeof(System.IFormatProvider)});
|
||||
if ((method == null))
|
||||
{
|
||||
return objectToConvert.ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
return ((string)(method.Invoke(objectToConvert, new object[] {
|
||||
this.formatProviderField })));
|
||||
}
|
||||
}
|
||||
}
|
||||
private ToStringInstanceHelper toStringHelperField = new ToStringInstanceHelper();
|
||||
/// <summary>
|
||||
/// Helper to produce culture-oriented representation of an object as a string
|
||||
/// </summary>
|
||||
public ToStringInstanceHelper ToStringHelper
|
||||
{
|
||||
get
|
||||
{
|
||||
return this.toStringHelperField;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
#endregion
|
||||
}
|
121
KattekerCreator/SetupTemplate.tt
Normal file
@ -0,0 +1,121 @@
|
||||
<#@ template language="C#" #>
|
||||
<#@ assembly name="System.Core" #>
|
||||
<#@ import namespace="System.Linq" #>
|
||||
<#@ import namespace="System.Text" #>
|
||||
<#@ import namespace="System.Collections.Generic" #>
|
||||
Unicode true
|
||||
ManifestDPIAware true
|
||||
!define APPNAME "<#= AppName #>"
|
||||
!define EXECUTABLE "<#= Executable #>"
|
||||
!define COMPANYNAME "<#= CompanyName #>"
|
||||
!define DESCRIPTION "<#= Description #>"
|
||||
!define ASSEMBLYNAME "<#= AssemblyName #>"
|
||||
!define VERSION <#= Version.ToString() #>
|
||||
!define HELPURL <#= HelpUrl #>
|
||||
!define INSTALLSIZE <#= InstallSize #>
|
||||
!define ISMANAGED <#= IsManaged ? 1 : 0 #>
|
||||
; exampleCmd: makensis.exe /DVERSION=1.0.0.5 /DNAME=WpfApp1 Setup.nsi
|
||||
|
||||
Name "${APPNAME}"
|
||||
OutFile "<#= OutFile #>"
|
||||
InstallDir "$LOCALAPPDATA\Programs\${ASSEMBLYNAME}"
|
||||
RequestExecutionLevel user
|
||||
SetCompressor /SOLID lzma
|
||||
SilentUnInstall silent
|
||||
; Subcaption 3 " "
|
||||
XPStyle on
|
||||
AutoCloseWindow true
|
||||
ChangeUI all "<#= UserInterface #>"
|
||||
Icon "<#= IconPath #>"
|
||||
UninstallIcon "${NSISDIR}\Contrib\Graphics\Icons\nsis3-uninstall.ico"
|
||||
ShowInstDetails nevershow
|
||||
ShowUninstDetails nevershow
|
||||
BrandingText "${COMPANYNAME}"
|
||||
|
||||
VIProductVersion <#= LegacyVersion.ToString(4) #>
|
||||
VIAddVersionKey ProductName "${APPNAME}"
|
||||
VIAddVersionKey Comments ""
|
||||
VIAddVersionKey CompanyName "${COMPANYNAME}"
|
||||
VIAddVersionKey LegalCopyright "${COMPANYNAME}"
|
||||
VIAddVersionKey FileDescription "${DESCRIPTION}"
|
||||
VIAddVersionKey FileVersion "${VERSION}"
|
||||
VIAddVersionKey ProductVersion "${VERSION}"
|
||||
VIAddVersionKey OriginalFilename "<#= OutFile #>"
|
||||
|
||||
;--------------------------------
|
||||
; The stuff to install
|
||||
Section "install" ;No components page, name is not important
|
||||
DetailPrint 'Installing ${APPNAME}. Please wait...'
|
||||
SetShellVarContext current
|
||||
SetDetailsPrint None
|
||||
IfSilent +2
|
||||
RMDir /r $INSTDIR
|
||||
SetOutPath $INSTDIR
|
||||
|
||||
; Create sub-directories
|
||||
<# foreach(var directory in Directories) { #><#= $" CreateDirectory \"$INSTDIR\\{directory}\"{Environment.NewLine}" #><# } #>
|
||||
|
||||
; Put file there
|
||||
<#foreach(var file in Files) { #><#= $" File \"/oname={file.Target}\" \"{file.Source}\"{Environment.NewLine}" #><# } #>
|
||||
|
||||
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
|
28
KattekerCreator/T4Extensions.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Reflection;
|
||||
|
||||
namespace KattekerCreator
|
||||
{
|
||||
internal static class T4Extensions
|
||||
{
|
||||
public static MethodInfo GetMethod(this Type type, string method, params Type[] parameters)
|
||||
{
|
||||
return type.GetRuntimeMethod(method, parameters);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
namespace System.CodeDom.Compiler
|
||||
{
|
||||
public class CompilerErrorCollection : List<CompilerError>
|
||||
{
|
||||
}
|
||||
|
||||
public class CompilerError
|
||||
{
|
||||
public string ErrorText { get; set; }
|
||||
|
||||
public bool IsWarning { get; set; }
|
||||
}
|
||||
}
|
87
KattekerCreator/Types/AssemblyFileInfo.cs
Normal file
@ -0,0 +1,87 @@
|
||||
using System;
|
||||
using System.Drawing;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Semver;
|
||||
using TsudaKageyu;
|
||||
using Vestris.ResourceLib;
|
||||
|
||||
namespace KattekerCreator.Types
|
||||
{
|
||||
public class AssemblyFileInfo
|
||||
{
|
||||
private readonly string _company;
|
||||
private readonly string _copyright;
|
||||
private readonly string _description;
|
||||
private readonly string _productName;
|
||||
|
||||
public AssemblyFileInfo(string programFile, string version, string tempDir)
|
||||
{
|
||||
FileInfo = new FileInfo(programFile);
|
||||
using var resourceInfo = new ResourceInfo();
|
||||
resourceInfo.Load(programFile);
|
||||
if (resourceInfo.ResourceTypes.All(x => x.ResourceType != Kernel32.ResourceTypes.RT_VERSION)) return;
|
||||
var versionResource = (VersionResource)resourceInfo[Kernel32.ResourceTypes.RT_VERSION][0];
|
||||
var stringFileInfo = ((StringFileInfo)versionResource[nameof(StringFileInfo)]).Strings
|
||||
.FirstOrDefault().Value;
|
||||
AssemblyIconPath = GetAssemblyIcon(programFile, 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 = version != null ? GetSemanticVersion(version) : GetSemanticVersion(stringFileInfo.Strings["ProductVersion"].StringValue.TrimEnd('\0'));
|
||||
}
|
||||
|
||||
public string AssemblyIconPath { get; }
|
||||
|
||||
public SemVersion AssemblyVersion { get; }
|
||||
|
||||
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));
|
||||
}
|
||||
}
|
||||
}
|
1042
KattekerCreator/Types/Minimatcher.cs
Normal file
23
KattekerCreator/Types/PathFragments.cs
Normal file
@ -0,0 +1,23 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace KattekerCreator.Types
|
||||
{
|
||||
public struct 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));
|
||||
}
|
||||
}
|
13
KattekerCreator/Types/PhysicalFile.cs
Normal file
@ -0,0 +1,13 @@
|
||||
namespace KattekerCreator.Types
|
||||
{
|
||||
public struct PhysicalFile
|
||||
{
|
||||
public PhysicalFile(string source, string target)
|
||||
{
|
||||
Source = source;
|
||||
Target = target;
|
||||
}
|
||||
|
||||
public readonly string Source, Target;
|
||||
}
|
||||
}
|
42
KattekerCreator/Types/TemporaryDirectory.cs
Normal file
@ -0,0 +1,42 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Threading;
|
||||
|
||||
namespace KattekerCreator.Types
|
||||
{
|
||||
public class TemporaryDirectory : IDisposable
|
||||
{
|
||||
public string Path { get; }
|
||||
|
||||
public TemporaryDirectory(string path)
|
||||
{
|
||||
Path = path;
|
||||
}
|
||||
|
||||
void IDisposable.Dispose()
|
||||
{
|
||||
try
|
||||
{
|
||||
Thread.Sleep(100);
|
||||
Directory.Delete(Path, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
//Try it, catch it, forget it.
|
||||
}
|
||||
}
|
||||
|
||||
public static TemporaryDirectory Create()
|
||||
{
|
||||
string result;
|
||||
do
|
||||
{
|
||||
result = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "temp", Environment.UserName,
|
||||
System.IO.Path.GetRandomFileName());
|
||||
} while (Directory.Exists(result));
|
||||
|
||||
Directory.CreateDirectory(result);
|
||||
return new TemporaryDirectory(result);
|
||||
}
|
||||
}
|
||||
}
|
BIN
KattekerCreator/app.ico
Normal file
After Width: | Height: | Size: 65 KiB |
BIN
KattekerCreator/contrib/LoadingBar_Icon.exe
Normal file
BIN
KattekerCreator/contrib/signtool.exe
Normal file
BIN
KattekerCreator/contrib/uninstall.ico
Normal file
After Width: | Height: | Size: 18 KiB |
144
KattekerCreator/nsis/COPYING
Normal file
@ -0,0 +1,144 @@
|
||||
COPYRIGHT
|
||||
---------
|
||||
|
||||
Copyright (C) 1999-2018 Contributors
|
||||
|
||||
More detailed copyright information can be found in the individual source code files.
|
||||
|
||||
APPLICABLE LICENSES
|
||||
-------------------
|
||||
|
||||
* All NSIS source code, plug-ins, documentation, examples, header files and graphics, with the exception of the compression modules and where otherwise noted, are licensed under the zlib/libpng license.
|
||||
|
||||
* The zlib compression module for NSIS is licensed under the zlib/libpng license.
|
||||
|
||||
* The bzip2 compression module for NSIS is licensed under the bzip2 license.
|
||||
|
||||
* The LZMA compression module for NSIS is licensed under the Common Public License version 1.0.
|
||||
|
||||
ZLIB/LIBPNG LICENSE
|
||||
-------------------
|
||||
|
||||
This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software.
|
||||
|
||||
Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely, subject to the following restrictions:
|
||||
|
||||
1. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
|
||||
2. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
|
||||
3. This notice may not be removed or altered from any source distribution.
|
||||
|
||||
BZIP2 LICENSE
|
||||
-------------
|
||||
|
||||
This program, "bzip2" and associated library "libbzip2", are copyright (C) 1996-2000 Julian R Seward. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
|
||||
|
||||
2. The origin of this software must not be misrepresented; you must not claim that you wrote the original software. If you use this software in a product, an acknowledgment in the product documentation would be appreciated but is not required.
|
||||
|
||||
3. Altered source versions must be plainly marked as such, and must not be misrepresented as being the original software.
|
||||
|
||||
4. The name of the author may not be used to endorse or promote products derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
Julian Seward, Cambridge, UK.
|
||||
|
||||
jseward@acm.org
|
||||
|
||||
COMMON PUBLIC LICENSE VERSION 1.0
|
||||
---------------------------------
|
||||
|
||||
THE ACCOMPANYING PROGRAM IS PROVIDED UNDER THE TERMS OF THIS COMMON PUBLIC LICENSE ("AGREEMENT"). ANY USE, REPRODUCTION OR DISTRIBUTION OF THE PROGRAM CONSTITUTES RECIPIENT'S ACCEPTANCE OF THIS AGREEMENT.
|
||||
|
||||
1. DEFINITIONS
|
||||
|
||||
"Contribution" means:
|
||||
|
||||
a) in the case of the initial Contributor, the initial code and documentation distributed under this Agreement, and
|
||||
b) in the case of each subsequent Contributor:
|
||||
|
||||
i) changes to the Program, and
|
||||
|
||||
ii) additions to the Program;
|
||||
|
||||
where such changes and/or additions to the Program originate from and are distributed by that particular Contributor. A Contribution 'originates' from a Contributor if it was added to the Program by such Contributor itself or anyone acting on such Contributor's behalf. Contributions do not include additions to the Program which: (i) are separate modules of software distributed in conjunction with the Program under their own license agreement, and (ii) are not derivative works of the Program.
|
||||
|
||||
"Contributor" means any person or entity that distributes the Program.
|
||||
|
||||
"Licensed Patents " mean patent claims licensable by a Contributor which are necessarily infringed by the use or sale of its Contribution alone or when combined with the Program.
|
||||
|
||||
"Program" means the Contributions distributed in accordance with this Agreement.
|
||||
|
||||
"Recipient" means anyone who receives the Program under this Agreement, including all Contributors.
|
||||
|
||||
2. GRANT OF RIGHTS
|
||||
|
||||
a) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free copyright license to reproduce, prepare derivative works of, publicly display, publicly perform, distribute and sublicense the Contribution of such Contributor, if any, and such derivative works, in source code and object code form.
|
||||
|
||||
b) Subject to the terms of this Agreement, each Contributor hereby grants Recipient a non-exclusive, worldwide, royalty-free patent license under Licensed Patents to make, use, sell, offer to sell, import and otherwise transfer the Contribution of such Contributor, if any, in source code and object code form. This patent license shall apply to the combination of the Contribution and the Program if, at the time the Contribution is added by the Contributor, such addition of the Contribution causes such combination to be covered by the Licensed Patents. The patent license shall not apply to any other combinations which include the Contribution. No hardware per se is licensed hereunder.
|
||||
|
||||
c) Recipient understands that although each Contributor grants the licenses to its Contributions set forth herein, no assurances are provided by any Contributor that the Program does not infringe the patent or other intellectual property rights of any other entity. Each Contributor disclaims any liability to Recipient for claims brought by any other entity based on infringement of intellectual property rights or otherwise. As a condition to exercising the rights and licenses granted hereunder, each Recipient hereby assumes sole responsibility to secure any other intellectual property rights needed, if any. For example, if a third party patent license is required to allow Recipient to distribute the Program, it is Recipient's responsibility to acquire that license before distributing the Program.
|
||||
|
||||
d) Each Contributor represents that to its knowledge it has sufficient copyright rights in its Contribution, if any, to grant the copyright license set forth in this Agreement.
|
||||
|
||||
3. REQUIREMENTS
|
||||
|
||||
A Contributor may choose to distribute the Program in object code form under its own license agreement, provided that:
|
||||
|
||||
a) it complies with the terms and conditions of this Agreement; and
|
||||
|
||||
b) its license agreement:
|
||||
|
||||
i) effectively disclaims on behalf of all Contributors all warranties and conditions, express and implied, including warranties or conditions of title and non-infringement, and implied warranties or conditions of merchantability and fitness for a particular purpose;
|
||||
|
||||
ii) effectively excludes on behalf of all Contributors all liability for damages, including direct, indirect, special, incidental and consequential damages, such as lost profits;
|
||||
|
||||
iii) states that any provisions which differ from this Agreement are offered by that Contributor alone and not by any other party; and
|
||||
|
||||
iv) states that source code for the Program is available from such Contributor, and informs licensees how to obtain it in a reasonable manner on or through a medium customarily used for software exchange.
|
||||
|
||||
When the Program is made available in source code form:
|
||||
|
||||
a) it must be made available under this Agreement; and
|
||||
|
||||
b) a copy of this Agreement must be included with each copy of the Program.
|
||||
|
||||
Contributors may not remove or alter any copyright notices contained within the Program.
|
||||
|
||||
Each Contributor must identify itself as the originator of its Contribution, if any, in a manner that reasonably allows subsequent Recipients to identify the originator of the Contribution.
|
||||
|
||||
4. COMMERCIAL DISTRIBUTION
|
||||
|
||||
Commercial distributors of software may accept certain responsibilities with respect to end users, business partners and the like. While this license is intended to facilitate the commercial use of the Program, the Contributor who includes the Program in a commercial product offering should do so in a manner which does not create potential liability for other Contributors. Therefore, if a Contributor includes the Program in a commercial product offering, such Contributor ("Commercial Contributor") hereby agrees to defend and indemnify every other Contributor ("Indemnified Contributor") against any losses, damages and costs (collectively "Losses") arising from claims, lawsuits and other legal actions brought by a third party against the Indemnified Contributor to the extent caused by the acts or omissions of such Commercial Contributor in connection with its distribution of the Program in a commercial product offering. The obligations in this section do not apply to any claims or Losses relating to any actual or alleged intellectual property infringement. In order to qualify, an Indemnified Contributor must: a) promptly notify the Commercial Contributor in writing of such claim, and b) allow the Commercial Contributor to control, and cooperate with the Commercial Contributor in, the defense and any related settlement negotiations. The Indemnified Contributor may participate in any such claim at its own expense.
|
||||
|
||||
For example, a Contributor might include the Program in a commercial product offering, Product X. That Contributor is then a Commercial Contributor. If that Commercial Contributor then makes performance claims, or offers warranties related to Product X, those performance claims and warranties are such Commercial Contributor's responsibility alone. Under this section, the Commercial Contributor would have to defend claims against the other Contributors related to those performance claims and warranties, and if a court requires any other Contributor to pay any damages as a result, the Commercial Contributor must pay those damages.
|
||||
|
||||
5. NO WARRANTY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, THE PROGRAM IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED INCLUDING, WITHOUT LIMITATION, ANY WARRANTIES OR CONDITIONS OF TITLE, NON-INFRINGEMENT, MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. Each Recipient is solely responsible for determining the appropriateness of using and distributing the Program and assumes all risks associated with its exercise of rights under this Agreement, including but not limited to the risks and costs of program errors, compliance with applicable laws, damage to or loss of data, programs or equipment, and unavailability or interruption of operations.
|
||||
|
||||
6. DISCLAIMER OF LIABILITY
|
||||
|
||||
EXCEPT AS EXPRESSLY SET FORTH IN THIS AGREEMENT, NEITHER RECIPIENT NOR ANY CONTRIBUTORS SHALL HAVE ANY LIABILITY FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING WITHOUT LIMITATION LOST PROFITS), HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OR DISTRIBUTION OF THE PROGRAM OR THE EXERCISE OF ANY RIGHTS GRANTED HEREUNDER, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
|
||||
|
||||
7. GENERAL
|
||||
|
||||
If any provision of this Agreement is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms of this Agreement, and without further action by the parties hereto, such provision shall be reformed to the minimum extent necessary to make such provision valid and enforceable.
|
||||
|
||||
If Recipient institutes patent litigation against a Contributor with respect to a patent applicable to software (including a cross-claim or counterclaim in a lawsuit), then any patent licenses granted by that Contributor to such Recipient under this Agreement shall terminate as of the date such litigation is filed. In addition, if Recipient institutes patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Program itself (excluding combinations of the Program with other software or hardware) infringes such Recipient's patent(s), then such Recipient's rights granted under Section 2(b) shall terminate as of the date such litigation is filed.
|
||||
|
||||
All Recipient's rights under this Agreement shall terminate if it fails to comply with any of the material terms or conditions of this Agreement and does not cure such failure in a reasonable period of time after becoming aware of such noncompliance. If all Recipient's rights under this Agreement terminate, Recipient agrees to cease use and distribution of the Program as soon as reasonably practicable. However, Recipient's obligations under this Agreement and any licenses granted by Recipient relating to the Program shall continue and survive.
|
||||
|
||||
Everyone is permitted to copy and distribute copies of this Agreement, but in order to avoid inconsistency the Agreement is copyrighted and may only be modified in the following manner. The Agreement Steward reserves the right to publish new versions (including revisions) of this Agreement from time to time. No one other than the Agreement Steward has the right to modify this Agreement. IBM is the initial Agreement Steward. IBM may assign the responsibility to serve as the Agreement Steward to a suitable separate entity. Each new version of the Agreement will be given a distinguishing version number. The Program (including Contributions) may always be distributed subject to the version of the Agreement under which it was received. In addition, after a new version of the Agreement is published, Contributor may elect to distribute the Program (including its Contributions) under the new version. Except as expressly stated in Sections 2(a) and 2(b) above, Recipient receives no rights or licenses to the intellectual property of any Contributor under this Agreement, whether expressly, by implication, estoppel or otherwise. All rights in the Program not expressly granted under this Agreement are reserved.
|
||||
|
||||
This Agreement is governed by the laws of the State of New York and the intellectual property laws of the United States of America. No party to this Agreement will bring a legal action under this Agreement more than one year after the cause of action arose. Each party waives its rights to a jury trial in any resulting litigation.
|
||||
|
||||
SPECIAL EXCEPTION FOR LZMA COMPRESSION MODULE
|
||||
---------------------------------------------
|
||||
|
||||
Igor Pavlov and Amir Szekely, the authors of the LZMA compression module for NSIS, expressly permit you to statically or dynamically link your code (or bind by name) to the files from the LZMA compression module for NSIS without subjecting your linked code to the terms of the Common Public license version 1.0. Any modifications or additions to files from the LZMA compression module for NSIS, however, are subject to the terms of the Common Public License version 1.0.
|
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/big.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/classic-cross.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/classic.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/colorful.bmp
Normal file
After Width: | Height: | Size: 2.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/grey-cross.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/grey.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/modern.bmp
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/red-round.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/red.bmp
Normal file
After Width: | Height: | Size: 886 B |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/simple-round.bmp
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/simple-round2.bmp
Normal file
After Width: | Height: | Size: 1.8 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Checks/simple.bmp
Normal file
After Width: | Height: | Size: 1.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis-r.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 25 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis3-branding.bmp
Normal file
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 8.7 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis3-grey.bmp
Normal file
After Width: | Height: | Size: 8.7 KiB |
After Width: | Height: | Size: 25 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis3-metro.bmp
Normal file
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 8.8 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/nsis3-vintage.bmp
Normal file
After Width: | Height: | Size: 8.8 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/orange-nsis.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/orange-r-nsis.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/orange-r.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/orange.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Header/win.bmp
Normal file
After Width: | Height: | Size: 9.5 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/arrow-install.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/arrow-uninstall.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/arrow2-install.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/arrow2-uninstall.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/box-install.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/box-uninstall.ico
Normal file
After Width: | Height: | Size: 4.6 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/classic-install.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 1.1 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/llama-blue.ico
Normal file
After Width: | Height: | Size: 2.2 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/llama-grey.ico
Normal file
After Width: | Height: | Size: 2.2 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/modern-install.ico
Normal file
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 14 KiB |
After Width: | Height: | Size: 23 KiB |
After Width: | Height: | Size: 23 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/modern-uninstall.ico
Normal file
After Width: | Height: | Size: 14 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/nsis-menu.ico
Normal file
After Width: | Height: | Size: 38 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/nsis1-install.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/nsis1-uninstall.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
After Width: | Height: | Size: 13 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/nsis3-install.ico
Normal file
After Width: | Height: | Size: 11 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/nsis3-uninstall.ico
Normal file
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 25 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/orange-install.ico
Normal file
After Width: | Height: | Size: 25 KiB |
After Width: | Height: | Size: 25 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/orange-uninstall.ico
Normal file
After Width: | Height: | Size: 25 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/pixel-install.ico
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/pixel-uninstall.ico
Normal file
After Width: | Height: | Size: 5.3 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/win-install.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Icons/win-uninstall.ico
Normal file
After Width: | Height: | Size: 1.1 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/arrow.bmp
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/llama.bmp
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nsis.bmp
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nsis3-branding.bmp
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nsis3-grey.bmp
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nsis3-metro.bmp
Normal file
After Width: | Height: | Size: 151 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nsis3-vintage.bmp
Normal file
After Width: | Height: | Size: 51 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/nullsoft.bmp
Normal file
After Width: | Height: | Size: 26 KiB |
BIN
KattekerCreator/nsis/Contrib/Graphics/Wizard/orange-nsis.bmp
Normal file
After Width: | Height: | Size: 51 KiB |