div. Anpassungen

- Settings *.xml eingefügt
- div. Anwendungen eingefügt
- kleine Fehler behoben

automatische zentrieren der Maus entfernt

div. Anpassungen

Squashed 'FSI.Lib/' changes from 24aa22a..9a24247

9a24247 Version erhöht
9536f8a div. Anpassungen für FSI.BT.Tools

git-subtree-dir: FSI.Lib
git-subtree-split: 9a242472bc63c937efcdaaa4e391c5733abe2891

div. Anpassungen

div. Fehlerbehoben
This commit is contained in:
maier_S
2022-03-17 07:50:10 +01:00
parent e702335252
commit 15c25af4b8
46 changed files with 3031 additions and 544 deletions

View File

@@ -6,21 +6,30 @@ namespace FSI.BT.Tools
{
internal class Admin
{
public static bool CheckSuperAdminRight()
{
if (Global.Settings.SuperAdmin == null)
{
return false;
}
System.Security.Principal.WindowsIdentity windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
if (string.Equals(Global.Settings.SuperAdmin, windowsIdentity.ShortName(), StringComparison.OrdinalIgnoreCase))
return true;
return false;
}
public static bool CheckAdminRight()
{
string adminsSettings = Lib.Settings.Setting<string>("AdminUsers", Lib.Settings.Mode.ExeSetttings);
string[] adminsCrypt = adminsSettings.Split(";;");
List<string> admins = new List<string>();
foreach (string admin in adminsCrypt)
if (Global.Settings.Admins == null)
{
try
{
admins.Add(Lib.DeEncryptString.DeEncrypt.DecryptString(Lib.DeEncryptString.DeEncrypt.DecryptString(admin, Lib.Settings.Setting<string>("DeEnCryptPasswort", Lib.Settings.Mode.ExeSetttings)), Lib.Settings.Setting<string>("DeEnCryptPasswort", Lib.Settings.Mode.ExeSetttings)));
}
catch { }
return false;
}
List<string> admins = new List<string>(Global.Settings.Admins);
System.Security.Principal.WindowsIdentity windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
foreach (string admin in admins)
@@ -31,5 +40,25 @@ namespace FSI.BT.Tools
return false;
}
public static bool CheckUserRight()
{
if (Global.Settings.Users == null)
{
return false;
}
List<string> users = new List<string>(Global.Settings.Users);
System.Security.Principal.WindowsIdentity windowsIdentity = System.Security.Principal.WindowsIdentity.GetCurrent();
foreach (string user in users)
{
if (string.Equals(user, windowsIdentity.ShortName(), StringComparison.OrdinalIgnoreCase))
return true;
}
return false;
}
}
}

View File

@@ -1,80 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="DeEnCryptPasswort"
value="Fondium Singen GmbH"/>
<add key="Users"
value="x27xm8kujBnjlCVaIcoTTg=="/>
<add key="AdminUsers"
value="hU4oePJDurXlIZUL4WLIRTt7LoEhVS//rfdZH3O2QVsUPPJL62dqKOCbXZMDdCRih884NktbdDHgRSzsN7wjkQ=="/>
<add key="TimeStamp.Format"
value="_yyyyMMdd_HHmmss"/>
<add key="SIE.Simatic.Manager.Exe"
value="C:\Program Files (x86)\Siemens\Step7\S7BIN\S7tgtopx.exe"/>
<add key="SIE.TIA.V13.Exe"
value="C:\Program Files (x86)\Siemens\Automation\Portal V13\Bin\Siemens.Automation.Portal.exe"/>
<add key="SIE.TIA.V14.Exe"
value="C:\Program Files\Siemens\Automation\Portal V14\Bin\Siemens.Automation.Portal.exe"/>
<add key="SIE.TIA.V15.Exe"
value="C:\Program Files\Siemens\Automation\Portal V15\Bin\Siemens.Automation.Portal.exe;
C:\Program Files\Siemens\Automation\Portal V15_1\Bin\Siemens.Automation.Portal.exe"/>
<add key="SIE.TIA.V16.Exe"
value="C:\Program Files\Siemens\Automation\Portal V16\Bin\Siemens.Automation.Portal.exe"/>
<add key="SIE.TIA.V17.Exe"
value="C:\Program Files\Siemens\Automation\Portal V17\Bin\Siemens.Automation.Portal.exe"/>
<add key="SIE.Starter.Exe"
value="C:\Program Files (x86)\Siemens\Step7\S7BIN\u7wdrfax.exe"/>
<add key="Epl.Exe"
value="C:\Program Files\EPLAN\Platform\2.9.4\Bin\EPLAN.exe;
C:\Program Files\EPLAN\Platform\2022.0.3\Bin\Eplan.exe"/>
<add key="Npp.Exe"
value="C:\Windows\system32\notepad.exe;
C:\Program Files\Notepad++\notepad++.exe"/>
<add key="TeXstudio.Exe"
value="C:\Program Files\texstudio\texstudio.exe"/>
<add key="TeXstudio.Path"
value="C:\Program Files\texstudio\dictionaries"/>
<add key="TotalCmd.Exe"
value="C:\Program Files\totalcmd\TOTALCMD.EXE;
C:\Program Files\totalcmd\TOTALCMD64.EXE;
C:\totalcmd\TOTALCMD64.EXE;
C:\totalcmd\TOTALCMD.EXE"/>
<add key="VS.Exe"
value="C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe"/>
<add key="VS.Code.Exe"
value="%USERPROFILE%\AppData\Local\Programs\Microsoft VS Code\Code.exe"/>
<add key="Rdp.Exe"
value="%windir%\system32\mstsc.exe"/>
<add key="ZentralWeb.Url"
value="http://desiaugetwf/web/?AspxAutoDetectCookieSupport=1"/>
<add key="Schichtbuch.Url"
value="http://10.10.1.42/SKSchichtbuchWeb/de-DE/Plugin/ShiftBook/ShiftBook/IR"/>
<add key="SPS.Url"
value="http://10.10.1.42/SKChangeTrackerWeb/de-DE/Plugin/ChangeTracker"/>
<add key="PL1.PLS.Url"
value="http://10.10.200.2/SKPL1Web/index.aspx"/>
<add key="PL2.PLS.Url"
value="http://10.10.213.4/SKPL2Web/index.aspx"/>
<add key="PL2.ALS.Url"
value="http://10.10.213.234:84/emb_1/index.html"/>
<add key="PL3.PLS.Url"
value="http://10.10.202.10/SKPL3Web/index.aspx"/>
<add key="FSI.Gitea.Url"
value="http://desiaugetc7-088:3000/"/>
<add key="FSI.Wiki.Url"
value="http://desiaugetc7-088:3001/en/home"/>
<add key="Erp.Url"
value="https://mingle-portal.eu1.inforcloudsuite.com/FONDIUM_prd"/>
</appSettings>
</configuration>

View File

@@ -2,7 +2,8 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:tb="http://www.hardcodet.net/taskbar"
Startup="InitApplication">
Startup="Application_Startup"
Exit="Application_Exit">
<Application.Resources>

View File

@@ -3,10 +3,6 @@ using NHotkey;
using NHotkey.Wpf;
using System.Windows;
using System.Windows.Input;
using FSI.Lib.Wpf.ExtensionMethods;
using System.IO;
using System.Diagnostics;
using System;
namespace FSI.BT.Tools
{
@@ -18,11 +14,18 @@ namespace FSI.BT.Tools
private static readonly KeyGesture RadialMenu = new(Key.OemBackslash, ModifierKeys.Control);
private static readonly KeyGesture TimeStamp = new(Key.C, ModifierKeys.Control | ModifierKeys.Alt);
public void InitApplication(object sender, StartupEventArgs e)
public void Application_Startup(object sender, StartupEventArgs e)
{
Global.Settings = new AppSettings(GetType().Namespace.ToString() + ".xml");
Global.Settings.Load();
Global.TaskbarIcon = (TaskbarIcon)FindResource("FSINotifyIcon");
Global.AdminRights = Admin.CheckAdminRight();
Global.SuperAdminRights = Admin.CheckSuperAdminRight();
Global.UserRights = Admin.CheckUserRight();
HotkeyManager.Current.AddOrReplace("RadialMenu", RadialMenu, ShowRadialMenu);
@@ -34,7 +37,9 @@ namespace FSI.BT.Tools
private void ShowRadialMenu(object sender, HotkeyEventArgs e)
{
var cmd = new Commands.RadialMenuCommand();
cmd.Execute(null);
if (cmd.CanExecute(null))
cmd.Execute(null);
e.Handled = true;
}
@@ -47,5 +52,9 @@ namespace FSI.BT.Tools
e.Handled = true;
}
private void Application_Exit(object sender, ExitEventArgs e)
{
Global.Settings.Save();
}
}
}

View File

@@ -0,0 +1,61 @@
using FSI.Lib.WinSettings;
namespace FSI.BT.Tools
{
public class AppSettings : XmlSettings
{
public AppSettings(string fileName) : base(fileName)
{
TimeStampFormat = "_yyyyMMdd_HHmmss";
EplArguments = "/Variant:\"Electric P8\"";
SuperAdmin = "maier_s";
}
[EncryptedSetting]
public string[]? Users { get; set; }
[EncryptedSetting]
public string[]? Admins{ get; set; }
public string? SuperAdmin{ get; set; }
public string? TimeStampFormat { get; set; }
public string[]? SieSimaticManagerExe { get; set; }
public string[]? SieTiaV13Exe { get; set; }
public string[]? SieTiaV14Exe { get; set; }
public string[]? SieTiaV15Exe { get; set; }
public string[]? SieTiaV16Exe { get; set; }
public string[]? SieTiaV17Exe { get; set; }
public string[]? SieTiaVStarterExe { get; set; }
public string[]? EplExe { get; set; }
public string? EplArguments { get; set; }
public string[]? NppExe { get; set; }
public string[]? TotalCmdExe { get; set; }
public string[]? TeXstudioExe { get; set; }
public string[]? TeXstudioPath { get; set; }
public string[]? VsExe { get; set; }
public string[]? VsCodeExe { get; set; }
public string[]? RdpExe { get; set; }
public string[]? OutlookExe { get; set; }
public string[]? TeamsExe { get; set; }
public string? TeamsArg { get; set; }
public string[]? ExcelExe { get; set; }
public string[]? WordExe { get; set; }
public string[]? PaintNetExe { get; set; }
public string[]? GimpExe { get; set; }
public string[]? VncExe { get; set; }
public string[]? VncAdrBookExe { get; set; }
public string? ZentralWebUrl { get; set; }
public string? SchichtbuchUrl { get; set; }
public string? SPSUrl { get; set; }
public string? Pl1PlsUrl { get; set; }
public string? Pl2PlsUrl { get; set; }
public string? Pl2PlsAls { get; set; }
public string? Pl3PlsUrl { get; set; }
public string? GiteaUrl { get; set; }
public string? WikiUrl { get; set; }
public string? ErpUrl { get; set; }
public string? EplPdfPath { get; set; }
public string? EplPrjPath { get; set; }
}
}

View File

@@ -11,7 +11,7 @@ namespace FSI.BT.Tools.Commands
{
Lib.Guis.AutoPw.FrmMain frmMain = new()
{
CloseAtLostFocus = true,
CloseAtLostFocus = false,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
};
frmMain.ShowDialog();
@@ -20,7 +20,6 @@ namespace FSI.BT.Tools.Commands
Global.AdminRights = frmMain.PwOk;
}
public override bool CanExecute(object parameter)
{
return true;

View File

@@ -20,36 +20,36 @@ namespace FSI.BT.Tools.Commands
switch ((string)parameter)
{
case "SimaticManager":
files = Global.Settings.Apps.SieSimaticManagerExe.Split(";");
files = Global.Settings.SieSimaticManagerExe;
break;
case "TIAv13":
files = Global.Settings.Apps.SieTiaV13Exe.Split(";");
files = Global.Settings.SieTiaV13Exe;
break;
case "TIAv14":
files = Global.Settings.Apps.SieTiaV14Exe.Split(";");
files = Global.Settings.SieTiaV14Exe;
break;
case "TIAv15":
files = Global.Settings.Apps.SieTiaV15Exe.Split(";");
files = Global.Settings.SieTiaV13Exe;
break;
case "TIAv16":
files = Global.Settings.Apps.SieTiaV16Exe.Split(";");
files = Global.Settings.SieTiaV16Exe;
break;
case "TIAv17":
files = Global.Settings.Apps.SieTiaV17Exe.Split(";");
files = Global.Settings.SieTiaV17Exe;
break;
case "Starter":
files = Global.Settings.Apps.SieTiaVStarterExe.Split(";");
files = Global.Settings.SieTiaVStarterExe;
break;
case "Epl":
files = Global.Settings.Apps.Epl.Exe.Split(";");
arguments = Global.Settings.Apps.Epl.Arguments;
files = Global.Settings.EplExe;
arguments = Global.Settings.EplArguments;
break;
case "EplPrj":
@@ -58,6 +58,8 @@ namespace FSI.BT.Tools.Commands
ShowPdf = false,
CloseAtLostFocus = true,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Path = Global.Settings.EplPrjPath,
EplExes = Global.Settings.EplExe,
};
frmMainEplPrj.Show();
return;
@@ -68,6 +70,7 @@ namespace FSI.BT.Tools.Commands
ShowPdf = true,
CloseAtLostFocus = true,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
Path = Global.Settings.EplPdfPath,
};
frmMainEplPdf.Show();
return;
@@ -81,35 +84,35 @@ namespace FSI.BT.Tools.Commands
return;
case "Npp":
files = Global.Settings.Apps.NppExe.Split(";");
files = Global.Settings.NppExe;
break;
case "TotalCmd":
files = Global.Settings.Apps.TotalCmdExe.Split(";");
files = Global.Settings.TotalCmdExe;
break;
case "TeXstudio":
files = Global.Settings.Apps.TeXstudioExe.Split(";");
pathes = Global.Settings.Apps.TeXstudioPath.Split(";");
files = Global.Settings.TeXstudioExe;
pathes = Global.Settings.TeXstudioPath;
break;
case "VS":
files = Global.Settings.Apps.VsExe.Split(";");
files = Global.Settings.VsExe;
break;
case "VS.Code":
files = Global.Settings.Apps.VsCodeExe.Split(";");
files = Global.Settings.VsCodeExe;
break;
case "Rdp":
files = Global.Settings.Apps.RdpExe.Split(";"); ;
files = Global.Settings.RdpExe;
break;
case "DeEncrypt":
Lib.Guis.DeEncryptMessage.FrmMain frmMainDeEnCrypt = new()
{
Password = Global.Settings.General.DeEnCryptPasswort,
Password = GetType().Namespace.ToString(),
CloseAtLostFocus = true,
WindowStartupLocation = WindowStartupLocation.CenterOwner,
};
@@ -121,6 +124,54 @@ namespace FSI.BT.Tools.Commands
frmMain.Show();
return;
case "Admin":
Gui.FrmAdmin frmAdmin = new()
{
Admins = Global.Settings.Admins,
Users = Global.Settings.Users,
};
frmAdmin.ShowDialog();
if (frmAdmin.DialogResult.HasValue && frmAdmin.DialogResult.Value)
{
Global.Settings.Admins = frmAdmin.Admins;
Global.Settings.Users = frmAdmin.Users;
}
return;
case "Outlook":
files = Global.Settings.OutlookExe;
break;
case "Teams":
files = Global.Settings.TeamsExe;
arguments = Global.Settings.TeamsArg;
break;
case "Excel":
files = Global.Settings.ExcelExe;
break;
case "Word":
files = Global.Settings.WordExe;
break;
case "PaintNet":
files = Global.Settings.PaintNetExe;
break;
case "Gimp":
files = Global.Settings.GimpExe;
break;
case "Vnc":
files = Global.Settings.VncExe;
break;
case "VncAdrBook":
files = Global.Settings.VncAdrBookExe;
break;
}
string fileName = string.Empty;
@@ -177,35 +228,35 @@ namespace FSI.BT.Tools.Commands
switch ((string)parameter)
{
case "SimaticManager":
files = Global.Settings.Apps.SieSimaticManagerExe.Split(";");
files = Global.Settings.SieSimaticManagerExe;
break;
case "TIAv13":
files = Global.Settings.Apps.SieTiaV13Exe.Split(";");
files = Global.Settings.SieTiaV13Exe;
break;
case "TIAv14":
files = Global.Settings.Apps.SieTiaV14Exe.Split(";");
files = Global.Settings.SieTiaV14Exe;
break;
case "TIAv15":
files = Global.Settings.Apps.SieTiaV15Exe.Split(";");
files = Global.Settings.SieTiaV13Exe;
break;
case "TIAv16":
files = Global.Settings.Apps.SieTiaV16Exe.Split(";");
files = Global.Settings.SieTiaV16Exe;
break;
case "TIAv17":
files = Global.Settings.Apps.SieTiaV17Exe.Split(";");
files = Global.Settings.SieTiaV17Exe;
break;
case "Starter":
files = Global.Settings.Apps.SieTiaVStarterExe.Split(";");
files = Global.Settings.SieTiaVStarterExe;
break;
case "Epl":
files = Global.Settings.Apps.Epl.Exe.Split(";");
files = Global.Settings.EplExe;
break;
case "EplPrj":
@@ -218,27 +269,28 @@ namespace FSI.BT.Tools.Commands
return Global.AdminRights;
case "Npp":
files = Global.Settings.Apps.NppExe.Split(";");
files = Global.Settings.NppExe;
break;
case "TotalCmd":
files = Global.Settings.Apps.TotalCmdExe.Split(";");
files = Global.Settings.TotalCmdExe;
break;
case "TeXstudio":
files = Global.Settings.Apps.TeXstudioExe.Split(";");
files = Global.Settings.TeXstudioExe;
break;
case "VS":
files = Global.Settings.Apps.VsExe.Split(";");
files = Global.Settings.VsExe;
break;
case "VS.Code":
files = Global.Settings.Apps.VsCodeExe.Split(";");
files = Global.Settings.VsCodeExe;
break;
case "Rdp":
files = Global.Settings.Apps.RdpExe.Split(";"); ;
files = Global.Settings.RdpExe;
break;
case "DeEncrypt":
@@ -246,6 +298,42 @@ namespace FSI.BT.Tools.Commands
case "StarterCsvExporter":
return Global.AdminRights;
case "Admin":
return Global.SuperAdminRights;
case "Outlook":
files = Global.Settings.OutlookExe;
break;
case "Teams":
files = Global.Settings.TeamsExe;
break;
case "Excel":
files = Global.Settings.ExcelExe;
break;
case "Word":
files = Global.Settings.WordExe;
break;
case "PaintNet":
files = Global.Settings.PaintNetExe;
break;
case "Gimp":
files = Global.Settings.GimpExe;
break;
case "Vnc":
files = Global.Settings.VncExe;
break;
case "VncAdrBook":
files = Global.Settings.VncAdrBookExe;
break;
default: return false;
}

View File

@@ -16,43 +16,43 @@ namespace FSI.BT.Tools.Commands
switch ((string)parameter)
{
case "ZentralWeb":
url = Global.Settings.Urls.ZentralWeb;
url = Global.Settings.ZentralWebUrl;
break;
case "Schichtbuch":
url = Global.Settings.Urls.Schichtbuch;
url = Global.Settings.SchichtbuchUrl;
break;
case "SPS":
url = Global.Settings.Urls.SPS;
url = Global.Settings.SPSUrl;
break;
case "PL1.Pls":
url = Global.Settings.Urls.Pl1Pls;
url = Global.Settings.Pl1PlsUrl;
break;
case "PL2.Pls":
url = Global.Settings.Urls.Pl2Pls;
url = Global.Settings.Pl2PlsUrl;
break;
case "PL2.Als":
url = Global.Settings.Urls.Pl2Als;
url = Global.Settings.Pl2PlsAls;
break;
case "PL3.Pls":
url = Global.Settings.Urls.Pl3Pls;
url = Global.Settings.Pl3PlsUrl;
break;
case "FSI.Gitea":
url = Global.Settings.Urls.Gitea;
url = Global.Settings.GiteaUrl;
break;
case "FSI.Wiki":
url = Global.Settings.Urls.Wiki;
url = Global.Settings.WikiUrl;
break;
case "Erp":
url = Global.Settings.Urls.Erp;
url = Global.Settings.ErpUrl;
break;
}

View File

@@ -1,4 +1,5 @@
using System.Windows.Controls.Primitives;
using System;
using System.Windows.Controls.Primitives;
namespace FSI.BT.Tools.Commands
{
@@ -9,7 +10,7 @@ namespace FSI.BT.Tools.Commands
{
public override void Execute(object parameter)
{
System.Windows.Forms.Clipboard.SetDataObject(Global.Settings.General.TimeStampFormat);
System.Windows.Forms.Clipboard.SetDataObject(DateTime.Now.ToString(Global.Settings.TimeStampFormat));
var balloon = new ToolTip()
{
BalloonText = "Zeitstempel",

View File

@@ -8,13 +8,46 @@
<UseWPF>true</UseWPF>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
<ApplicationIcon>Icons\FondiumU.ico</ApplicationIcon>
<AssemblyVersion>0.1</AssemblyVersion>
<AssemblyVersion>2.0</AssemblyVersion>
</PropertyGroup>
<ItemGroup>
<None Remove="Icons\Erp.png" />
<None Remove="Icons\Plc.jpg" />
<None Remove="Icons\Rdp.png" />
<Resource Remove="Icons\Admin.jpg" />
<Resource Remove="Icons\Apps.png" />
<Resource Remove="Icons\Circuit.png" />
<Resource Remove="Icons\Close.png" />
<Resource Remove="Icons\Crypt.jpg" />
<Resource Remove="Icons\EplP8.png" />
<Resource Remove="Icons\Erp.png" />
<Resource Remove="Icons\Excel.png" />
<Resource Remove="Icons\FondiumU.ico" />
<Resource Remove="Icons\FU.png" />
<Resource Remove="Icons\Gimp.png" />
<Resource Remove="Icons\Gitea.png" />
<Resource Remove="Icons\Info.png" />
<Resource Remove="Icons\Links.png" />
<Resource Remove="Icons\NPP.png" />
<Resource Remove="Icons\Outlook.png" />
<Resource Remove="Icons\Paint.png" />
<Resource Remove="Icons\Pdf.png" />
<Resource Remove="Icons\Plc.jpg" />
<Resource Remove="Icons\Rdp.png" />
<Resource Remove="Icons\SIE.png" />
<Resource Remove="Icons\STEP7.png" />
<Resource Remove="Icons\Teams.png" />
<Resource Remove="Icons\TIAv13.jpg" />
<Resource Remove="Icons\TIAv14.jpg" />
<Resource Remove="Icons\TIAv15.jpg" />
<Resource Remove="Icons\TIAv16.jpg" />
<Resource Remove="Icons\TIAv17.jpg" />
<Resource Remove="Icons\Tools.png" />
<Resource Remove="Icons\TotalCmd.jfif" />
<Resource Remove="Icons\Vnc.png" />
<Resource Remove="Icons\VncAdrBook.png" />
<Resource Remove="Icons\Vs.png" />
<Resource Remove="Icons\VsCode.png" />
<Resource Remove="Icons\TeXstudio.png" />
<Resource Remove="Icons\Word.png" />
</ItemGroup>
<ItemGroup>
@@ -26,22 +59,29 @@
<ItemGroup>
<Resource Include="Icons\1087815.png" />
<Resource Include="Icons\Admin.jpg" />
<Resource Include="Icons\Apps.png" />
<Resource Include="Icons\Circuit.png" />
<Resource Include="Icons\Close.png" />
<Resource Include="Icons\Crypt.jpg" />
<Resource Include="Icons\EplP8.png" />
<Resource Include="Icons\Erp.png" />
<Resource Include="Icons\Excel.png" />
<Resource Include="Icons\FondiumU.ico" />
<Resource Include="Icons\FU.png" />
<Resource Include="Icons\Gimp.png" />
<Resource Include="Icons\Gitea.png" />
<Resource Include="Icons\Info.png" />
<Resource Include="Icons\Links.png" />
<Resource Include="Icons\NPP.png" />
<Resource Include="Icons\Outlook.png" />
<Resource Include="Icons\Paint.png" />
<Resource Include="Icons\Pdf.png" />
<Resource Include="Icons\Plc.jpg" />
<Resource Include="Icons\Rdp.png" />
<Resource Include="Icons\SIE.png" />
<Resource Include="Icons\STEP7.png" />
<Resource Include="Icons\Teams.png" />
<Resource Include="Icons\TIAv13.jpg" />
<Resource Include="Icons\TIAv14.jpg" />
<Resource Include="Icons\TIAv15.jpg" />
@@ -49,9 +89,18 @@
<Resource Include="Icons\TIAv17.jpg" />
<Resource Include="Icons\Tools.png" />
<Resource Include="Icons\TotalCmd.jfif" />
<Resource Include="Icons\Vnc.png" />
<Resource Include="Icons\VncAdrBook.png" />
<Resource Include="Icons\Vs.png" />
<Resource Include="Icons\VsCode.png" />
<Resource Include="Icons\TeXstudio.png" />
<Resource Include="Icons\Word.png" />
</ItemGroup>
<ItemGroup>
<None Update="FSI.BT.Tools.xml">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="UTF-8"?>
<Settings>
<Users>+I945AMzKKYBAAAAB21haWVyX3M=</Users>
<Admins>e+Dt7FRUDDoBAAAAB21haWVyX3M=</Admins>
<SuperAdmin>maier_s</SuperAdmin>
<TimeStampFormat>_yyyyMMdd_HHmmss</TimeStampFormat>
<SieSimaticManagerExe>C:\Program Files (x86)\Siemens\Step7\S7BIN\S7tgtopx.exe</SieSimaticManagerExe>
<SieTiaV13Exe>C:\Program Files (x86)\Siemens\Automation\Portal V13\Bin\Siemens.Automation.Portal.exe</SieTiaV13Exe>
<SieTiaV14Exe>C:\Program Files\Siemens\Automation\Portal V14\Bin\Siemens.Automation.Portal.exe</SieTiaV14Exe>
<SieTiaV15Exe>C:\Program Files\Siemens\Automation\Portal V15\Bin\Siemens.Automation.Portal.exe,c:\Program Files\Siemens\Automation\Portal V15_1\Bin\Siemens.Automation.Portal.exe</SieTiaV15Exe>
<SieTiaV16Exe>C:\Program Files\Siemens\Automation\Portal V16\Bin\Siemens.Automation.Portal.exe</SieTiaV16Exe>
<SieTiaV17Exe>C:\Program Files\Siemens\Automation\Portal V17\Bin\Siemens.Automation.Portal.exe</SieTiaV17Exe>
<SieTiaVStarterExe>C:\Program Files (x86)\Siemens\Step7\S7BIN\u7wdrfax.exe</SieTiaVStarterExe>
<EplExe>C:\Program Files\EPLAN\Platform\2.9.4\Bin\EPLAN.exe,C:\Program Files\EPLAN\Platform\2022.0.3\Bin\Eplan.exe</EplExe>
<EplArguments>/Variant:"Electric P8"</EplArguments>
<NppExe>C:\Windows\system32\notepad.exe,c:\Program Files\Notepad++\notepad++.exe</NppExe>
<TotalCmdExe>C:\Program Files\totalcmd\TOTALCMD.EXE,C:\Program Files\totalcmd\TOTALCMD64.EXE,C:\totalcmd\TOTALCMD64.EXE,C:\totalcmd\TOTALCMD.EXE</TotalCmdExe>
<TeXstudioExe>C:\Program Files\texstudio\texstudio.exe</TeXstudioExe>
<TeXstudioPath>C:\Program Files\texstudio\dictionaries</TeXstudioPath>
<VsExe>C:\Program Files\Microsoft Visual Studio\2022\Community\Common7\IDE\devenv.exe</VsExe>
<VsCodeExe>%USERPROFILE%\AppData\Local\Programs\Microsoft VS Code\Code.exe</VsCodeExe>
<RdpExe>%windir%\system32\mstsc.exe</RdpExe>
<OutlookExe>C:\Program Files (x86)\Microsoft Office\root\Office16\OUTLOOK.EXE</OutlookExe>
<TeamsExe>C:\Users\maier_s\AppData\Local\Microsoft\Teams\Update.exe</TeamsExe>
<TeamsArg>--processStart ""Teams.exe""</TeamsArg>
<ExcelExe>C:\Program Files (x86)\Microsoft Office\root\Office16\EXCEL.EXE</ExcelExe>
<WordExe>C:\Program Files (x86)\Microsoft Office\root\Office16\WINWORD.EXE</WordExe>
<PaintNetExe>C:\Program Files\paint.net\paintdotnet.exe</PaintNetExe>
<GimpExe>C:\Program Files\GIMP 2\bin\gimp-2.10.exe</GimpExe>
<VncExe>C:\Program Files\RealVNC\VNC Viewer\vncviewer.exe,c:\Users\maier_s\OneDrive - Fondium Group GmbH\Documents\Apps\VNC-Viewer-6.20.113-Windows-64bit.exe</VncExe>
<VncAdrBookExe>C:\Program Files\RealVNC\VNC Viewer\vncaddrbook.exe</VncAdrBookExe>
<ZentralWebUrl>http://desiaugetwf/web/?AspxAutoDetectCookieSupport=1</ZentralWebUrl>
<SchichtbuchUrl>http://10.10.1.42/SKSchichtbuchWeb/de-DE/Plugin/ShiftBook/ShiftBook/IR</SchichtbuchUrl>
<SPSUrl>http://10.10.1.42/SKChangeTrackerWeb/de-DE/Plugin/ChangeTracker</SPSUrl>
<Pl1PlsUrl>http://10.10.200.2/SKPL1Web/index.aspx</Pl1PlsUrl>
<Pl2PlsUrl>http://10.10.213.4/SKPL2Web/index.aspx</Pl2PlsUrl>
<Pl2PlsAls>http://10.10.213.234:84/emb_1/index.html</Pl2PlsAls>
<Pl3PlsUrl>http://10.10.202.10/SKPL3Web/index.aspx</Pl3PlsUrl>
<GiteaUrl>http://desiaugetc7-088:3000/</GiteaUrl>
<WikiUrl>http://desiaugetc7-088:3001/en/home</WikiUrl>
<ErpUrl>https://mingle-portal.eu1.inforcloudsuite.com/FONDIUM_prd</ErpUrl>
<EplPdfPath>\\10.10.1.40\Betriebstechnik\Eplan</EplPdfPath>
<EplPrjPath>\\fondium.org\DESI$\AUG_Abteilung\Betriebstechnik\EPL\P8\Data\Projekte\FSI\</EplPrjPath>
</Settings>

View File

@@ -39,7 +39,7 @@
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenHome}">
<RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuCentralItem Command="{Binding CloseRadialMenuHome}" >
<RadialMenu:RadialMenuCentralItem Command="{Binding CloseRadialMenuHome}">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
@@ -49,11 +49,10 @@
</RadialMenu:RadialMenuCentralItem>
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuEpl}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuEpl}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/EplP8.png" />
</Rectangle.Fill>
@@ -65,11 +64,10 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuTools}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuTools}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Tools.png" />
</Rectangle.Fill>
@@ -81,11 +79,10 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuSie}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuSie}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/SIE.png" />
</Rectangle.Fill>
@@ -98,11 +95,10 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TotalCmd"
Click="RadialMenuItem_Click">
CommandParameter="TotalCmd">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/TotalCmd.jfif" />
</Rectangle.Fill>
@@ -115,27 +111,25 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Npp"
Click="RadialMenuItem_Click">
CommandParameter="Npp">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/NPP.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Notepad++
N++
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuLinks}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuLinks}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Links.png" />
</Rectangle.Fill>
@@ -147,6 +141,53 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Outlook">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Outlook.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Outlook
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Teams">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Teams.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Teams
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuApps}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Apps.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Apps
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
</RadialMenu:RadialMenu>
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenEpl}">
@@ -163,8 +204,7 @@
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Epl"
Click="RadialMenuItem_Click">
CommandParameter="Epl">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -180,8 +220,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="EplPrj"
Click="RadialMenuItem_Click">
CommandParameter="EplPrj">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
@@ -197,8 +236,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="EplPdf"
Click="RadialMenuItem_Click">
CommandParameter="EplPdf">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
@@ -213,8 +251,8 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenEplPdfMgt}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="EplPdfMgt">
<WrapPanel Orientation="Vertical">
<Rectangle Width="35"
Height="35">
@@ -234,8 +272,7 @@
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenTools}">
<RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuCentralItem Command="{Binding OpenRadialMenuHome}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuCentralItem Command="{Binding OpenRadialMenuHome}">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
@@ -246,8 +283,7 @@
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="DeEncrypt"
Click="RadialMenuItem_Click">
CommandParameter="DeEncrypt">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
@@ -263,8 +299,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Rdp"
Click="RadialMenuItem_Click">
CommandParameter="Rdp">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -280,8 +315,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="VS"
Click="RadialMenuItem_Click">
CommandParameter="VS">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -297,8 +331,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="VS.Code"
Click="RadialMenuItem_Click">
CommandParameter="VS.Code">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -315,8 +348,7 @@
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TeXstudio"
Click="RadialMenuItem_Click">
CommandParameter="TeXstudio">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -332,8 +364,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="StarterCsvExporter"
Click="RadialMenuItem_Click">
CommandParameter="StarterCsvExporter">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
@@ -348,6 +379,22 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Admin">
<WrapPanel Orientation="Vertical">
<Rectangle Width="40"
Height="40">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Admin.jpg" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Admin
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
</RadialMenu:RadialMenu>
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenSie}">
@@ -364,8 +411,7 @@
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="SimaticManager"
Click="RadialMenuItem_Click">
CommandParameter="SimaticManager">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -381,8 +427,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TIAv13"
Click="RadialMenuItem_Click">
CommandParameter="TIAv13">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -398,8 +443,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TIAv14"
Click="RadialMenuItem_Click">
CommandParameter="TIAv14">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -415,8 +459,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TIAv15"
Click="RadialMenuItem_Click">
CommandParameter="TIAv15">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -432,8 +475,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TIAv16"
Click="RadialMenuItem_Click">
CommandParameter="TIAv16">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -449,8 +491,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="TIAv17"
Click="RadialMenuItem_Click">
CommandParameter="TIAv17">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -466,8 +507,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Starter"
Click="RadialMenuItem_Click">
CommandParameter="Starter">
<WrapPanel Orientation="Vertical">
<Rectangle Width="50"
Height="50">
@@ -487,8 +527,7 @@
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenLinks}">
<RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuCentralItem Command="{Binding OpenRadialMenuHome}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuCentralItem Command="{Binding OpenRadialMenuHome}">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
@@ -498,8 +537,7 @@
</RadialMenu:RadialMenuCentralItem>
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuPlantLinks}"
Click="RadialMenuItem_Click">
<RadialMenu:RadialMenuItem Command="{Binding OpenRadialMenuPlantLinks}">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -515,8 +553,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="Erp"
Click="RadialMenuItem_Click">
CommandParameter="Erp">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -531,10 +568,9 @@
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="ZentralWeb"
Click="RadialMenuItem_Click">
CommandParameter="ZentralWeb">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -550,8 +586,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="Schichtbuch"
Click="RadialMenuItem_Click">
CommandParameter="Schichtbuch">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -567,8 +602,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="SPS"
Click="RadialMenuItem_Click">
CommandParameter="SPS">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -584,8 +618,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="FSI.Gitea"
Click="RadialMenuItem_Click">
CommandParameter="FSI.Gitea">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -595,14 +628,13 @@
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
FSI<LineBreak />Gitea
Gitea
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="FSI.Wiki"
Click="RadialMenuItem_Click">
CommandParameter="FSI.Wiki">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -632,8 +664,7 @@
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="ZentralWeb"
Click="RadialMenuItem_Click">
CommandParameter="ZentralWeb">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -649,8 +680,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="PL1.PLS"
Click="RadialMenuItem_Click">
CommandParameter="PL1.PLS">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -666,8 +696,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="PL2.PLS"
Click="RadialMenuItem_Click">
CommandParameter="PL2.PLS">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -683,8 +712,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="PL2.Als"
Click="RadialMenuItem_Click">
CommandParameter="PL2.Als">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -700,8 +728,7 @@
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenLinkCommand}"
CommandParameter="PL3.Pls"
Click="RadialMenuItem_Click">
CommandParameter="PL3.Pls">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
@@ -718,6 +745,117 @@
</RadialMenu:RadialMenu>
<RadialMenu:RadialMenu IsOpen="{Binding IsOpenApps}">
<RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuCentralItem Command="{Binding OpenRadialMenuHome}">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/FondiumU.ico" />
</Rectangle.Fill>
</Rectangle>
</RadialMenu:RadialMenuCentralItem>
</RadialMenu:RadialMenu.CentralItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Excel">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Excel.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Excel
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Word">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Word.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Word
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="PaintNet">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Paint.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Paint.Net
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Gimp">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Gimp.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
Gimp
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="Vnc">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/Vnc.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
VNC
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
<RadialMenu:RadialMenuItem Command="{commands:OpenAppCommand}"
CommandParameter="VncAdrBook">
<WrapPanel Orientation="Vertical">
<Rectangle Width="30"
Height="30">
<Rectangle.Fill>
<ImageBrush ImageSource="../../Icons/VncAdrBook.png" />
</Rectangle.Fill>
</Rectangle>
<TextBlock FontSize="14"
TextAlignment="Center">
VNC<LineBreak />Adressbuch
</TextBlock>
</WrapPanel>
</RadialMenu:RadialMenuItem>
</RadialMenu:RadialMenu>
</Grid>
</Canvas>

View File

@@ -56,6 +56,7 @@ namespace FSI.BT.Tools
IsOpenEpl =
IsOpenTools =
IsOpenSie =
IsOpenApps =
IsOpenLinks = false;
});
}
@@ -213,6 +214,36 @@ namespace FSI.BT.Tools
#endregion
#region Apps
private bool _isOpenApps = false;
public bool IsOpenApps
{
get
{
return _isOpenApps;
}
set
{
_isOpenApps = value;
RaisePropertyChanged();
}
}
public ICommand OpenRadialMenuApps
{
get
{
return new RelayCommand(() =>
{
IsOpenApps = true;
IsOpenHome = false;
});
}
}
#endregion
public event PropertyChangedEventHandler PropertyChanged;
void RaisePropertyChanged([CallerMemberName] string? propertyName = null)
@@ -229,38 +260,8 @@ namespace FSI.BT.Tools
IsOpenTools =
IsOpenSie =
IsOpenLinks =
IsOpenApps =
IsOpenPlantLinks = false;
}
private void RadialMenuItem_Click(object sender, RoutedEventArgs e)
{
int left = Convert.ToInt32(GetActualLeft() + this.ActualWidth / 2);
int top = Convert.ToInt32(GetActuaTop() + this.ActualHeight / 2);
System.Windows.Forms.Cursor.Position = new System.Drawing.Point(left, top);
}
private double GetActualLeft()
{
if (this.WindowState == WindowState.Maximized)
{
var leftField = typeof(Window).GetField("_actualLeft", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
return (double)leftField.GetValue(this);
}
else
return this.Left;
}
private double GetActuaTop()
{
if (this.WindowState == WindowState.Maximized)
{
var topField = typeof(Window).GetField("_actualTop", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
return (double)topField.GetValue(this);
}
else
return this.Top;
}
}
}

View File

@@ -1,4 +1,5 @@
using Hardcodet.Wpf.TaskbarNotification;
using FSI.Lib.WinSettings;
using Hardcodet.Wpf.TaskbarNotification;
namespace FSI.BT.Tools
{
@@ -9,171 +10,12 @@ namespace FSI.BT.Tools
public static TaskbarIcon? TaskbarIcon { get; set; }
public static AppSettings? Settings { get; set; }
public static bool UserRights { get; set; }
public static bool AdminRights { get; set; }
public static class Settings
{
public static class General
{
public static string DeEnCryptPasswort
{
get
{
return FSI.Lib.Settings.Setting<string>("DeEnCryptPasswort", Lib.Settings.Mode.ExeSetttings);
}
}
public static string TimeStampFormat
{
get
{
return FSI.Lib.Settings.Setting<string>("TimeStamp.Format", Lib.Settings.Mode.ExeSetttings);
}
}
}
public static class Apps
{
public static string SieSimaticManagerExe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.Simatic.Manager.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaV13Exe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.TIA.V13.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaV14Exe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.TIA.V14.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaV15Exe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.TIA.V15.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaV16Exe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.TIA.V16.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaV17Exe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.TIA.V17.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SieTiaVStarterExe
{
get { return FSI.Lib.Settings.Setting<string>("SIE.Starter.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static class Epl
{
public static string Exe
{
get { return FSI.Lib.Settings.Setting<string>("Epl.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Arguments
{
get { return "/Variant:\"Electric P8\""; }
}
}
public static string NppExe
{
get { return FSI.Lib.Settings.Setting<string>("Npp.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string TotalCmdExe
{
get { return FSI.Lib.Settings.Setting<string>("TotalCmd.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string TeXstudioExe
{
get { return FSI.Lib.Settings.Setting<string>("TeXstudio.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string TeXstudioPath
{
get { return FSI.Lib.Settings.Setting<string>("TeXstudio.Path", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string VsExe
{
get { return FSI.Lib.Settings.Setting<string>("VS.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static bool SuperAdminRights { get; set; }
public static string VsCodeExe
{
get { return FSI.Lib.Settings.Setting<string>("VS.Code.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string RdpExe
{
get { return FSI.Lib.Settings.Setting<string>("Rdp.Exe", FSI.Lib.Settings.Mode.ExeSetttings); }
}
}
public static class Urls
{
public static string ZentralWeb
{
get { return FSI.Lib.Settings.Setting<string>("ZentralWeb.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Schichtbuch
{
get { return FSI.Lib.Settings.Setting<string>("Schichtbuch.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string SPS
{
get { return FSI.Lib.Settings.Setting<string>("SPS.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Pl1Pls
{
get { return FSI.Lib.Settings.Setting<string>("PL1.Pls.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Pl2Pls
{
get { return FSI.Lib.Settings.Setting<string>("PL2.Pls.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Pl2Als
{
get { return FSI.Lib.Settings.Setting<string>("PL2.Als.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Pl3Pls
{
get { return FSI.Lib.Settings.Setting<string>("PL3.Pls.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Gitea
{
get { return FSI.Lib.Settings.Setting<string>("FSI.Gitea.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Wiki
{
get { return FSI.Lib.Settings.Setting<string>("FSI.Gitea.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
public static string Erp
{
get { return FSI.Lib.Settings.Setting<string>("Erp.Url", FSI.Lib.Settings.Mode.ExeSetttings); }
}
}
}
}
}

View File

@@ -0,0 +1,48 @@
<Window x:Class="FSI.BT.Tools.Gui.FrmAdmin"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:FSI.BT.Tools.Gui"
mc:Ignorable="d"
Title="Admin-/Benutzerverwaltung"
SizeToContent="WidthAndHeight"
Height="Auto"
MinWidth="800"
Loaded="Window_Loaded">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="200" />
<RowDefinition Height="Auto" />
<RowDefinition Height="200" />
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label Content="Benutzer:" />
<TextBox x:Name="tbUsers"
Grid.Row="1"
AcceptsReturn="true"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible" />
<Label Grid.Row="2"
Content="Admins:" />
<TextBox x:Name="tbAdmins"
Grid.Row="3"
AcceptsReturn="true"
VerticalScrollBarVisibility="Visible"
HorizontalScrollBarVisibility="Visible" />
<StackPanel Grid.Row="4" Orientation="Horizontal">
<Button x:Name="btnOk"
Margin="5 5 5 5"
Content="Speichern"
Click="btnOk_Click" />
<Button x:Name="btnCancel"
Margin="5 5 5 5 "
Content="Abbruch"
Click="btnCancel_Click" />
</StackPanel>
</Grid>
</Window>

View File

@@ -0,0 +1,51 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
namespace FSI.BT.Tools.Gui
{
/// <summary>
/// Interaktionslogik für FrmAdmin.xaml
/// </summary>
public partial class FrmAdmin : Window
{
public string[] Admins { get; set; }
public string[] Users { get; set; }
public FrmAdmin()
{
InitializeComponent();
}
private void btnOk_Click(object sender, RoutedEventArgs e)
{
Admins = tbAdmins.Text.Split(Environment.NewLine);
Users = tbUsers.Text.Split(Environment.NewLine);
DialogResult = true;
Close();
}
private void btnCancel_Click(object sender, RoutedEventArgs e)
{
DialogResult = false;
Close();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
tbAdmins.Text = String.Join(Environment.NewLine, Admins);
tbUsers.Text = String.Join(Environment.NewLine, Users);
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 658 KiB

BIN
FSI.BT.Tools/Icons/Apps.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 19 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
FSI.BT.Tools/Icons/Gimp.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 76 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

BIN
FSI.BT.Tools/Icons/Vnc.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 30 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

BIN
FSI.BT.Tools/Icons/Word.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

View File

@@ -1,24 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="Epl.Prj.Path"
value="\\fondium.org\DESI$\AUG_Abteilung\Betriebstechnik\EPL\P8\Data\Projekte\FSI\"/>
<add key="Epl.Pdf.Path"
value="\\10.10.1.40\Betriebstechnik\Eplan\"/>
<add key="TimeStamp.Format"
value="_yyyyMMdd_HHmmss"/>
<add key ="SieTiaWinCCMsgMgt.Autostart"
value="false"/>
<add key ="SieTiaWinCCMsgMgt.UpdateIntervall"
value="100"/>
<add key ="SieTiaWinCCMsgMgt.WindowsName"
value=""/>
<add key ="SieTiaWinCCMsgMgt.WindowsClassName"
value="#32770"/>
<add key ="SieTiaWinCCMsgMgt.ButtonName"
value="Zur Kenntnis genommen"/>
</appSettings>
</configuration>

View File

@@ -0,0 +1,704 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Security.Cryptography;
namespace FSI.Lib.EasyEncryption
{
/// <summary>
/// Encryption algorithm types.
/// </summary>
public enum EncryptionAlgorithm
{
/// <summary>
/// Specifies the Advanced Encryption Standard (AES) symmetric encryption algorithm.
/// </summary>
Aes,
/// <summary>
/// Specifies the Data Encryption Standard (DES) symmetric encryption algorithm.
/// </summary>
Des,
/// <summary>
/// Specifies the RC2 symmetric encryption algorithm.
/// </summary>
Rc2,
/// <summary>
/// Specifies the Rijndael symmetric encryption algorithm.
/// </summary>
Rijndael,
/// <summary>
/// Specifies the TripleDES symmetric encryption algorithm.
/// </summary>
TripleDes
}
/// <summary>
/// Class to provide encryption and decryption services.
/// </summary>
/// <remarks>
/// <para>
/// The Encryption class performs encryption and decryption using the specified algorithm.
/// </para>
/// <para>
/// The encrypted values may appear considerably larger than the decrypted values
/// because encrypted values contains some additional meta data. If either data size or
/// performance is a concern, use the <see cref="CreateStreamReader(Stream)"/> or
/// <see cref="CreateStreamWriter(Stream)"/> methods to work with the streaming classes
/// instead.
/// </para>
/// </remarks>
public class Encryption
{
private static readonly int SaltLength = 8;
private static readonly Dictionary<EncryptionAlgorithm, Type> AlgorithmLookup = new Dictionary<EncryptionAlgorithm, Type>
{
[EncryptionAlgorithm.Aes] = typeof(Aes),
[EncryptionAlgorithm.Des] = typeof(DES),
[EncryptionAlgorithm.Rc2] = typeof(RC2),
[EncryptionAlgorithm.Rijndael] = typeof(Rijndael),
[EncryptionAlgorithm.TripleDes] = typeof(TripleDES),
};
private string Password { get; }
private Type AlgorithmType { get; }
/// <summary>
/// Converts a byte array to a string.
/// </summary>
/// <param name="bytes">The byte array to be converted.</param>
/// <returns>Returns the converted string.</returns>
public static string EncodeBytesToString(byte[] bytes) => Convert.ToBase64String(bytes);
/// <summary>
/// Converts a string to a byte array.
/// </summary>
/// <param name="s">The string to be converted.</param>
/// <returns>Returns the converted byte array.</returns>
public static byte[] DecodeBytesFromString(string s) => Convert.FromBase64String(s);
/// <summary>
/// Constructs a new <c>Encryption</c> instance.
/// </summary>
/// <param name="password">Specifies the encryption password. Leading and trailing spaces are removed.</param>
/// <param name="algorithm">Specifies which encryption algorithm is used.</param>
public Encryption(string password, EncryptionAlgorithm algorithm)
{
if (string.IsNullOrWhiteSpace(password))
throw new ArgumentException("Password is required.", nameof(password));
Password = password.Trim();
AlgorithmType = AlgorithmLookup[algorithm];
}
#region Encryption stream creation methods
/// <summary>
/// Creates an <see cref="EncryptionWriter"/> instance using the specified stream.
/// </summary>
/// <remarks>
/// The <see cref="EncryptionWriter"/> class is the preferred method to encrypt data
/// as it will store some necessary meta data only once for all data in the stream.
/// It is also more performant. The other encryption methods defer to the EncryptionWriter
/// class for actual encryption.
/// </remarks>
/// <param name="stream">The stream the encrypted data will be written to.</param>
/// <returns>An instance of the <see cref="EncryptionWriter"/> class.</returns>
public EncryptionWriter CreateStreamWriter(Stream stream)
{
// Create a random salt and write to stream
byte[] salt = CreateSalt();
stream.Write(salt, 0, salt.Length);
// Create symmetric algorithm
SymmetricAlgorithm algorithm = CreateAlgorithm();
algorithm.Padding = PaddingMode.PKCS7;
// Create key and IV
byte[] key, iv;
GenerateKeyAndIv(algorithm, salt, out key, out iv);
// Create EncryptionWriter
ICryptoTransform encryptor = algorithm.CreateEncryptor(key, iv);
CryptoStream cs = new CryptoStream(stream, encryptor, CryptoStreamMode.Write);
return new EncryptionWriter(algorithm, encryptor, stream);
}
/// <summary>
/// Creates an <see cref="EncryptionWriter"/> instance using the specified file name.
/// </summary>
/// <remarks>
/// The <see cref="EncryptionWriter"/> class is the preferred method to encrypt data
/// as it will store some necessary meta data only once for all data in the stream.
/// It is also more performant. The other encryption methods defer to the EncryptionWriter
/// class for actual encryption.
/// </remarks>
/// <param name="path">The file name the encrypted data will be written to.</param>
/// <returns>An instance of the <see cref="EncryptionWriter"/> class.</returns>
public EncryptionWriter CreateStreamWriter(string path)
{
return CreateStreamWriter(File.Open(path, FileMode.OpenOrCreate, FileAccess.Write));
}
/// <summary>
/// Creates an <see cref="EncryptionReader"/> instance using the specified stream.
/// </summary>
/// <remarks>
/// The <see cref="EncryptionReader"/> class is the preferred method to decrypt data.
/// It is also more performant. The other decryption methods defer to the EncryptionReader
/// class for actual decryption.
/// </remarks>
/// <param name="stream">The stream the encrypted data will be read from.</param>
/// <returns>An instance of the <see cref="EncryptionReader"/> class.</returns>
public EncryptionReader CreateStreamReader(Stream stream)
{
// Read salt from input stream
byte[] salt = new byte[SaltLength];
if (stream.Read(salt, 0, salt.Length) < SaltLength)
throw new ArgumentOutOfRangeException("Reached end of input stream before reading encryption metadata.");
// Create symmetric algorithm
SymmetricAlgorithm algorithm = CreateAlgorithm();
algorithm.Padding = PaddingMode.PKCS7;
// Create key and IV
byte[] key, iv;
GenerateKeyAndIv(algorithm, salt, out key, out iv);
// Create EncryptionReader
ICryptoTransform decryptor = algorithm.CreateDecryptor(key, iv);
CryptoStream cs = new CryptoStream(stream, decryptor, CryptoStreamMode.Read);
return new EncryptionReader(algorithm, decryptor, stream);
}
/// <summary>
/// Creates an <see cref="EncryptionReader"/> instance using the specified file name.
/// </summary>
/// <remarks>
/// The <see cref="EncryptionReader"/> class is the preferred method to decrypt data.
/// It is also more performant. The other decryption methods defer to the EncryptionReader
/// class for actual decryption.
/// </remarks>
/// <param name="path">The file name the encrypted data will be read from.</param>
/// <returns>An instance of the <see cref="EncryptionReader"/> class.</returns>
public EncryptionReader CreateStreamReader(string path)
{
return CreateStreamReader(File.Open(path, FileMode.Open, FileAccess.Read));
}
#endregion
#region Encryption
/// <summary>
/// Encrypts a <c>string</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(string value) => Encrypt(w => w.Write(value ?? string.Empty));
/// <summary>
/// Encrypts a <c>bool</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(bool value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>char</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(char value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>sbyte</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(sbyte value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>byte</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(byte value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>short</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(short value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>ushort</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(ushort value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>int</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(int value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>uint</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(uint value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>long</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(long value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>ulong</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(ulong value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>float</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(float value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>double</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(double value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>decimal</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(decimal value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>DateTime</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(DateTime value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>byte[]</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(byte[] value) => Encrypt(w => w.Write(value));
/// <summary>
/// Encrypts a <c>string[]</c> value.
/// </summary>
/// <remarks>
/// The encrypted value will be larger than the unencrypted value because the
/// encrypted value will contain some additional meta data. To minimize the
/// size of this meta data when encrypting multiple values, use <see cref="CreateStreamWriter(Stream)"/>
/// to create a <see cref="EncryptionWriter"/> instead.
/// </remarks>
/// <param name="value">The value to decrypt.</param>
/// <returns>Returns the encrypted value</returns>
public string Encrypt(string[] value) => Encrypt(w => w.Write(value));
private string Encrypt(Action<EncryptionWriter> action)
{
using (MemoryStream stream = new MemoryStream())
using (EncryptionWriter writer = CreateStreamWriter(stream))
{
action(writer);
return EncodeBytesToString(stream.ToArray());
}
}
#endregion
#region Decryption
/// <summary>
/// Decrypts a <c>string</c> value encrypted with <see cref="Encrypt(string)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public string DecryptString(string encryptedValue) => (string)Decrypt(encryptedValue, r => r.ReadString());
/// <summary>
/// Decrypts a <c>bool</c> value encrypted with <see cref="Encrypt(bool)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public bool DecryptBoolean(string encryptedValue) => (bool)Decrypt(encryptedValue, r => r.ReadBoolean());
/// <summary>
/// Decrypts a <c>char</c> value encrypted with <see cref="Encrypt(char)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public char DecryptChar(string encryptedValue) => (char)Decrypt(encryptedValue, r => r.ReadChar());
/// <summary>
/// Decrypts a <c>sbyte</c> value encrypted with <see cref="Encrypt(sbyte)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public sbyte DecryptSByte(string encryptedValue) => (sbyte)Decrypt(encryptedValue, r => r.ReadSByte());
/// <summary>
/// Decrypts a <c>byte</c> value encrypted with <see cref="Encrypt(byte)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public byte DecryptByte(string encryptedValue) => (byte)Decrypt(encryptedValue, r => r.ReadByte());
/// <summary>
/// Decrypts a <c>short</c> value encrypted with <see cref="Encrypt(short)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public short DecryptInt16(string encryptedValue) => (short)Decrypt(encryptedValue, r => r.ReadInt16());
/// <summary>
/// Decrypts a <c>ushort</c> value encrypted with <see cref="Encrypt(ushort)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public ushort DecryptUInt16(string encryptedValue) => (ushort)Decrypt(encryptedValue, r => r.ReadUInt16());
/// <summary>
/// Decrypts a <c>int</c> value encrypted with <see cref="Encrypt(int)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public int DecryptInt32(string encryptedValue) => (int)Decrypt(encryptedValue, r => r.ReadInt32());
/// <summary>
/// Decrypts a <c>uint</c> value encrypted with <see cref="Encrypt(uint)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public uint DecryptUInt32(string encryptedValue) => (uint)Decrypt(encryptedValue, r => r.ReadUInt32());
/// <summary>
/// Decrypts a <c>long</c> value encrypted with <see cref="Encrypt(long)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public long DecryptInt64(string encryptedValue) => (long)Decrypt(encryptedValue, r => r.ReadInt64());
/// <summary>
/// Decrypts a <c>ulong</c> value encrypted with <see cref="Encrypt(ulong)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public ulong DecryptUInt64(string encryptedValue) => (ulong)Decrypt(encryptedValue, r => r.ReadUInt64());
/// <summary>
/// Decrypts a <c>float</c> value encrypted with <see cref="Encrypt(float)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public float DecryptSingle(string encryptedValue) => (float)Decrypt(encryptedValue, r => r.ReadSingle());
/// <summary>
/// Decrypts a <c>double</c> value encrypted with <see cref="Encrypt(double)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public double DecryptDouble(string encryptedValue) => (double)Decrypt(encryptedValue, r => r.ReadDouble());
/// <summary>
/// Decrypts a <c>decimal</c> value encrypted with <see cref="Encrypt(decimal)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public decimal DecryptDecimal(string encryptedValue) => (decimal)Decrypt(encryptedValue, r => r.ReadDecimal());
/// <summary>
/// Decrypts a <c>DateTime</c> value encrypted with <see cref="Encrypt(DateTime)"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public DateTime DecryptDateTime(string encryptedValue) => (DateTime)Decrypt(encryptedValue, r => r.ReadDateTime());
/// <summary>
/// Decrypts a <c>byte[]</c> value encrypted with <see cref="Encrypt(byte[])"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public byte[] DecryptByteArray(string encryptedValue) => (byte[])Decrypt(encryptedValue, r => r.ReadByteArray());
/// <summary>
/// Decrypts a <c>string[]</c> value encrypted with <see cref="Encrypt(string[])"/>.
/// </summary>
/// <param name="encryptedValue">The value to decrypt.</param>
/// <returns>Returns the decrypted value</returns>
public string[] DecryptStringArray(string encryptedValue) => (string[])Decrypt(encryptedValue, r => r.ReadStringArray());
private object Decrypt(string encryptedValue, Func<EncryptionReader, object> action)
{
using (MemoryStream stream = new MemoryStream(DecodeBytesFromString(encryptedValue)))
using (EncryptionReader reader = CreateStreamReader(stream))
{
return action(reader);
}
}
#endregion
#region Encryption/decryption of objects
/// <summary>
/// Class to hold encrypt/decrypt functions for each supported data type.
/// </summary>
private class TypeInfo
{
public Func<Encryption, object, string> Encrypt { get; set; }
public Func<Encryption, string, object> Decrypt { get; set; }
public TypeInfo(Func<Encryption, object, string> encrypt, Func<Encryption, string, object> decrypt)
{
Encrypt = encrypt;
Decrypt = decrypt;
}
}
private static readonly Dictionary<Type, TypeInfo> TypeInfoLookup = new Dictionary<Type, TypeInfo>()
{
[typeof(string)] = new TypeInfo((e, v) => e.Encrypt((string)v), (e, s) => e.DecryptString(s)),
[typeof(bool)] = new TypeInfo((e, v) => e.Encrypt((bool)v), (e, s) => e.DecryptBoolean(s)),
[typeof(char)] = new TypeInfo((e, v) => e.Encrypt((char)v), (e, s) => e.DecryptChar(s)),
[typeof(sbyte)] = new TypeInfo((e, v) => e.Encrypt((sbyte)v), (e, s) => e.DecryptSByte(s)),
[typeof(byte)] = new TypeInfo((e, v) => e.Encrypt((byte)v), (e, s) => e.DecryptByte(s)),
[typeof(short)] = new TypeInfo((e, v) => e.Encrypt((short)v), (e, s) => e.DecryptInt16(s)),
[typeof(ushort)] = new TypeInfo((e, v) => e.Encrypt((ushort)v), (e, s) => e.DecryptUInt16(s)),
[typeof(int)] = new TypeInfo((e, v) => e.Encrypt((int)v), (e, s) => e.DecryptInt32(s)),
[typeof(uint)] = new TypeInfo((e, v) => e.Encrypt((uint)v), (e, s) => e.DecryptUInt32(s)),
[typeof(long)] = new TypeInfo((e, v) => e.Encrypt((long)v), (e, s) => e.DecryptInt64(s)),
[typeof(ulong)] = new TypeInfo((e, v) => e.Encrypt((ulong)v), (e, s) => e.DecryptUInt64(s)),
[typeof(float)] = new TypeInfo((e, v) => e.Encrypt((float)v), (e, s) => e.DecryptSingle(s)),
[typeof(double)] = new TypeInfo((e, v) => e.Encrypt((double)v), (e, s) => e.DecryptDouble(s)),
[typeof(decimal)] = new TypeInfo((e, v) => e.Encrypt((decimal)v), (e, s) => e.DecryptDecimal(s)),
[typeof(DateTime)] = new TypeInfo((e, v) => e.Encrypt((DateTime)v), (e, s) => e.DecryptDateTime(s)),
[typeof(byte[])] = new TypeInfo((e, v) => e.Encrypt((byte[])v), (e, s) => e.DecryptByteArray(s)),
[typeof(string[])] = new TypeInfo((e, v) => e.Encrypt((string[])v), (e, s) => e.DecryptStringArray(s)),
};
/// <summary>
/// Indicates if the specified data type is supported by the encryption and decryption methods.
/// </summary>
/// <remarks>
/// The encryption code supports all basic .NET data types in addition to <c>byte[]</c>
/// and <c>string[]</c>. More complex data types are not supported.
/// </remarks>
/// <param name="type">The data type to be tested.</param>
/// <returns>True if the specified type is supported. False otherwise.</returns>
public static bool IsTypeSupported(Type type) => TypeInfoLookup.ContainsKey(type);
/// <summary>
/// Encrypts an object value. The object must hold one of the supported data types.
/// </summary>
/// <param name="value">Object to be encrypted.</param>
/// <exception cref="ArgumentException"><paramref name="value"/> holds an unsupported data type.</exception>
/// <returns>An encrypted string that can be decrypted using Decrypt.</returns>
public string Encrypt(object value)
{
if (value == null)
return null;
if (TypeInfoLookup.TryGetValue(value.GetType(), out TypeInfo info))
return info.Encrypt(this, value);
throw new ArgumentException(string.Format("Cannot encrypt value : Data type '{0}' is not supported", value.GetType()));
}
/// <summary>
/// Decrypts an object value of the specified type.
/// </summary>
/// <param name="encryptedValue">The encrypted string to be decrypted.</param>
/// <param name="targetType">The type of data that was originally encrypted into <paramref name="encryptedValue"/>.</param>
/// <exception cref="ArgumentException"></exception>
/// <returns>Returns the decrypted value.</returns>
public object Decrypt(string encryptedValue, Type targetType)
{
if (TypeInfoLookup.TryGetValue(targetType, out TypeInfo info))
return info.Decrypt(this, encryptedValue);
throw new ArgumentException(string.Format("Cannot decrypt value : Data type '{0}' is not supported", targetType));
}
#endregion
#region Support methods
/// <summary>
/// Creates a SymmetricAlgorithm instance for the current encryption algorithm.
/// </summary>
/// <returns>
/// Returns the created SymmetricAlgorithm instance.
/// </returns>
protected SymmetricAlgorithm CreateAlgorithm()
{
MethodInfo method = AlgorithmType.GetMethod("Create", Array.Empty<Type>());
if (method != null)
{
if (method.Invoke(null, null) is SymmetricAlgorithm algorithm)
return algorithm;
}
throw new Exception($"Unable to create instance of {AlgorithmType.FullName}.");
}
/// <summary>
/// Generates a salt that contains a cryptographically strong sequence of random values.
/// </summary>
/// <returns>The generated salt value.</returns>
private byte[] CreateSalt()
{
byte[] salt = new byte[SaltLength];
using (RNGCryptoServiceProvider generator = new RNGCryptoServiceProvider())
{
generator.GetBytes(salt);
}
return salt;
}
/// <summary>
/// Generates a pseudorandom key and initialization vector from the current password and the
/// given salt.
/// </summary>
/// <param name="algorithm"><see cref="SymmetricAlgorithm"></see> being used to encrypt.</param>
/// <param name="salt">The salt used to derive the key and initialization vector.</param>
/// <param name="key">Returns the generated key.</param>
/// <param name="iv">Returns the generated initialization vector.</param>
protected void GenerateKeyAndIv(SymmetricAlgorithm algorithm, byte[] salt, out byte[] key, out byte[] iv)
{
int keyLength = algorithm.KeySize >> 3;
int ivLength = algorithm.BlockSize >> 3;
byte[] bytes = DeriveBytes(salt, keyLength + ivLength);
key = new byte[keyLength];
Buffer.BlockCopy(bytes, 0, key, 0, keyLength);
iv = new byte[ivLength];
Buffer.BlockCopy(bytes, keyLength, iv, 0, ivLength);
}
/// <summary>
/// Generates a series of pseudorandom bytes of the specified length based on the current
/// password and the given salt.
/// </summary>
/// <param name="salt">The salt used to derive the bytes.</param>
/// <param name="bytes">The number of bits of data to generate.</param>
/// <returns>Returns the derived bytes.</returns>
protected byte[] DeriveBytes(byte[] salt, int bytes)
{
Rfc2898DeriveBytes derivedBytes = new Rfc2898DeriveBytes(Password, salt, 1000);
return derivedBytes.GetBytes(bytes);
}
#endregion
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.IO;
using System.Security.Cryptography;
namespace FSI.Lib.EasyEncryption
{
/// <summary>
/// Class that provides streaming decryption functionality.
/// </summary>
/// <remarks>
/// Using this class is the preferred way to decrypt values from a file or memory.
/// Other decryption methods defer to this class for actual decryption.
/// </remarks>
public class EncryptionReader : BinaryReader, IDisposable
{
private SymmetricAlgorithm Algorithm;
private ICryptoTransform Decryptor;
internal EncryptionReader(SymmetricAlgorithm algorithm, ICryptoTransform decryptor, Stream stream) : base(stream)
{
Algorithm = algorithm;
Decryptor = decryptor;
}
/// <summary>
/// Reads a <c>DateTime</c> value from the encrypted stream.
/// </summary>
/// <returns>The decrypted value.</returns>
public DateTime ReadDateTime()
{
return new DateTime(ReadInt64());
}
/// <summary>
/// Reads a <c>byte[]</c> value from the encrypted stream.
/// </summary>
/// <returns>The decrypted values.</returns>
public byte[] ReadByteArray()
{
int count = ReadInt32();
byte[] bytes = new byte[count];
if (count > 0)
Read(bytes, 0, count);
return bytes;
}
/// <summary>
/// Reads a <c>string[]</c> value from the encrypted stream.
/// </summary>
/// <returns>The decrypted values.</returns>
public string[] ReadStringArray()
{
int count = ReadInt32();
string[] strings = new string[count];
for (int i = 0; i < count; i++)
strings[i] = ReadString();
return strings;
}
#region IDisposable implementation
private bool disposed = false; // To detect redundant calls
/// <summary>
/// Releases all resources used by the current instance of the <c>EncryptionReader</c> class.
/// </summary>
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases the unmanaged resources used by the <c>EncryptionReader</c> class and optionally
/// releases the managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
/// <c>false</c> to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (!disposed)
{
disposed = true;
if (disposing)
{
// Dispose managed objects
base.Dispose(true);
Decryptor.Dispose();
Algorithm.Dispose();
}
}
}
/// <summary>
/// Destructs this instance of <c>EncryptionReader</c>.
/// </summary>
~EncryptionReader()
{
Dispose(false);
}
#endregion
}
}

View File

@@ -0,0 +1,105 @@
using System;
using System.IO;
using System.Security.Cryptography;
namespace FSI.Lib.EasyEncryption
{
/// <summary>
/// Class that provides streaming encryption functionality.
/// </summary>
/// <remarks>
/// Using this class is the preferred way to encrypt values to a file or memory.
/// Other encryption methods defer to this class for actual encryption. Meta data
/// that must be stored with the encrypted result is only stored once for all
/// data in the stream.
/// </remarks>
public class EncryptionWriter : BinaryWriter, IDisposable
{
private readonly SymmetricAlgorithm Algorithm;
private readonly ICryptoTransform Encryptor;
internal EncryptionWriter(SymmetricAlgorithm algorithm, ICryptoTransform encryptor, Stream stream) : base(stream)
{
Algorithm = algorithm;
Encryptor = encryptor;
}
/// <summary>
/// Writes a <c>DateTime</c> value to the encrypted stream.
/// </summary>
/// <param name="value"><c>DateTime</c> value to write.</param>
public void Write(DateTime value)
{
Write(value.Ticks);
}
/// <summary>
/// Writes a <c>byte</c> array to the encrypted stream.
/// </summary>
/// <remarks>
/// Note: Hides <c>BinaryWriter.Write(byte[])</c>.
/// </remarks>
/// <param name="value"><c>byte[]</c> values to write.</param>
public new void Write(byte[] value)
{
Write(value.Length);
Write(value, 0, value.Length);
}
/// <summary>
/// Writes a <c>string</c> to the encrypted stream.
/// </summary>
/// <param name="value"><c>string[]</c> values to write.</param>
public void Write(string[] value)
{
Write(value.Length);
for (int i = 0; i < value.Length; i++)
Write(value[i]);
}
#region IDisposable implementation
private bool disposed = false; // To detect redundant calls
/// <summary>
/// Releases all resources used by the current instance of the <c>EncryptionWriter</c> class.
/// </summary>
public new void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
/// <summary>
/// Releases the unmanaged resources used by the <c>EncryptionWriter</c> class and optionally
/// releases the managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources;
/// <c>false</c> to release only unmanaged resources.</param>
protected override void Dispose(bool disposing)
{
if (!disposed)
{
disposed = true;
if (disposing)
{
// Dispose managed objects
base.Dispose(true);
Encryptor.Dispose();
Algorithm.Dispose();
}
}
}
/// <summary>
/// Destructs this instance of <c>EncryptionWriter</c>.
/// </summary>
~EncryptionWriter()
{
Dispose(false);
}
#endregion
}
}

View File

@@ -0,0 +1,90 @@
# EasyEncryption
[![NuGet version (SoftCircuits.EasyEncryption)](https://img.shields.io/nuget/v/SoftCircuits.EasyEncryption.svg?style=flat-square)](https://www.nuget.org/packages/SoftCircuits.EasyEncryption/)
```
Install-Package SoftCircuits.EasyEncryption
```
The .NET Framework provides a number of encryption routines. However, these routines generally require a bit of work to set up correctly. Use `EasyEncryption` to make these encryption routines more easily accessible.
## Encrypting a String
The `Encrypt()` method can be used to encrypt a string. Use `DecryptString()` to decrypt the string back to the original.
```cs
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
string original = "This is my message";
string cipher = encrypt.Encrypt(original);
string result = encrypt.DecryptString(cipher);
Debug.Assert(result == message);
```
## Encrypting other Types
The `Encrypt()` method is overloaded to encrypt many different data types. When decrypting, you must use the decryption method specific to the data type you are decrypting. This example encrypts an `int` and `double` value.
```cs
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
int originalInt = 55;
double originalDouble = 123.45;
string cipherInt = encrypt.Encrypt(originalInt);
string cipherDouble = encrypt.Encrypt(originalDouble);
int resultInt = encrypt.DecryptInt32(cipherInt);
double resultDouble = encrypt.DecryptDouble(cipherDouble);
Debug.Assert(resultInt == originalInt);
Debug.Assert(resultDouble == originalDouble);
```
## Streams
`EasyEncryption` also provides the streaming classes `EncryptionWriter` and `EncryptionReader`. These classes work well when encrypting to (or decrypting from) files.
The following example uses the `CreateStreamWriter()` to encrypt a number of integer values to a file.
```cs
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
int[] intValues = { 123, 88, 902, 27, 16, 4, 478, 54 };
using (EncryptionWriter writer = encrypt.CreateStreamWriter(path))
{
for (int i = 0; i < intValues.Length; i++)
writer.Write(intValues[i]);
}
```
Use the `CreateStreamReader()` method to decrypt those integer values from the file.
```cs
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
int[] intValues = new int[8];
using (EncryptionReader reader = encrypt.CreateStreamReader(path))
{
for (int i = 0; i < intValues.Length; i++)
intValues[i] = reader.ReadInt32();
}
```
Also, the `CreateStreamWriter()` and `CreateStreamReader()` methods are overloaded to accept a stream argument, allowing you to use custom streams. For example, you could use a `MemoryStream` to encrypt data to memory. This is demonstrated in the following example. It also uses the static method `EncodeBytesToString()` method to convert the results to a string. (Note that there is also a corresponding static `DecodeBytesFromString()` method.)
```cs
Encryption encrypt = new Encryption("Password123", EncryptionAlgorithm.TripleDes);
using (MemoryStream stream = new MemoryStream())
using (EncryptionWriter writer = encrypt.CreateStreamWriter(stream))
{
writer.Write("ABC");
writer.Write(123);
writer.Write(123.45);
string s = Encryption.EncodeBytesToString(stream.ToArray());
}
```
Note that the streaming classes are actually the most efficient way to encrypt and decrypt data. In fact the `Encrypt()` and decryption methods create an instance of `EncryptionWriter` internally (using a `MemoryStream`), even when only encrypting or decrypting a single byte.
In addition, it should be pointed out that the encrypted results produced by these routines include embedded meta data, making the encrypted data slightly larger than it would otherwise be. However, when encrypting to a stream, this data would only be stored once regardless of the number of values added to the stream. The takeaway is that you can use the `Encrypt()` method for a simple encryption, but should use the streaming classes for anything more complex.

View File

@@ -6,7 +6,7 @@
<GenerateAssemblyInfo>true</GenerateAssemblyInfo>
<UseWPF>true</UseWPF>
<ImportWindowsDesktopTargets>true</ImportWindowsDesktopTargets>
<AssemblyVersion>1.0</AssemblyVersion>
<AssemblyVersion>3.0</AssemblyVersion>
</PropertyGroup>
<ItemGroup>

View File

@@ -67,13 +67,11 @@ namespace FSI.Lib.Guis.AutoPw
private void TbPw_KeyDown(object sender, KeyEventArgs e)
{
if (BtnOk.IsEnabled == true)
{
Close();
{
PwOk = true;
}
else
{
Close();
{
PwOk = false;
}
}

View File

@@ -13,6 +13,8 @@ namespace FSI.Lib.Guis.Prj.Mgt
public ViewModelPrj Prj { get; set; }
public bool ShowPdf { get; set; }
public bool CloseAtLostFocus { get; set; }
public string Path { get; set; }
public string[] EplExes { get; set; }
public FrmMain()
{
@@ -30,34 +32,33 @@ namespace FSI.Lib.Guis.Prj.Mgt
private void Main_Loaded(object sender, RoutedEventArgs e)
{
string path;
if (ShowPdf)
{
Title = "FSI PDF-Auswahl";
path = Settings.Setting<string>("Epl.Pdf.Path");
}
else
{
Title = "FSI Epl Projektauswahl";
path = Settings.Setting<string>("Epl.Prj.Path");
}
Title += " v" + Assembly.GetExecutingAssembly().GetName().Version; // Version in Titel eintragen
Prj = new ViewModelPrj(new PrjDataProvider())
{
DataPath = path,
DataPath = Path,
ShowPdf = ShowPdf,
EplExes = EplExes,
};
DataContext = Prj;
Prj.Load();
}
private void tbSearch_TextChanged(object sender, TextChangedEventArgs e)
{
tbSearch.Select(tbSearch.Text.Length, 0);
}
}
}
}

View File

@@ -40,6 +40,7 @@ namespace FSI.Lib.Guis.Prj.Mgt.ViewModel
public string DataPath { get; set; }
public bool ShowPdf { get; set; }
public string[] EplExes { get; set; }
public void Load()
{
@@ -133,19 +134,17 @@ namespace FSI.Lib.Guis.Prj.Mgt.ViewModel
}.Start();
}
else
{
var files = Settings.Setting<string>("Epl.Exe", Settings.Mode.ExeSetttings).Replace(Environment.NewLine, "").Replace("\t", "").Split(";");
{
var arguments = " /Variant:\"Electric P8\" ProjectOpen /Project:\"" + SeletctedPrj.FullName + "\"";
string fileName = string.Empty;
string path = string.Empty;
for (int i = 0; i <= files.Length - 1; i++)
for (int i = 0; i <= EplExes.Length - 1; i++)
{
if (File.Exists(files[i].Trim()))
if (File.Exists(EplExes[i].Trim()))
{
fileName = files[i].Trim();
fileName = EplExes[i].Trim();
}
}

View File

@@ -1,73 +0,0 @@
using System;
using System.Configuration;
using System.Globalization;
using System.Reflection;
namespace FSI.Lib
{
public static class Settings
{
//static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().CodeBase);
#if NET472
static UriBuilder uri = new UriBuilder(Assembly.GetExecutingAssembly().Location);
#elif NET6_0
static UriBuilder uri = new(Assembly.GetExecutingAssembly().Location);
#endif
static readonly NumberFormatInfo nfi = new NumberFormatInfo()
{
NumberGroupSeparator = "",
CurrencyDecimalSeparator = "."
};
public static T Setting<T>(string name)
{
return Setting<T>(name, Mode.DllSettings);
}
public static T Setting<T>(string name, Mode exeSettings)
{
if (exeSettings == Mode.ExeSetttings)
{
Configuration configuration = ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.None);
AppSettingsSection appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");
return (T)Convert.ChangeType(appSettingsSection.Settings[name].Value, typeof(T), nfi);
}
if (exeSettings == Mode.DllSettings)
{
Configuration configuration = ConfigurationManager.OpenExeConfiguration(uri.Path);
AppSettingsSection appSettingsSection = (AppSettingsSection)configuration.GetSection("appSettings");
return (T)Convert.ChangeType(appSettingsSection.Settings[name].Value, typeof(T), nfi);
}
return (T)Convert.ChangeType(null, typeof(T), nfi);
}
public enum Mode
{
ExeSetttings,
DllSettings,
}
}
}
/*
App.Config file sample
<add key="Enabled" value="true" />
<add key="ExportPath" value="c:\" />
<add key="Seconds" value="25" />
<add key="Ratio" value="0.14" />
Usage:
somebooleanvar = Settings.Setting<bool>("Enabled");
somestringlvar = Settings.Setting<string>("ExportPath");
someintvar = Settings.Setting<int>("Seconds");
somedoublevar = Settings.Setting<double>("Ratio");
*/

View File

@@ -0,0 +1,90 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace FSI.Lib.WinSettings
{
internal static class ArrayToString
{
/// <summary>
/// Represents the given array as a single string.
/// </summary>
/// <param name="array">String array to encode.</param>
/// <returns>The encoded string.</returns>
public static string Encode(string[] array)
{
StringBuilder builder = new StringBuilder();
if (array == null)
return string.Empty;
for (int i = 0; i < array.Length; i++)
{
if (i > 0)
builder.Append(',');
if (array[i].IndexOfAny(new[] { ',', '"', '\r', '\n' }) >= 0)
builder.Append(string.Format("\"{0}\"", array[i].Replace("\"", "\"\"")));
else
builder.Append(array[i]);
}
return builder.ToString();
}
/// <summary>
/// Decodes a string created with <see cref="Encode"></see> back to an array.
/// </summary>
/// <param name="s">String to decode.</param>
/// <returns>The decoded array.</returns>
public static string[] Decode(string s)
{
List<string> list = new List<string>();
int pos = 0;
if (s == null)
return Array.Empty<string>();
while (pos < s.Length)
{
if (s[pos] == '\"')
{
// Parse quoted value
StringBuilder builder = new StringBuilder();
// Skip starting quote
pos++;
while (pos < s.Length)
{
if (s[pos] == '"')
{
// Skip quote
pos++;
// One quote signifies end of value
// Two quote signifies single quote literal
if (pos >= s.Length || s[pos] != '"')
break;
}
builder.Append(s[pos++]);
}
list.Add(builder.ToString());
// Skip delimiter
pos = s.IndexOf(',', pos);
if (pos == -1)
pos = s.Length;
pos++;
}
else
{
// Parse value
int start = pos;
pos = s.IndexOf(',', pos);
if (pos == -1)
pos = s.Length;
list.Add(s.Substring(start, pos - start));
// Skip delimiter
pos++;
}
}
return list.ToArray();
}
}
}

View File

@@ -0,0 +1,13 @@
using System;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// This attribute specifies that this property should be encrypted
/// when it is saved.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class EncryptedSettingAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,13 @@
using System;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Attribute specifies that this property does not represent a setting and
/// should not be saved.
/// </summary>
[AttributeUsage(AttributeTargets.Property)]
public class ExcludedSettingAttribute : Attribute
{
}
}

View File

@@ -0,0 +1,337 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Represents one name/value pair in an INI file.
/// </summary>
internal class IniSetting
{
/// <summary>
/// The name of this INI setting.
/// </summary>
public string Name { get; set; }
/// <summary>
/// The value of this INI setting.
/// </summary>
public string Value { get; set; }
}
/// <summary>
/// Class to create and read INI files.
/// </summary>
internal class IniFile
{
/// <summary>
/// Section used for settings not under any section header (within [])
/// </summary>
public const string DefaultSectionName = "General";
/// <summary>
/// Represents an entire INI file section.
/// </summary>
private class IniSection
{
public string Name { get; set; }
public Dictionary<string, IniSetting> Settings { get; private set; }
public IniSection()
{
Name = string.Empty;
Settings = new Dictionary<string, IniSetting>(StringComparer.OrdinalIgnoreCase);
}
}
private readonly Dictionary<string, IniSection> Sections = new Dictionary<string, IniSection>(StringComparer.OrdinalIgnoreCase);
#region File functions
/// <summary>
/// Loads an INI settings file.
/// </summary>
/// <param name="filename">Path of file to load.</param>
public void Load(string filename)
{
Sections.Clear();
// Default section
IniSection section = new IniSection { Name = DefaultSectionName };
Sections.Add(section.Name, section);
string line;
using StreamReader file = new StreamReader(filename);
while ((line = file.ReadLine()) != null)
{
line = line.TrimStart();
if (line.Length > 0)
{
if (line[0] == ';')
{
// Ignore comments
}
else if (line[0] == '[')
{
// Parse section header
int pos = line.IndexOf(']', 1);
if (pos == -1)
pos = line.Length;
#if NETSTANDARD2_0
string name = line.Substring(1, pos - 1).Trim();
#else
string name = line[1..pos].Trim();
#endif
if (name.Length > 0)
{
if (!Sections.TryGetValue(name, out section))
{
section = new IniSection { Name = name };
Sections.Add(section.Name, section);
}
}
}
else
{
// Parse setting name and value
string name, value;
int pos = line.IndexOf('=');
if (pos == -1)
{
name = line.Trim();
value = string.Empty;
}
else
{
name = line.Substring(0, pos).Trim();
#if NETSTANDARD2_0
value = line.Substring(pos + 1);
#else
value = line[(pos + 1)..];
#endif
}
if (name.Length > 0)
{
if (section.Settings.TryGetValue(name, out IniSetting setting))
{
setting.Value = value;
}
else
{
setting = new IniSetting { Name = name, Value = value };
section.Settings.Add(name, setting);
}
}
}
}
}
}
/// <summary>
/// Writes the current settings to an INI file. If the file already exists, it is overwritten.
/// </summary>
/// <param name="filename">Path of file to write to.</param>
public void Save(string filename)
{
using StreamWriter file = new StreamWriter(filename, false);
bool firstLine = true;
foreach (IniSection section in Sections.Values)
{
if (firstLine)
firstLine = false;
else
file.WriteLine();
if (section.Settings.Any())
{
file.WriteLine("[{0}]", section.Name);
foreach (IniSetting setting in section.Settings.Values)
file.WriteLine("{0}={1}", setting.Name, setting.Value);
}
}
}
#endregion
#region Read values
/// <summary>
/// Returns the value of an INI setting.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found.</param>
/// <returns>Returns the specified setting value.</returns>
public string GetSetting(string section, string setting, string defaultValue = null)
{
if (Sections.TryGetValue(section, out IniSection iniSection))
{
if (iniSection.Settings.TryGetValue(setting, out IniSetting iniSetting))
return iniSetting.Value;
}
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as an integer value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a integer value.</param>
/// <returns>Returns the specified setting value as an integer value.</returns>
public int GetSetting(string section, string setting, int defaultValue)
{
if (int.TryParse(GetSetting(section, setting), out int value))
return value;
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as a double value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a double value.</param>
/// <returns>Returns the specified setting value as a double value.</returns>
public double GetSetting(string section, string setting, double defaultValue)
{
if (double.TryParse(GetSetting(section, setting), out double value))
return value;
return defaultValue;
}
/// <summary>
/// Returns the value of an INI setting as a Boolean value.
/// </summary>
/// <param name="section">The INI file section.</param>
/// <param name="setting">The INI setting name.</param>
/// <param name="defaultValue">The value to return if the setting was not found,
/// or if it could not be converted to a Boolean value.</param>
/// <returns>Returns the specified setting value as a Boolean.</returns>
public bool GetSetting(string section, string setting, bool defaultValue)
{
if (ConvertToBool(GetSetting(section, setting), out bool value))
return value;
return defaultValue;
}
/// <summary>
/// Returns all settings in the given INI section.
/// </summary>
/// <param name="section">The section that contains the settings to be retrieved.</param>
/// <returns>Returns the settings in the given INI section.</returns>
public IEnumerable<IniSetting> GetSectionSettings(string section)
{
if (Sections.TryGetValue(section, out IniSection iniSection))
{
foreach (var setting in iniSection.Settings)
yield return setting.Value;
}
}
#endregion
#region Write values
/// <summary>
/// Sets an INI file setting. The setting is not written to disk until
/// <see cref="Save"/> is called.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, string value)
{
if (!Sections.TryGetValue(section, out IniSection iniSection))
{
iniSection = new IniSection { Name = section };
Sections.Add(iniSection.Name, iniSection);
}
if (!iniSection.Settings.TryGetValue(setting, out IniSetting iniSetting))
{
iniSetting = new IniSetting { Name = setting };
iniSection.Settings.Add(iniSetting.Name, iniSetting);
}
iniSetting.Value = value;
}
/// <summary>
/// Sets an INI file setting with an integer value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, int value)
{
SetSetting(section, setting, value.ToString());
}
/// <summary>
/// Sets an INI file setting with a double value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, double value)
{
SetSetting(section, setting, value.ToString());
}
/// <summary>
/// Sets an INI file setting with a Boolean value.
/// </summary>
/// <param name="section">The INI-file section.</param>
/// <param name="setting">The name of the INI-file setting.</param>
/// <param name="value">The value of the INI-file setting</param>
public void SetSetting(string section, string setting, bool value)
{
SetSetting(section, setting, value.ToString());
}
#endregion
#region Boolean parsing
private readonly string[] TrueStrings = { "true", "yes", "on" };
private readonly string[] FalseStrings = { "false", "no", "off" };
private bool ConvertToBool(string s, out bool value)
{
if (s == null)
value = false;
if (TrueStrings.Any(s2 => string.Compare(s, s2, true) == 0))
value = true;
else if (FalseStrings.Any(s2 => string.Compare(s, s2, true) == 0))
value = false;
else if (int.TryParse(s, out int i))
value = i != 0;
else
{
value = false;
return false;
}
return true;
}
#endregion
//public void Dump()
//{
// foreach (IniSection section in Sections.Values)
// {
// Debug.WriteLine(string.Format("[{0}]", section.Name));
// foreach (IniSetting setting in section.Settings.Values)
// Debug.WriteLine("[{0}]=[{1}]", setting.Name, setting.Value);
// }
//}
}
}

View File

@@ -0,0 +1,142 @@
using System;
using System.Collections.Generic;
using System.IO;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// The <see cref="IniSettings"/> class makes it very easy to save your application
/// settings to an INI file.
/// </summary>
/// <remarks>
/// <para>
/// To use the class, simply derive your own settings class from
/// <see cref="IniSettings" /> and add the public properties that you want to be
/// saved as settings. You can then call the <see cref="Settings.Load"/> and
/// <see cref="Settings.Save"/> methods to read or write those settings to an INI
/// file.
/// </para>
/// <para>
/// Your derived class' constructor should initialize your settings properties to
/// their default values.
/// </para>
/// <para>
/// Two attributes are available for public properties in your derived class. The
/// first is <see cref="EncryptedSettingAttribute" />. Use this attribute if you
/// want the setting to be encrypted when saved to file. When using this attribute on
/// any property, you must provide a valid encryption password to the
/// <see cref="IniSettings" /> constructor.
/// </para>
/// <para>
/// The second is the <see cref="ExcludedSettingAttribute"/>. Use this attribute
/// on any properties that are used internally by your code and should not saved to
/// file.
/// </para>
/// <para>
/// All public properties without the <see cref="ExcludedSettingAttribute"></see>
/// attribute must be of one of the supported data types. This includes all the basic
/// data types as well as <see cref="string[]"></see> and <see cref="byte[]"></see>.
/// All other types will raise an exception. In addition, INI files do not support
/// strings that contain newlines unless those strings are encrypted.
/// </para>
/// </remarks>
/// <example>
/// The following example creates a settings class called <c>MySettings</c> with
/// several properties, two of which are encrypted when saved to file.
/// <code>
/// public class MySettings : IniSettings
/// {
/// // Define properties to be saved to file
/// public string EmailHost { get; set; }
/// public int EmailPort { get; set; }
///
/// // The following properties will be encrypted
/// [EncryptedSetting]
/// public string UserName { get; set; }
/// [EncryptedSetting]
/// public string Password { get; set; }
///
/// // The following property will not be saved to file
/// // Non-public properties are also not saved to file
/// [ExcludedSetting]
/// public DateTime Created { get; set; }
///
/// public MySettings(string filename)
/// : base(filename, "Password123")
/// {
/// // Set initial, default property values
/// EmailHost = string.Empty;
/// EmailPort = 0;
/// UserName = string.Empty;
/// Password = string.Empty;
///
/// Created = DateTime.Now;
/// }
/// }
/// </code>
/// </example>
/// <seealso cref="RegistrySettings"/>
/// <seealso cref="XmlSettings"/>
public abstract class IniSettings : Settings
{
/// <summary>
/// Gets or sets the name of the INI settings file.
/// </summary>
[ExcludedSetting]
public string FileName { get; set; }
/// <summary>
/// Constructs an instance of the <c>XmlSettings</c> class.
/// </summary>
/// <param name="filename">Name of the settings file.</param>
/// <param name="password">Encryption password. May be <c>null</c>
/// if no settings use the <see cref="EncryptedSettingAttribute" />
/// attribute.</param>
public IniSettings(string filename, string password = null)
: base(password)
{
if (string.IsNullOrWhiteSpace(filename))
throw new ArgumentException("A valid path and file name is required.", nameof(filename));
FileName = filename;
}
/// <summary>
/// Performs internal load operations.
/// </summary>
/// <param name="settings">Settings to be loaded.</param>
public override void OnLoadSettings(IEnumerable<Setting> settings)
{
if (File.Exists(FileName))
{
// Load INI file
IniFile iniFile = new IniFile();
iniFile.Load(FileName);
// Read settings
foreach (Setting setting in settings)
{
string value = iniFile.GetSetting(IniFile.DefaultSectionName, setting.Name, null);
if (value != null)
setting.SetValueFromString(value);
}
}
}
/// <summary>
/// Performs internal save operations.
/// </summary>
/// <param name="settings">Settings to be saved.</param>
public override void OnSaveSettings(IEnumerable<Setting> settings)
{
// Create INI file
IniFile iniFile = new IniFile();
// Write settings
foreach (Setting setting in settings)
{
string value = setting.GetValueAsString();
if (value != null)
iniFile.SetSetting(IniFile.DefaultSectionName, setting.Name, value);
}
iniFile.Save(FileName);
}
}
}

View File

@@ -0,0 +1,180 @@
# WinSettings
[![NuGet version (SoftCircuits.WinSettings)](https://img.shields.io/nuget/v/SoftCircuits.WinSettings.svg?style=flat-square)](https://www.nuget.org/packages/SoftCircuits.WinSettings/)
```
Install-Package SoftCircuits.WinSettings
```
## Overview
WinSettings is a .NET class library that makes it easy to save and retrieve application settings on Windows. It includes three settings classes: `IniSettings`, which stores the settings to an INI file; `XmlSettings`, which stores the settings to an XML file, and `RegistrySettings`, which stores the settings to the Windows registry. In addition, it makes it easy to define your own settings type.
Settings can be encrypted just by adding a property attribute. There is also an attribute to exclude a particular property when the property is used internally and does not represent an application setting.
To use a settings class, simply derive your own settings class from one of the ones described above and add public properties that you want to be saved. Your class' constructor should set any default values. Then call the `Save()` and `Load()` methods to save the settings in your class.
## IniSettings Class
The <see cref="IniSettings"/> class makes it very easy to save your application settings to an INI file.
To use the class, simply derive your own settings class from `IniSettings` and add the public properties that you want to be saved as settings. You can then call the `Load()` and `Save()` methods to read or write those settings to an INI file.
Your derived class' constructor should initialize your settings properties to their default values.
Two attributes are available for public properties in your derived class. The first is `EncryptedSettingAttribute`. Use this attribute if you want the setting to be encrypted when saved to file. When using this attribute on any property, you must provide a valid encryption password to the `IniSettings` constructor.
The second is the `ExcludedSettingAttribute`. Use this attribute on any properties that are used internally by your code and should not saved to file.
All public properties without the `ExcludedSettingAttribute` attribute must be of one of the supported data types. This includes all the basic data types as well as `string[]` and `byte[]`. All other types will raise an exception. In addition, INI files do not support strings that contain newlines unless those strings are encrypted.
#### Example
The following example creates a settings class called `MySettings` with several properties, two of which are encrypted when saved to file.
```cs
public class MySettings : IniSettings
{
// Define properties to be saved to file
public string EmailHost { get; set; }
public int EmailPort { get; set; }
// The following properties will be encrypted
[EncryptedSetting]
public string UserName { get; set; }
[EncryptedSetting]
public string Password { get; set; }
// The following property will not be saved to file
// Non-public properties are also not saved to file
[ExcludedSetting]
public DateTime Created { get; set; }
public MySettings(string filename)
: base(filename, "Password123")
{
// Set initial, default property values
EmailHost = string.Empty;
EmailPort = 0;
UserName = string.Empty;
Password = string.Empty;
Created = DateTime.Now;
}
}
```
## XmlSettings Class
The <see `XmlSettings` class makes it very easy to save your application settings to an XML file.
To use the class, simply derive your own settings class from `XmlSettings` and add the public properties that you want to be saved as settings. You can then call the `Load()` and `Save()` methods to read or write those settings to an XML file.
Your derived class' constructor should initialize your settings properties to their default values.
Two attributes are available for public properties in your derived class. The first is `EncryptedSettingAttribute`. Use this attribute if you want the setting to be encrypted when saved to file. When using this attribute on any property, you must provide a valid encryption password to the `XmlSettings` constructor.
The second is the `ExcludedSettingAttribute` Use this attribute on any properties that are used internally by your code and should not saved to file.
All public properties without the `ExcludedSettingAttribute` attribute must be of one of the supported data types. This includes all the basic data types `string[]` and `byte[]`. All other types will raise an exception.
#### Example
The following example creates a settings class called `MySettings` with several properties, two of which are encrypted when saved to file.
```cs
public class MySettings : XmlSettings
{
// Define properties to be saved to file
public string EmailHost { get; set; }
public int EmailPort { get; set; }
// The following properties will be encrypted
[EncryptedSetting]
public string UserName { get; set; }
[EncryptedSetting]
public string Password { get; set; }
// The following property will not be saved to file
// Non-public properties are also not saved to file
[ExcludedSetting]
public DateTime Created { get; set; }
public MySettings(string filename)
: base(filename, "Password123")
{
// Set initial, default property values
EmailHost = string.Empty;
EmailPort = 0;
UserName = string.Empty;
Password = string.Empty;
Created = DateTime.Now;
}
}
```
## RegistrySettings Class
The `RegistrySettings` class makes it very easy to save your application settings to the system registry.
To use the class, simply derive your own settings class from `RegistrySettings` and add the public properties that you want to be
saved as settings. You can then call the `Load()` and `Save()` methods to read or write those settings to the system registry.
Your derived class' constructor should initialize your settings properties to their default values.
Two attributes are available for public properties in your derived class. The first is `EncryptedSettingAttribute`. Use this attribute if you want the setting to be encrypted when saved to file. When using this attribute on any property, you must provide a valid encryption password to the `RegistrySettings` constructor.
The second is the `ExcludedSettingAttribute`. Use this attribute on any properties that are used internally by your code and should not saved to the registry.
All public properties without the `ExcludedSettingAttribute` attribute must be of one of the supported data types. This includes all the basic data types as well as `string[]` and `byte[]`. All other types will raise an exception.
#### Example
The following example creates a settings class called `MySettings` with several properties, two of which are encrypted when saved to file.
```cs
public class MySettings : RegistrySettings
{
// Define properties to be saved to file
public string EmailHost { get; set; }
public int EmailPort { get; set; }
// The following properties will be encrypted
[EncryptedSetting]
public string UserName { get; set; }
[EncryptedSetting]
public string Password { get; set; }
// The following property will not be saved to file
// Non-public properties are also not saved to file
[ExcludedSetting]
public DateTime Created { get; set; }
public MySettings(string companyName, string applicationName, RegistrySettingsType settingsType)
: base(companyName, applicationName, settingsType, "Password123")
{
// Set initial, default property values
EmailHost = string.Empty;
EmailPort = 0;
UserName = string.Empty;
Password = string.Empty;
Created = DateTime.Now;
}
}
```
## Settings Class
The `Settings` class is the base class for the `IniSettings`, `XmlSettings` and `RegistrySettings` classes. You don't need this class but you could use it to create your own type of custom settings class.
To do this, create your own `static`, `abstract` class that derives from `Settings` and override the virtual `OnSaveSettings()` and `OnLoadSettings()` methods.
As the name suggests, `OnSaveSettings()` is called when the settings are being saved. This method is passed a collection of `Setting` objects. Your handler needs to write these settings to your custom data store. The `Setting.Name` property contains the setting name. Use the `Setting.GetValue()` method to get the value. Or use the `Setting.GetValueAsString()` instead if your data store only supports string values.
The steps to override `OnLoadSettings()` is similar. This method is also passed a collection of `Setting` objects. Your handler needs to read each named setting from your custom data store. You can then set that value using the `Setting.SetValue()` or `Setting.SetValueFromString()` methods.
## Dependencies
This project requires the NuGet packages [SoftCircuits.EasyEncryption](https://www.nuget.org/packages/SoftCircuits.EasyEncryption/) and Microsoft.Win32.Registry.

View File

@@ -0,0 +1,154 @@
using Microsoft.Win32;
using System.Collections.Generic;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Specifies the location within the registry where <see cref="RegistrySettings"/> stores
/// settings.
/// </summary>
public enum RegistrySettingsType
{
/// <summary>
/// Stores settings in the Windows registry base key HKEY_CURRENT_USER, normally
/// used for storing information about the current user preferences.
/// </summary>
CurrentUser,
/// <summary>
/// Stores settings in thee Windows registry base key HKEY_LOCAL_MACHINE, normally
/// use for storing configuration data for the local machine.
/// </summary>
LocalMachine
}
/// <summary>
/// The <see cref="RegistrySettings"/> class makes it very easy to save your application
/// settings to the system registry.
/// </summary>
/// <remarks>
/// <para>
/// To use the class, simply derive your own settings class from
/// <see cref="RegistrySettings" /> and add the public properties that you want to be
/// saved as settings. You can then call the <see cref="Settings.Load"/> and
/// <see cref="Settings.Save"/> methods to read or write those settings to the
/// system registry.
/// </para>
/// <para>
/// Your derived class' constructor should initialize your settings properties to
/// their default values.
/// </para>
/// <para>
/// Two attributes are available for public properties in your derived class. The
/// first is <see cref="EncryptedSettingAttribute" />. Use this attribute if you
/// want the setting to be encrypted when saved to file. When using this attribute on
/// any property, you must provide a valid encryption password to the
/// <see cref="RegistrySettings" /> constructor.
/// </para>
/// <para>
/// The second is the <see cref="ExcludedSettingAttribute"/>. Use this attribute
/// on any properties that are used internally by your code and should not saved to
/// the registry.
/// </para>
/// <para>
/// All public properties without the <see cref="ExcludedSettingAttribute"></see>
/// attribute must be of one of the supported data types. This includes all the basic
/// data types as well as <see cref="string[]"></see> and <see cref="byte[]"></see>.
/// All other types will raise an exception.
/// </para>
/// </remarks>
/// <example>
/// The following example creates a settings class called <c>MySettings</c> with
/// several properties, two of which are encrypted when saved to file.
/// <code>
/// public class MySettings : RegistrySettings
/// {
/// // Define properties to be saved to file
/// public string EmailHost { get; set; }
/// public int EmailPort { get; set; }
///
/// // The following properties will be encrypted
/// [EncryptedSetting]
/// public string UserName { get; set; }
/// [EncryptedSetting]
/// public string Password { get; set; }
///
/// // The following property will not be saved to file
/// // Non-public properties are also not saved to file
/// [ExcludedSetting]
/// public DateTime Created { get; set; }
///
/// public MySettings(string companyName, string applicationName, RegistrySettingsType settingsType)
/// : base(companyName, applicationName, settingsType, "Password123")
/// {
/// // Set initial, default property values
/// EmailHost = string.Empty;
/// EmailPort = 0;
/// UserName = string.Empty;
/// Password = string.Empty;
///
/// Created = DateTime.Now;
/// }
/// }
/// </code>
/// </example>
/// <seealso cref="IniSettings"/>
/// <seealso cref="XmlSettings"/>
public abstract class RegistrySettings : Settings
{
private readonly string SubKeyPath;
private readonly RegistryKey RegistryKey;
/// <summary>
/// Constructs a new <c>RegistrySettings</c> instance.
/// </summary>
/// <param name="companyName">Company name entry in registry.</param>
/// <param name="applicationName">Application name entry in registration.</param>
/// <param name="settingsType">Section to store entries in registry.</param>
/// <param name="password">Encryption password. May be <c>null</c> if no settings
/// use the <see cref="EncryptedSettingAttribute" /> attribute.</param>
public RegistrySettings(string companyName, string applicationName, RegistrySettingsType settingsType, string password = null)
: base(password)
{
SubKeyPath = string.Format("Software\\{0}\\{1}", companyName, applicationName);
RegistryKey = settingsType == RegistrySettingsType.CurrentUser ? Registry.CurrentUser : Registry.LocalMachine;
}
/// <summary>
/// Performs internal save operations.
/// </summary>
/// <param name="settings">Settings to be saved.</param>
public override void OnSaveSettings(IEnumerable<Setting> settings)
{
using (RegistryKey registryKey = RegistryKey.CreateSubKey(SubKeyPath, RegistryKeyPermissionCheck.ReadWriteSubTree))
{
foreach (var setting in settings)
{
var value = setting.GetValue();
if (value != null)
registryKey.SetValue(setting.Name, value);
}
}
}
/// <summary>
/// Performs internal load operations.
/// </summary>
/// <param name="settings">Settings to be loaded.</param>
public override void OnLoadSettings(IEnumerable<Setting> settings)
{
using (RegistryKey registryKey = RegistryKey.OpenSubKey(SubKeyPath))
{
if (registryKey != null)
{
foreach (var setting in settings)
{
object value = registryKey.GetValue(setting.Name);
if (value != null)
setting.SetValue(value);
}
}
}
}
}
}

View File

@@ -0,0 +1,117 @@
using System;
using System.Diagnostics;
using System.Linq;
using System.Reflection;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Represents a single setting for <see cref="Settings"></see>-derived classes.
/// </summary>
public class Setting
{
private readonly Settings Settings;
private readonly PropertyInfo PropertyInfo;
private readonly bool Encrypted;
/// <summary>
/// Constructs a new instance of the <see cref="Setting"></see> class.
/// </summary>
/// <param name="settings">The <see cref="Settings"/> class that contains
/// this property (setting).</param>
/// <param name="propertyInfo">The <see cref="PropertyInfo"></see> for this
/// property.</param>
/// <param name="encrypted">Indicates whether or not this setting is
/// encrypted.</param>
public Setting(Settings settings, PropertyInfo propertyInfo, bool encrypted)
{
Settings = settings;
PropertyInfo = propertyInfo;
Encrypted = encrypted;
}
/// <summary>
/// Gets the name of this setting.
/// </summary>
public string Name => PropertyInfo.Name;
/// <summary>
/// Gets the type of this setting.
/// </summary>
public Type Type => Encrypted ? typeof(string) : PropertyInfo.PropertyType;
/// <summary>
/// Gets the value of this setting.
/// </summary>
/// <returns>Returns the value of this setting.</returns>
public object GetValue()
{
object value = PropertyInfo.GetValue(Settings);
if (value != null && Encrypted && Settings.Encryption != null)
return Settings.Encryption.Encrypt(value);
return value;
}
/// <summary>
/// Sets the value of this setting.
/// </summary>
/// <param name="value">The value this setting should be set to.</param>
public void SetValue(object value)
{
// Leave property value unmodified if no value or error
if (value != null)
{
try
{
if (Encrypted && Settings.Encryption != null)
{
// Ecrypted values stored as string
if (value is string s)
PropertyInfo.SetValue(Settings, Settings.Encryption.Decrypt(s, PropertyInfo.PropertyType));
}
else PropertyInfo.SetValue(Settings, Convert.ChangeType(value, Type));
}
catch (Exception) { Debug.Assert(false); }
}
}
/// <summary>
/// Gets this setting's value as a string.
/// </summary>
/// <returns>Returns this setting's value as a string.</returns>
public string GetValueAsString()
{
object value = GetValue();
if (value == null)
return string.Empty;
else if (value is byte[] byteArray)
return ArrayToString.Encode(byteArray.Select(b => b.ToString()).ToArray());
else if (value is string[] stringArray)
return ArrayToString.Encode(stringArray);
else
return value?.ToString() ?? string.Empty;
}
/// <summary>
/// Sets this setting's value from a string.
/// </summary>
/// <param name="value">A string that represents the value this setting should be set to.</param>
public void SetValueFromString(string value)
{
if (value != null)
{
try
{
if (Type == typeof(byte[]))
SetValue(ArrayToString.Decode(value).Select(s => byte.Parse(s)).ToArray());
else if (Type == typeof(string[]))
SetValue(ArrayToString.Decode(value));
else
SetValue(value);
}
catch (Exception) { Debug.Assert(false); }
}
}
}
}

View File

@@ -0,0 +1,106 @@
using FSI.Lib.EasyEncryption;
using System;
using System.Collections.Generic;
using System.Reflection;
namespace FSI.Lib.WinSettings
{
/// <summary>
/// Provides an abstract base class for specialized settings classes.
/// </summary>
/// <remarks>
/// <para>
/// Specialized classes should inherit from this class and implement specific storage and
/// retrieval logic for each settings by overriding the
/// <see cref="OnSaveSettings(IEnumerable{Setting})"/> and
/// <see cref="OnLoadSettings(IEnumerable{Setting})"/> methods.
/// </para>
/// <para>
/// Ultimately, the specialized classes will then be overridden by each application's
/// settings class. The public properties in that class will become the settings that
/// are saved by classes that derive from this class.
/// </para>
/// </remarks>
public abstract class Settings
{
private IEnumerable<Setting> SettingsList { get; }
/// <summary>
/// Abstract method called when the settings should be saved. Allows
/// the derived class to save those settings in a specialized way.
/// </summary>
/// <param name="settings">The list of settings to be saved.</param>
public abstract void OnSaveSettings(IEnumerable<Setting> settings);
/// <summary>
/// Abstract method called when the settings sould be loaded. Allows
/// the derived class to load those settings in a specialized way.
/// </summary>
/// <param name="settings">The list of settings to be loaded.</param>
public abstract void OnLoadSettings(IEnumerable<Setting> settings);
/// <summary>
/// Gets the <c>Encryption</c> instance associated with this <c>Settings</c>
/// instance.
/// </summary>
[ExcludedSetting]
public Encryption? Encryption { get; }
/// <summary>
/// Constructs a new <see cref="Settings"></see> instance.
/// </summary>
/// <remarks>
/// An exception is thrown if password is null but one or more properties have the
/// <see cref="EncryptedSettingAttribute"></see> attribute.
/// </remarks>
/// <param name="password">Encryption password. Can be <c>null</c> if no
/// properties have the <see cref="EncryptedSettingAttribute"></see>
/// attribute.</param>
public Settings(string password = null)
{
if (password == null)
password = GetType().Namespace.ToString();
SettingsList = BuildSettingsList();
Encryption = password != null ?
new Encryption(password, EncryptionAlgorithm.TripleDes) :
null;
}
/// <summary>
/// Saves all settings.
/// </summary>
public void Save()
{
OnSaveSettings(SettingsList);
}
/// <summary>
/// Loads all settings.
/// </summary>
public void Load()
{
OnLoadSettings(SettingsList);
}
private IEnumerable<Setting> BuildSettingsList()
{
// Iterate through all public instance properties
foreach (PropertyInfo prop in GetType().GetProperties(BindingFlags.Instance | BindingFlags.Public))
{
// Ignore properties with ExcludedSetting attribute
if (!Attribute.IsDefined(prop, typeof(ExcludedSettingAttribute)))
{
// Test for supported data type (same types as for Encryption class)
if (!Encryption.IsTypeSupported(prop.PropertyType))
throw new Exception(string.Format("Settings property '{0}' is an unsupported data type '{1}'. Change property type or use ExcludedSetting attribute.",
prop.Name, prop.PropertyType.ToString()));
bool encrypted = Attribute.IsDefined(prop, typeof(EncryptedSettingAttribute));
if (encrypted && Encryption == null)
throw new InvalidOperationException("Encryption password cannot be null if any settings have the EncryptedSetting attribute.");
yield return new Setting(this, prop, encrypted);
}
}
}
}
}

View File

@@ -0,0 +1,149 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
namespace FSI.Lib.WinSettings;
/// <summary>
/// The <see cref="XmlSettings"/> class makes it very easy to save your application
/// settings to an XML file.
/// </summary>
/// <remarks>
/// <para>
/// To use the class, simply derive your own settings class from
/// <see cref="XmlSettings" /> and add the public properties that you want to be
/// saved as settings. You can then call the <see cref="Settings.Load"/> and
/// <see cref="Settings.Save"/> methods to read or write those settings to an XML
/// file.
/// </para>
/// <para>
/// Your derived class' constructor should initialize your settings properties to
/// their default values.
/// </para>
/// <para>
/// Two attributes are available for public properties in your derived class. The
/// first is <see cref="EncryptedSettingAttribute" />. Use this attribute if you
/// want the setting to be encrypted when saved to file. When using this attribute on
/// any property, you must provide a valid encryption password to the
/// <see cref="XmlSettings" /> constructor.
/// </para>
/// <para>
/// The second is the <see cref="ExcludedSettingAttribute"/>. Use this attribute
/// on any properties that are used internally by your code and should not saved to
/// file.
/// </para>
/// <para>
/// All public properties without the <see cref="ExcludedSettingAttribute"></see>
/// attribute must be of one of the supported data types. This includes all the basic
/// data types as well as <see cref="string[]"></see> and <see cref="byte[]"></see>.
/// All other types will raise an exception.
/// </para>
/// </remarks>
/// <example>
/// The following example creates a settings class called <c>MySettings</c> with
/// several properties, two of which are encrypted when saved to file.
/// <code>
/// public class MySettings : XmlSettings
/// {
/// // Define properties to be saved to file
/// public string EmailHost { get; set; }
/// public int EmailPort { get; set; }
///
/// // The following properties will be encrypted
/// [EncryptedSetting]
/// public string UserName { get; set; }
/// [EncryptedSetting]
/// public string Password { get; set; }
///
/// // The following property will not be saved to file
/// // Non-public properties are also not saved to file
/// [ExcludedSetting]
/// public DateTime Created { get; set; }
///
/// public MySettings(string filename)
/// : base(filename, "Password123")
/// {
/// // Set initial, default property values
/// EmailHost = string.Empty;
/// EmailPort = 0;
/// UserName = string.Empty;
/// Password = string.Empty;
///
/// Created = DateTime.Now;
/// }
/// }
/// </code>
/// </example>
/// <seealso cref="IniSettings"/>
/// <seealso cref="RegistrySettings"/>
public abstract class XmlSettings : Settings
{
/// <summary>
/// Gets or sets the name of the XML settings file.
/// </summary>
[ExcludedSetting]
public string FileName { get; set; }
/// <summary>
/// Constructs an instance of the <see cref="XmlSettings"></see> class.
/// </summary>
/// <param name="filename">Name of the settings file.</param>
/// <param name="password">Encryption password. May be <c>null</c> if
/// no settings use the <see cref="EncryptedSettingAttribute" />
/// attribute.</param>
public XmlSettings(string filename, string password = null)
: base(password)
{
if (string.IsNullOrWhiteSpace(filename))
throw new ArgumentException("A valid file name is required.", nameof(filename));
FileName = filename;
}
/// <summary>
/// Performs internal load operations.
/// </summary>
/// <param name="settings">Settings to be loaded.</param>
public override void OnLoadSettings(IEnumerable<Setting> settings)
{
if (File.Exists(FileName))
{
// Load XML document
XmlDocument doc = new XmlDocument();
doc.Load(FileName);
// Read settings
foreach (Setting setting in settings)
{
XmlNode node = doc.DocumentElement?.SelectSingleNode(setting.Name);
if (node != null)
setting.SetValueFromString(node.InnerText);
}
}
}
/// <summary>
/// Performs internal save operations.
/// </summary>
/// <param name="settings">Settings to be saved.</param>
public override void OnSaveSettings(IEnumerable<Setting> settings)
{
// Create settings document
XmlDocument doc = new XmlDocument();
doc.AppendChild(doc.CreateXmlDeclaration("1.0", "UTF-8", null));
doc.AppendChild(doc.CreateElement("Settings"));
// Write settings
foreach (Setting setting in settings)
{
string value = setting.GetValueAsString();
if (value != null)
{
XmlElement element = doc.CreateElement(setting.Name);
element.InnerText = value;
doc.DocumentElement!.AppendChild(element);
}
}
doc.Save(FileName);
}
}