Knihovna NETGeniumConnection.dll určená pro .NET Framework 4.7.2 | .NET 9 | .NET 10
1. Základní informace
- Konzolové aplikace slouží k volání vlastního programového kódu v jazyce C# buď na straně serveru, nebo na straně klienta.
- Konzolové aplikace se používají v případech, kdy
- je potřeba spouštět jednorázové servisní činnosti nad databází nebo
- je potřeba tyto činnosti provádět v pravidelných intervalech.
- Pravidelné spouštění konzolových aplikací je možné nastavit v plánovači úloh systému Windows, nebo je možné konzolové aplikace přizpůsobit ke spouštění jako službu Windows.
- Konzolové aplikace se používají také pro přípravu a ladění externích funkcí. Detailní popis externích funkcí je uveden v samostatné příručce Externí funkce.
- Konzolové aplikace se připojují do databáze NET Genia
- napřímo z aplikačního serveru, který je umístěný ve stejné síti jako databázový server (aplikační server a databázový server je často jeden a ten samý počítač) nebo
- pomocí webových služeb, které jsou součástí každého NET Genia.
- Přímé připojení do databáze NET Genia je doporučovaný způsob, protože je řádově rychlejší než připojení přes webové služby, a podporuje databázové transakce, které v případě webových služeb není možné používat vůbec.
- Ladění nebo úpravy zdrojových kódů, které používají přímé připojení do databáze NET Genia, vyžadují databázi umístěnou ideálně na lokálním počítači, nebo ve stejné síti. To často není možné zajistit buď z bezpečnostních důvodů, nebo kvůli příliš velké databázi, kterou není reálné zazálohovat na databázovém serveru a přenést na lokální počítač. V takovém případě je doporučováno ladit zdrojové kódy pomocí API ve spojení s webovými službami.
- Konzolové aplikace využívají objekty a metody z knihovny „NETGeniumConnection.dll“, která je uložena v adresáři „N:\NetGenium\Projekty\NetGenium\References“. „NETGeniumConnection.dll“ je knihovna se základními funkcemi pro práci s databází a se souborovými přílohami.
- Konzolové aplikace se vyvíjí prostřednictvím samostatného projektu v aplikaci „Visual Studio 2015“ a vyšší, resp. programováním zdrojových kódů tohoto projektu, a následnou kompilací projektu do souboru formátu „exe“.
2. Vytvoření konzolové aplikace
- V prvním kroku je nutné vytvořit nový projekt konzolové aplikace ve Visual Studiu pomocí následujících kroků, a přidat referenci na knihovnu „NETGeniumConnection.dll“:
- Spustit Visual Studio
- Z menu na hlavní liště zvolit „File / New / Project...“ (Ctrl+Shift+N)
- Project type: Console App (.NET Framework)
- Project name: ConsoleApp1
- Location: volitelné umístění projektu
- Solution: Create new solution
- Place solution and project in the same directory: Ano
- Create directory for solution: Ne (Visual Studio 2015)
- Framework: .NET Framework 4.7.2
- Kliknout pravým tlačítkem na „References“, zvolit „Add Reference...“, a vybrat cestu k souboru „References\NETGeniumConnection.dll“ na disku počítače
- Zvolit režim kompilace „Debug“
- Režim „Debug“ ve výchozím nastavení generuje soubory formátu „exe“ a „pdb“
- Díky souboru formátu „pdb“ se snadno odhalují chyby a přerušení v konzolových aplikacích, protože součástí „Stack Trace“ každé chyby je i název souboru a číslo řádky, na které došlo k přerušení
- Režim „Release“ se doporučuje až pro finální verzi vyladěných zdrojových kódů v konzolové aplikaci. Ve výchozím nastavení režim „Release“ generuje pouze soubor formátu „exe“.
- Spustit projekt – z menu na hlavní liště zvolit „Debug“ / „Start Debugging“ (F5)
2.1. Přímé připojení do databáze NET Genia
- Přímé připojení do databáze používá třídu „DbConnection“ umístěnou v namespace „NETGenium“. Tato třída se chová analogicky jako obvyklá třída „DbConnection“ z namespace „System.Data“, nebo „SqlConnection“ z namespace „System.Data.SqlClient“.
- Třída „DbConnection“ je universální, a používá se jak pro databázový server Firebird, tak MSSQL.
using NETGenium;
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
NETGeniumConsole console = new NETGeniumConsole();
using (DbConnection conn = new DbConnection(@"driver=firebird;datasource=localhost;user=SYSDBA;password=masterkey;database=C:\Firebird\netgenium.fdb;charset=WIN1250;collation=WIN_CZ"))
// using (DbConnection conn = new DbConnection("server=(local);Trusted_Connection=true;database=netgenium"))
using (DbCommand cmd = new DbCommand(conn))
{
conn.Open();
conn.RootPath = "C:\\inetpub\\wwwroot\\netgenium";
console.WriteLine("Connected to database");
}
console.Exit();
}
}
}
2.2. Připojení do databáze NET Genia pomocí webových služeb
- Alternativou pro přímé připojení do databáze pomocí objektu „DbConnection“ je použití objektu „NETGeniumConnection“. Jde o třídu umístěnou v namespace „System“ knihovny „NETGeniumConnection.dll“, která umožňuje připojení do databáze NET Genia pomocí webových služeb.
- Webové služby stejně jako knihovna „NETGeniumConnection.dll“ tvoří jednotné API, a jsou součástí každého NET Genia.
- Většina metod používaných pro práci s daty v knihovně „NETGeniumConnection.dll“ má implementovanou jak variantu metody určenou pro objekt „DbConnection“, tak pro „NETGeniumConnection“.
- Po vytvoření instance objektu „NETGeniumConnection“ je nutné se přihlásit pomocí jména a hesla uživatele s administrátorským oprávněním. Na toto přihlášení se vztahují omezení na povolené IP adresy, definované v nastavení NET Genia, a je-li nastavená síla hesla, přihlásí se účet „Administrator“ s prázdným heslem jen z IP adresy 127.0.0.1. Účet, u kterého externí funkce „NETGenium.LoginCode“ zahájí dvoufaktorové ověření, se tímto způsobem nepřihlásí; detailní popis funkce je uveden v samostatné příručce Externí funkce. Každé takové přihlášení čerpá licence pro přihlášení do NET Genia, proto je důležité se na konci práce odhlásit. Přihlášení uživatele bez administrátorského oprávnění sice projde a licenci čerpá, k datům ani přílohám ale přístup nemá: kromě odhlášení mu projde jen volání externí funkce metodou „ngef“, a to jen funkce povolené callbackem „NETGenium.RegisterExternalFunction“ nebo seznamem „Veřejné externí funkce“ pro jeho uživatelské skupiny.
- Připojení přes webové služby, které déle než hodinu neposlalo žádný požadavek, zanikne, jakmile se týž uživatel znovu přihlásí přes webové služby, tokenem přes integrovaný MCP server (jen požadavkem, který pro token zakládá novou relaci – prvním nebo po zániku dosavadní relace tokenu; požadavky v existující relaci tokenu připojení neukončí) nebo přes Windows z adresy s parametrem „autologin“; další volání metod pak skončí chybou a je nutné se přihlásit znovu. Dlouho běžící služba proto má po delší nečinnosti počítat s novým přihlášením, případně používat vlastní účet.
- Připojení přes webové služby zanikne bez ohledu na nečinnost také restartem NET Genia nejdříve minutu po předchozím restartu (i při aktualizaci; u více instancí nad jednou databází restartem kterékoli další instance nejdříve 6 hodin po předchozím restartu), odhlášením relace v seznamu uživatelů online, smazáním uživatele a – existuje-li konfigurační soubor „SingleLogin.txt“ – každým dalším přihlášením téhož uživatele přes webové služby, tokenem přes integrovaný MCP server (jen požadavkem, který pro token zakládá novou relaci) nebo přes Windows z adresy s parametrem „autologin“; další volání metod pak skončí chybou a je nutné se přihlásit znovu, knihovna se sama znovu nepřihlásí. Dlouho běžící služba proto má s novým přihlášením počítat kdykoli.
- Třída „NETGeniumConnection“ je universální, a používá se jak pro databázový server Firebird, tak MSSQL.
- Komunikace se vzdáleným NET Geniem by měla být vždy zabezpečená SSL certifikátem. Jedinou výjimkou, kdy můžeme používat nezabezpečenou komunikaci, je připojení do lokálního NET Genia přes adresu „http://localhost/...“.
- Připojení přes webové služby nepodporuje cloudová varianta NET Genium Online (instance „identifikator.netgenium.online“). Vzdálený přístup k databázi přes knihovnu „NETGeniumConnection“ je dostupný pouze u plné instalace NET Genia; k datům instance NET Genium Online se z vlastního kódu přistupuje přes MCP server (viz NET Genium Online).
using NETGenium;
using System;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
NETGeniumConsole console = new NETGeniumConsole();
if (true) // Varianta 1
{
using (DbConnection conn = new DbConnection())
{
conn.Open("http://localhost/netgenium", "NETGeniumConnection", "heslo");
}
}
if (true) // Varianta 2
{
NETGeniumConnection conn = new NETGeniumConnection("http://localhost/netgenium");
conn.Login("NETGeniumConnection", "heslo");
conn.Logout();
}
console.Exit();
}
}
}
3. Čtení dat z databáze
3.1. Načtení záznamů z SQL dotazu do objektu DataTable
// using NETGenium;
// using System;
// using System.Data;
DataTable data = Data.Get("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
Console.WriteLine(conn.User.FormatDataTableText(data));
foreach (DataRow row in data.Rows)
{
Console.WriteLine(row["id"]);
}
3.2. Uložení objektu DataTable na disk a jeho opětovné načtení z disku
// using NETGenium;
// using System;
// using System.Data;
DataTable data = Data.Get("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
// HTML
Files.Write(Config.RootPath + "sholiday.html", conn.User.FormatDataTable(data));
// TXT
Files.Write(Config.RootPath + "sholiday.txt", conn.User.FormatDataTableText(data));
// XML
DataSet ds = new DataSet();
ds.Tables.Add(data);
ds.WriteXml(Config.RootPath + "sholiday.xml", XmlWriteMode.WriteSchema);
ds = new DataSet();
ds.ReadXml(Config.RootPath + "sholiday.xml", XmlReadMode.ReadSchema);
data = ds.Tables[0];
// JSON
Files.Write(Config.RootPath + "sholiday.json", JSon.ToString(data));
data = JSon.ToDataTable(File.ReadAllText(Config.RootPath + "sholiday.json"));
3.3. Načtení záznamů z SQL dotazu do objektu DbRow
// using NETGenium;
// using System;
DbRow row = new DbRow("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (row.Read())
{
Console.WriteLine(row["id"]);
Console.WriteLine(row.Report());
}
3.4. Parsování hodnot
// using NETGenium;
// using System;
DbRow row = new DbRow("SELECT * FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (row.Read())
{
int id = (int)row["id"];
Console.WriteLine("id: " + id);
int pid = Parser.ToInt32(row["pid"]);
Console.WriteLine("pid: " + pid);
double _pid = Parser.ToDouble(row["pid"]);
Console.WriteLine("pid: " + _pid);
string name = row["name"].ToString();
Console.WriteLine("name: " + name);
DateTime date = Parser.ToDateTime(row["date_"]);
Console.WriteLine("date: " + conn.User.FormatDateTime(date));
}
3.5. Indexace načtených záznamů podle primárního klíče
// using NETGenium;
// using System;
// using System.Collections.Generic;
// using System.Data;
DataTable data = Data.Get("SELECT * FROM sholiday", conn);
Dictionary<int, DataRow> dictionary = Data.DictionaryInt32(data);
int id = 1;
if (dictionary.ContainsKey(id))
{
DataRow row = dictionary[id];
Console.WriteLine(row["id"]);
}
3.6. Indexace načtených vnořených záznamů podle cizího klíče „pid“
// using NETGenium;
// using System;
// using System.Collections.Generic;
// using System.Data;
DataTable data = Data.Get("SELECT * FROM sholiday", conn);
Dictionary<int, List<DataRow>> dictionary = Data.DictionaryInt32(data, "pid", true);
int pid = 0;
if (dictionary.ContainsKey(pid))
{
List<DataRow> rows = dictionary[pid];
Console.WriteLine(rows.Count + " rows");
}
3.7. Sekvenční čtení záznamů
// using NETGenium;
// using System;
using (DbCommand cmd = new DbCommand("SELECT id, date_ FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn))
using (DbDataReader dr = cmd.ExecuteReader())
while (dr.Read())
{
Console.WriteLine(dr["id"] + ": " + dr["date_"]);
}
3.8. Sekvenční čtení záznamů do dictionary
// using NETGenium;
// using System;
// using System.Collections.Generic;
Dictionary<int, DateTime> dictionary = new Dictionary<int, DateTime>();
using (DbCommand cmd = new DbCommand("SELECT id, date_ FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn))
using (DbDataReader dr = cmd.ExecuteReader())
while (dr.Read())
{
dictionary.Add((int)dr["id"], (DateTime)dr["date_"]);
}
3.9. Sekvenční čtení záznamů do listu
// using NETGenium;
// using System;
// using System.Collections.Generic;
private class Item
{
public int ID;
public DateTime Date;
public Item(DbDataReader dr)
{
ID = (int)dr["id"];
Date = (DateTime)dr["date_"];
}
}
List<Item> items = new List<Item>();
using (DbCommand cmd = new DbCommand("SELECT id, date_ FROM sholiday WHERE date_ > " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn))
using (DbDataReader dr = cmd.ExecuteReader())
while (dr.Read())
{
items.Add(new Item(dr));
}
4. Zápis dat do databáze
4.1. INSERT INTO – vytvoření nového záznamu v databázi
4.1.1. DataSaver – vytvoření jednoho záznamu
// using NETGenium;
// using System;
DataSaver ds = new DataSaver("sholiday", 0, cmd);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Execute();
Console.WriteLine(ds.Report());
4.1.2. DataSaver – vytvoření dvou záznamů v samostatné transakci
Transakce otevřená metodou „BeginTransaction“ nad připojením platí pro všechny příkazy i čtení nad tímto připojením, takže čtení uvnitř transakce vidí i dosud nepotvrzené zápisy. Skončí-li blok „using“ bez zavolání „Commit“, typicky výjimkou, transakce se vrátí zpět. Nad připojením otevřeným přes webové služby (metodou „Open“ s adresou, přihlašovacím jménem a heslem) metoda „BeginTransaction“ chybu nehlásí, ale transakci nezaloží – každý zápis se potvrdí okamžitě a nic se nevrací zpět.
// using NETGenium;
// using System;
using (DbTransaction trans = conn.BeginTransaction())
{
DataSaver ds = new DataSaver("sholiday", 0, cmd);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Execute();
Console.WriteLine(ds.Report());
ds = new DataSaver("sholiday", 0, cmd);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year + 1, 1, 1));
ds.Execute();
Console.WriteLine(ds.Report());
trans.Commit();
}
4.1.3. DataSaver – vytvoření jednoho záznamu zkopírováním jiného záznamu
// using NETGenium;
// using System;
int id = 1;
DbRow row = new DbRow("SELECT * FROM sholiday WHERE id = " + id, conn);
if (row.Read())
{
// row["ng_zadanokym"] = conn.User.LoginName;
// row["ng_zadanokdy"] = DateTime.Now;
// row["ng_zmenenokym"] = DBNull.Value;
// row["ng_zmenenokdy"] = DBNull.Value;
DataSaver ds = new DataSaver("sholiday", 0, cmd);
ds.Add(row);
ds.Execute();
Console.WriteLine(ds.Report());
}
4.1.4. DataSaverSynchro – vytvoření jednoho záznamu včetně vytvoření záznamu historie a zajištění synchronizace záznamu
// using NETGenium;
// using System;
DataSaverSynchro ds = new DataSaverSynchro("sholiday", 0, conn);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Save(cmd);
Console.WriteLine(ds.Report());
4.1.5. DataSaverSynchro – vytvoření dvou záznamů v samostatné transakci
// using NETGenium;
// using System;
using (DbTransaction trans = conn.BeginTransaction())
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", 0, conn);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year, 1, 1));
ds.Save(cmd);
Console.WriteLine(ds.Report());
ds = new DataSaverSynchro("sholiday", 0, conn);
ds.Add("name", "Nový rok");
ds.Add("date_", new DateTime(DateTime.Today.Year + 1, 1, 1));
ds.Save(cmd);
Console.WriteLine(ds.Report());
trans.Commit();
}
Záznam se v transakci ukládá vždy metodou „Save(cmd)“ – přetížení bez příkazu „Save(user, ng_rootPath)“ by zápis provedlo ve vlastní transakci na samostatném připojení.
4.2. UPDATE – editace existujícího záznamu v databázi
4.2.1. DataSaver – editace záznamu, jehož ID je načteno z databáze
// using NETGenium;
// using System;
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaver ds = new DataSaver("sholiday", id, cmd);
ds.Add("name", "Nový rok – TEST");
ds.Execute();
Console.WriteLine(ds.Report());
}
4.2.2. DataSaver – editace záznamu, jehož ID je uloženo v proměnné; pokud záznam neexistuje, bude vytvořen
// using NETGenium;
// using System;
int id = 1;
DataSaver ds = new DataSaver("sholiday", id, true, cmd);
ds.Add("name", "Nový rok – TEST");
ds.Execute();
Console.WriteLine(ds.Report());
4.2.3. DataSaverSynchro – editace záznamu, jehož ID je načteno z databáze, včetně vytvoření záznamu historie a zajištění synchronizace záznamu
// using NETGenium;
// using System;
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, conn);
ds.Add("name", "Nový rok – TEST");
ds.Save(cmd);
Console.WriteLine(ds.Report());
}
4.2.4. DataSaverSynchro – editace záznamu, jehož ID je uloženo v proměnné, včetně vytvoření záznamu historie a zajištění synchronizace záznamu; pokud záznam neexistuje, bude vytvořen
// using NETGenium;
// using System;
int id = 1;
DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, true, conn);
ds.Add("name", "Nový rok – TEST");
ds.Save(cmd);
Console.WriteLine(ds.Report());
4.3. Synchronizace dat dvou databázových tabulek podle jednotného klíče
// using NETGenium;
// using System;
// using System.Collections.Generic;
// using System.Data;
string table1 = "ng_kniha1", table2 = "ng_kniha2", key = "ng_isbn";
DataTable data1 = Data.Get("SELECT * FROM " + table1, conn), data2 = Data.Get("SELECT * FROM " + table2, conn);
Dictionary<object, DataRow> dictionary = Data.Dictionary(data2, key);
foreach (DataRow row1 in data1.Rows)
{
DataRow row2 = Data.DataRow(dictionary, row1[key]);
if (row2 == null)
{
DataSaver ds = new DataSaver(table2, 0, cmd);
foreach (DataColumn c in data2.Columns)
if (c.ColumnName != "id" && c.ColumnName != "fulltexttimestamp" && data1.Columns.Contains(c.ColumnName))
{
ds.Add(c.ColumnName, row1[c.ColumnName]);
}
ds.Execute();
}
else
{
DataSaver ds = new DataSaver(table2, (int)row2["id"], cmd);
foreach (DataColumn c in data2.Columns)
if (c.ColumnName != "id" && c.ColumnName != "fulltexttimestamp" && data1.Columns.Contains(c.ColumnName) && row2[c].ToString() != row1[c.ColumnName].ToString())
{
ds.Add(c.ColumnName, row1[c.ColumnName]);
}
if (!ds.Empty)
{
ds.Execute();
}
}
}
5. Mazání dat z databáze
5.1. DELETE FROM – smazání záznamu z databáze
// using NETGenium;
// using System;
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok – TEST") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
cmd.CommandText = "DELETE FROM sholiday WHERE id = " + id;
cmd.ExecuteNonQuery();
}
5.2. DataSaverSynchro – smazání záznamu z databáze včetně vytvoření záznamu historie a zajištění synchronizace záznamu
// using NETGenium;
// using System;
int id = Data.ExecuteScalarInt32("SELECT id FROM sholiday WHERE name = " + conn.Format("Nový rok – TEST") + " AND date_ = " + conn.Format(new DateTime(DateTime.Today.Year, 1, 1)), conn);
if (id != 0)
{
DataSaverSynchro ds = new DataSaverSynchro("sholiday", id, conn);
ds.Delete(cmd);
}
6. Souborové přílohy
6.1. Vytvoření souborové přílohy
// using NETGenium;
// using System;
// using System.IO;
string temp = Path.GetTempFileName();
Files.Write(temp, "abc");
int file = Attachment.Add("test.txt", temp, conn);
File.Delete(temp);
Console.WriteLine(file);
6.2. Načtení obsahu souborové přílohy pomocí objektu DbConnection
// using NETGenium;
// using System;
// using System.IO;
string temp = Path.GetTempFileName();
Files.Write(temp, "abc");
int file = Attachment.Add("test.txt", temp, conn);
File.Delete(temp);
Console.WriteLine(file);
string path = Attachment.FilePath(file, conn);
if (File.Exists(path))
{
string s = File.ReadAllText(path);
Console.WriteLine(s);
}
6.3. Načtení obsahu souborové přílohy pomocí objektu NETGeniumConnection
// using NETGenium;
// using System;
// using System.IO;
string temp = Path.GetTempFileName();
Files.Write(temp, "abc");
int file = Attachment.Add("test.txt", temp, conn);
File.Delete(temp);
Console.WriteLine(file);
// Attachment
Attachment = conn.GetAttachment(id);
if (attachment != null)
{
Console.WriteLine(attachment.Name + ": " + attachment.ContentBytes.Length + " bytes");
}
// byte[]
byte[] buffer = conn.GetAttachmentAsBytes(id);
if (buffer != null)
{
Console.WriteLine(buffer.Length + " bytes");
}
// string
string s = conn.GetAttachmentAsString(id, Encoding.UTF8);
if (s != null)
{
Console.WriteLine(s);
}
7. E-maily
7.1. Odeslání e-mailové zprávy
// using NETGenium;
// using System;
// using System.Net.Mail;
string html = NETGenium.Email.Message.Container("<b>Hello</b>");
MailMessage message = new MailMessage();
message.From = new MailAddress("@");
message.To.Add(new MailAddress("@"));
message.Subject = "";
message.AlternateViews.Add(Config.CreateTextAlternateView(Html.ToText(html)));
message.AlternateViews.Add(Config.CreateHtmlAlternateView(html, conn));
Config.SendMessage(message, conn);
8. Logování
8.1. Logování na disk do adresáře „Logs“
// using NETGenium;
// using System;
// using System.IO;
try
{
throw new NullReferenceException("args");
}
catch (Exception ex)
{
L.E("MyFirstFunction", ex);
// L.LogError("MyFirstFunction", ex);
// L.Error("MyFirstFunction", ex);
L.W("MyFirstFunction", ex);
// L.LogWarning("MyFirstFunction", ex);
// L.Warning("MyFirstFunction", ex);
L.N("MyFirstFunction", ex);
// L.LogNotice("MyFirstFunction", ex);
// L.Notice("MyFirstFunction", ex);
}
- Volání s jediným textovým parametrem (zpráva, případně výjimka) zapíše záznam do denního logového souboru „Logs\yyyy-MM-dd.log“ – v ukázce výše je tedy „MyFirstFunction“ text zprávy, nikoli název souboru.
- Do samostatného logového souboru se záznam zapíše voláním, jehož prvním parametrem je prefix názvu souboru, například „L.E("MyFirstFunction", "Zpráva", ex)“. Název souboru se z prefixu sestaví takto:
- prefix neobsahuje „yyyy“ – soubor je měsíční, například „Logs\MyFirstFunction-2026-09.log“,
- prefix obsahuje „yyyy“ – text před „yyyy“ zůstane beze změny a zbytek prefixu od „yyyy“ se použije jako formát data .NET, takže prefix „PDDP-yyyy-MM-dd“ vytvoří denní soubor „Logs\PDDP-2026-09-29.log“ a prefix „PDDP-yyyy“ roční soubor „Logs\PDDP-2026.log“,
- prefixy „Errors“, „System“, „Version“ a „Warnings“ – soubor bez data, například „Logs\Errors.log“.
- Veškerý text za „yyyy“ se interpretuje jako formát data, takže písmena jako „d“, „M“, „H“, „m“, „s“ nebo „t“ se nahradí hodnotami data. Text, který má za datem zůstat beze změny, se uzavírá do apostrofů, například „PDDP-yyyy-MM-dd'-import'“.
8.2. Obecné logování na disk
// using NETGenium;
// using System;
Files.Write(Config.RootPath + "test.log", "TEST");
try
{
Files.WriteLine(Config.RootPath + "test.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + Convert.ToChar(160) + "TEST");
}
catch { }
Files.WriteLineTryCatch(Config.RootPath + "test.log", DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + Convert.ToChar(160) + "TEST");
9. Služby
9.1. Základní informace
- Konzolové aplikace je možné nainstalovat jako službu systému Windows, takže následně běží na pozadí operačního systému, a spouští se sami v pravidelných intervalech.
- Konzolové aplikace v režimu služby (dále jen „Služby“) musí mít definovaný název služby a jedinečný GUID projektu konzolové aplikace.
- Název služby se používá při instalaci služby, a pod tímto názvem je možné službu dohledat (zastavit, spustit, restartovat) v seznamu služeb operačního systému Windows nebo ve správci úloh (Task Manager).
- GUID projektu se používá pro bezpečné spuštění vždy pouze jedné instance služby tak, aby nedošlo k paralelnímu spuštění více instancí služby (při zkopírování existujícího projektu konzolové aplikace je nutné nastavit nový GUID projektu, aby tyto dvě služby mezi sebou nekolidovaly právě díky společnému GUID projektu). Ochrana platí pro každou iteraci zvlášť a spolu s GUID rozhoduje i název služby: druhá instance téže služby počká 3 sekundy, zaznamená do logu varování a svou iteraci vynechá.
- Služby používají konfigurační soubory, ze kterých si načítají nastavení připojení do databáze, adresu poštovního serveru odchozí pošty, počáteční a koncový čas technologické pauzy, během které služba nepracuje, atd.
- Služby se nepřipojují sami do databáze, a používají jednotný systém pro volání hlavního zdrojového kódu, který se vyskytuje v běžné konzolové aplikaci uvnitř metody „static void Main(string[] args)“.
- Služby nemají přístup k připojeným diskovým jednotkám, pouze k pevným nebo síťovým jednotkám. K diskům připojeným pomocí příkazu „mount“ musí být přistupováno pomocí síťové cesty, například „\\192.168.0.1\D\NETGenium“.
- Konzolová aplikace služby vyžaduje přidělení administrátorského oprávnění pomocí manifestu (viz kapitola Manifest), jinak při spuštění v konzoli a v dialogu nastavení služby (včetně instalace služby) selhávají základní operace typu zálohování, čtení nebo zápis na disk apod. Nainstalovaná služba běží pod účtem zvoleným při instalaci (výchozí je „LocalSystem“) a manifest ji neovlivní.
9.2. Vytvoření obálky služby a úprava souboru „Program.cs“
- V prvním kroku je nutné přesunout logiku konzolové aplikace umístěnou v metodě „static void Main(string[] args)“ do nového souboru „Service.cs“.
- Z tohoto zdrojového kódu je nutné odstranit vytvoření instance objektu „DbConnection“, „DbCommand“, a nastavení adresáře NET Genia.
- Minimální zdrojový kód služby zobrazuje následující příklad, namespace i název služby je pro názornost nastaven na „CRMService“:
using NETGenium;
using System;
namespace CRMService
{
public class Service : ServiceTemplate, IServiceTemplate
{
public override string ServiceName { get { return "CRMService"; } }
public Service()
{
}
protected override void HandleProcess(string[] args, Config config, DbCommand cmd, DbConnection conn)
{
DateTime now = DateTime.Now;
}
}
}
- Kromě metody „HandleProcess“ nabízí třída „ServiceTemplate“ další metody a vlastnosti, které lze v odvozené třídě přepsat nebo použít:
| Metoda nebo vlastnost | Popis |
| HandleInitialize(string[] args) | volá se jednou na začátku každé iterace, před zpracováním konfiguračních souborů |
| HandleProcess(string[] args, Config config, DbCommand cmd, DbConnection conn) | volá se v každé iteraci pro každý konfigurační soubor zvlášť, s otevřeným připojením do jeho databáze |
| HandleFinish() | volá se jednou na konci každé iterace, po zpracování všech konfiguračních souborů |
| OnStart(), OnStop(), OnCustomCommand(int command) | volají se jen u nainstalované služby, při jejím spuštění, zastavení a při přijetí vlastního příkazu služby |
| NextRunTime | čas příštího spuštění, který se zapisuje do tabulky „ng_sluzbawindows“ (viz kapitola Evidence běhu služby); lze ho v kódu služby přepsat |
| SingleInstance, SingleInstanceTimeOut | ochrana proti souběžnému běhu dvou iterací téže služby; výchozí hodnoty jsou „true“ a 3000 ms |
| ConfigDirectory | adresář, ve kterém se hledají konfigurační soubory XML |
| TempDirectory | adresář „Temp“ pro dočasné soubory; neexistuje-li, při použití se založí |
| RunScript(DbConnection conn, string buttonId, string userId, int timeout) | spustí skript tlačítka programem „RunScript.exe“ z adresáře „bin“ instalace NET Genia zadané klíčem „rootPath“ a vrátí jeho standardní výstup |
| LogServiceTask(string taskName, DateTime? nextRunTime, DbCommand cmd) | zapíše běh služby do tabulky „ng_sluzbawindows“; framework ji volá sám po každém úspěšném zpracování konfiguračního souboru, kromě služby se záporným intervalem |
- Ve druhém kroku je nutné změnit obsah souboru „Program.cs“ a nastavit interval spouštění služby.
- Konzolovou aplikaci od této chvíle nebude možné spustit běžným způsobem pomocí příkazu „Debug“ / „Start Debugging“ (F5), proto je důležité tento krok naplánovat až na chvíli, kdy bude konzolová aplikace vyladěná a stabilní.
using NETGenium;
namespace CRMService
{
class Program
{
static void Main(string[] args)
{
if (false)
{
new Service().Run(args);
return;
}
new Service().Process(args,
new ServiceTemplateInstaller.InstallOptions()
{
Interval = 5
});
}
}
}
- Interval spouštění nainstalované služby se zadává v minutách vlastností „Interval“ objektu „InstallOptions“ a smí být i desetinné číslo:
- kladná hodnota – iterace se spouštějí pravidelně po zadaném počtu minut; odpočet běží od začátku první iterace, nezávisle na tom, jak dlouho jednotlivé iterace trvají,
- 0 (výchozí hodnota) – služba se spouští jednou denně v 08:00; první pravidelná iterace proběhne v nejbližších 08:00 a další vždy po 24 hodinách,
- záporná hodnota – proběhne jen jediná iterace po spuštění služby a další se už nespouštějí.
- První iterace proběhne vždy 15 sekund po spuštění služby, bez ohledu na nastavený interval.
- Iterace se nepřekrývají: připadne-li čas další iterace na dobu, kdy předchozí iterace ještě běží, tato další iterace se vynechá a do logu se zapíše varování „Previous OnTimer() is still running“.
- Kdykoliv v budoucnu je možné konzolovou aplikaci upravit zpětně tak, aby se dala spustit běžným způsobem pomocí příkazu „Debug“ / „Start Debugging“ (F5), a bylo možné další ladění nebo zkoušení konzolové aplikace.
using NETGenium;
namespace CRMService
{
class Program
{
static void Main(string[] args)
{
if (true)
{
new Service().Run(args);
return;
}
new Service().Process(args,
new ServiceTemplateInstaller.InstallOptions()
{
Interval = 5
});
}
}
}
9.3. Manifest
- Ve třetím kroku je nutné přidělit konzolové aplikaci administrátorské oprávnění pomocí souboru manifestu:
- Spustit Visual Studio a otevřít projekt konzolové aplikace
- Kliknout pravým tlačítkem na název projektu v Solution Exploreru, zvolit „Add / New Item...“, do pole pro vyhledávání napsat „manifest“, najít položku „Application Manifest File“, a zvolit „Add“
- V obsahu souboru manifestu najít „<requestedExecutionLevel level="asInvoker" uiAccess="false" />“ a změnit na „<requestedExecutionLevel level="requireAdministrator" uiAccess="false" />“
9.4. Příklad služby CRMService
- Následující příklad demonstruje jednoduchou službu „CRMService“, která stahuje obsah technologické stránky, příchozí e-maily zálohuje do adresáře „POP3Downloads“, a do okna konzolové aplikace a na disk do adresáře „Logs“ vypisuje detaily e-mailu.
- Obsah souboru „Service.cs“:
using NETGenium;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
namespace CRMService
{
public class Service : ServiceTemplate, IServiceTemplate
{
public override string ServiceName { get { return "CRMService"; } }
private string dir, backupdir;
public Service()
{
AddRequiredConfigKey("pop3Email");
AddRequiredConfigKey("pop3Url");
AddRequiredConfigKey("pop3Name");
AddRequiredConfigKey("pop3Password");
Directory.CreateDirectory(dir = Config.RootPath + "Temp\\");
Directory.CreateDirectory(backupdir = Config.RootPath + "POP3Downloads\\");
}
protected override void HandleProcess(string[] args, Config config, DbCommand cmd, DbConnection conn)
{
DateTime now = DateTime.Now;
Files.DeleteDirectoriesYYYYMMDD(backupdir, now.AddMonths(-6));
Files.DeleteLogs(Config.RootPath, now.AddYears(-1));
try
{
using (var pop3 = new NETGenium.Email.Pop3(0, config["pop3Url"], config["pop3Name"], config["pop3Password"]))
{
pop3.Open();
for (int index = 0; index < pop3.Count; index++)
{
foreach (string file in Directory.GetFiles(dir))
{
File.Delete(file);
}
string backupdir2 = backupdir + now.ToString("yyyy-MM-dd") + "\\";
Directory.CreateDirectory(backupdir2);
string eml = backupdir2 + Guid.NewGuid().ToString().ToUpper() + ".eml";
var message = pop3.ReadMessage_SaveEmlAndAttachments(index, eml, dir);
Email.Eval(config, message, eml, true, "ID " + index, dir, ServiceName, now, cmd, conn);
// pop3.DeleteMessage(index); // Mazání zpráv z POP3 serveru až po odladění služby
if (index == 499)
{
break;
}
}
}
}
catch (Exception ex)
{
L.EW("Download e-mails from POP3", ex);
}
}
}
}
- Logika zpracování příchozí e-mailové zprávy je řešena v samostatném souboru „Email.cs“.
- Obsah souboru „Email.cs“:
using NETGenium;
using NETGenium.Email;
using System;
using System.IO;
namespace CRMService
{
internal class Email
{
public static bool Eval(Config config, Message message, string eml, bool pop3message, string name, string dir, string serviceName, DateTime now, DbCommand cmd, DbConnection conn)
{
L.N(name);
foreach (string file in Directory.GetFiles(dir))
{
L.N(Path.GetFileName(file));
}
L.N(message.DateOriginal.ToString());
L.N(message.From.EmailAddress);
L.N(message.To);
L.N(message.Subject);
L.N(message.Text);
return true;
}
}
}
- Místo třídy „Pop3“ lze poštu stahovat i protokolem IMAP třídou „NETGenium.Email.Imap“, která má stejný konstruktor i metody pro čtení a mazání zpráv. Adresa serveru se zadává stejně, výchozí port je 143 a zabezpečené spojení SSL se použije jen na portu 993 (například „imap.firma.cz:993“). Zprávy se čtou jen ze složky „INBOX“. Zpráva smazaná metodou „DeleteMessage“ se ze schránky odstraní až při uzavření spojení metodou „Close“, takže pořadí ostatních zpráv se do té doby nemění. Metoda „Open“ navíc hned po otevření schránky trvale odstraní všechny zprávy označené jako smazané – i ty, které takto označil jiný poštovní klient –, takže zpráva, jejíž spojení neskončilo voláním „Close“, se odstraní nejpozději při příštím otevření. Nedovolí-li server zprávy ze schránky odstraňovat, zůstanou v ní a metoda „Close“ zapíše do logu varování.
- Obě třídy umožňují přihlášení přes OAuth 2.0: přístupový token se místo hesla vyplní do vlastnosti „OAuth_access_token“ před voláním metody „Open“.
- Přílohy zabalené v příloze „winmail.dat“ (formát TNEF) rozbalí do zadaného adresáře metoda „Parse“ třídy „NETGenium.Email.TnefMessage“. Přílohy podepsané zprávy z přílohy „smime.p7m“ rozbalí stejně třída „NETGenium.Email.SmimeMessage“, jejíž vlastnost „Message“ navíc nese podepsanou zprávu včetně textu; zašifrovanou zprávu třída nepřečte.
- Zprávu, jejíž zpracování opakovaně selhává, pomáhá vyřadit třída „NETGenium.Email.FailedMessages“; její instance musí přetrvat mezi iteracemi služby. Metoda „Discard“ počítá neúspěšné pokusy o zpracování zprávy: dokud jich není tolik, kolik udává vlastnost „MaxAttempts“ (výchozí hodnota 3), zapíše do logu varování a vrátí „false“; při posledním pokusu zapíše do logu chybu, uloží kopii souboru „.eml“ do adresáře zadaného v konstruktoru a vrátí „true“ – zprávu je pak nutné smazat ze schránky. Zprávu, jejíž soubor „.eml“ neexistuje nebo jejíž kopii se nepodaří uložit, nevyřadí nikdy.
- Pozvánku do kalendáře ve formátu iCalendar zpřístupňují vlastnosti třídy „Message“ začínající slovem „Calendar“, například „CalendarSummary“, „CalendarStart“, „CalendarEnd“ nebo „CalendarAppointments“ s jednotlivými výskyty opakované události (nejvýše 1000).
9.5. Konfigurační soubory služby
- Služby mohou obsahovat dva druhy konfiguračních souborů:
- Hlavní konfigurační soubor (například „CRMService.exe.config“), jehož název musí vycházet z názvu aplikace (v tomto případě „CRMService.exe“). Zpracuje se jen tehdy, obsahuje-li klíč „connectionString“ nebo „rootPath“.
- Konfigurační soubory XML, které se používají v případech, kdy služba obsluhuje více databází najednou (například „netgenium1.xml“, „netgenium2.xml“, apod.). Zpracuje se každý soubor s příponou „xml“. Soubor „shared.xml“ nebo „globalconfiguration.xml“ se samostatně nezpracuje – jeho klíče se doplní do všech ostatních konfiguračních souborů včetně hlavního konfiguračního souboru, pokud je nemají. Sdílený soubor smí být jen jeden: jsou-li v adresáři oba, použije se jako sdílený jen jeden z nich a druhý se zpracuje jako běžný konfigurační soubor.
- Zdrojový kód služby se spouští pro každý konfigurační soubor zvlášť. Mezi přípustné kombinace patří:
- CRMService.exe.config
- netgenium1.xml, netgenium2.xml, ...
- CRMService.exe.config, netgenium1.xml, netgenium2.xml, ...
- Konfigurační soubory musí být umístěné ve stejném adresáři jako „CRMService.exe“. Výjimkou jsou konfigurační soubory XML služby spuštěné odkudkoli z podadresáře „bin“ (typicky „bin\Debug“ při ladění ve Visual Studiu) – ty se hledají v adresáři, který „bin“ obsahuje, tedy v adresáři projektu. Pokud jsme ve fázi ladění služby ve Visual Studiu, není nutné vytvářet konfigurační soubor ručně, protože každý projekt konzolové aplikace automaticky obsahuje výchozí konfigurační soubor „App.config“. Tento soubor se při každé kompilaci projektu sám překopíruje do adresáře „Debug“ nebo „Release“ (podle zvoleného režimu kompilace) do souboru s názvem „abc.exe.config“. V našem případě se tedy obsah konfiguračního souboru „App.config“ při kompilaci projektu sám zkopíruje do souboru „CRMService.exe.config“.
- Příklad konfiguračního souboru:
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<appSettings>
<add key="rootPath" value="C:\inetpub\wwwroot\netgenium" />
<add key="stopFrom" value="00:00" />
<add key="stopTo" value="06:00" />
<add key="smtpServer" value="localhost" />
<add key="errorFrom" value="crmservice@firma.cz" />
<add key="errorTo" value="support@firma.cz" />
<add key="pop3Url" value="pop3.firma.cz" />
<add key="pop3Email" value="crm@firma.cz" />
<add key="pop3Name" value="crm@firma.cz" />
<add key="pop3Password" value="pop3heslo" />
</appSettings>
</configuration>
- rootPath – absolutní cesta na disku k adresáři NET Genia; klíč je povinný ve všech režimech, pokud konfigurační soubor neobsahuje klíč „connectionString“
- connectionString – volitelný připojovací řetězec do databáze; není-li uveden, převezme se ze souboru „Config\ConnectionString.txt“ v adresáři NET Genia zadaném klíčem „rootPath“. Konfigurační soubor bez klíčů „rootPath“ i „connectionString“ se přeskočí a do logu se zapíše varování.
- stopFrom – počáteční čas technologické pauzy ve formátu „HH:mm“, během které služba nepracuje; pauza může přesahovat půlnoc (například 22:00–06:00)
- stopTo – koncový čas technologické pauzy ve formátu „HH:mm“, během které služba nepracuje
- Klíče „stopFrom“ a „stopTo“ jsou v režimu služby povinné, a to i při spuštění metodou „Run“; konfigurační soubor bez nich se přeskočí a do logu se zapíše varování. V konzolovém režimu (spuštění s argumentem „console“, viz kapitola Instalace služby) povinné nejsou; jsou-li ale v konfiguračním souboru uvedené oba, technologická pauza platí i tam.
- smtpServer – adresa poštovního serveru odchozí pošty, případně s číslem portu ve tvaru „název serveru:číslo portu“
- errorFrom – e-mailová adresa, ze které jsou zasílány notifikace o případných chybách ve službě
- errorTo – e-mailová adresa, na kterou jsou zasílány notifikace o případných chybách ve službě; není-li vyplněná, chodí notifikace podpoře NetGenia. Notifikace se odesílají jen při vyplněných klíčích „smtpServer“ a „errorFrom“ a jen u chyb, nikdy u varování. Výjimku z metody „HandleProcess“ zapíše framework do logu jako chybu jen tehdy, nejde-li o přechodnou chybu infrastruktury (síť, databáze, disk), odmítnuté přihlášení k poštovnímu serveru POP3 nebo IMAP a některé chyby při čtení zprávy z něj – tu zapíše jako varování, takže e-mail nevyvolá. U ostatních chyb odejde e-mail při prvním výskytu hned a stejná chyba se pak posílá nejvýše jednou za hodinu. Přechodná chyba, kterou kód služby zapíše do logu přímo jako chybu, e-mail při prvním výskytu nevyvolá; e-mail odejde až tehdy, opakuje-li se stejná chyba v rozmezí 1 až 24 hodin od prvního výskytu (resp. od posledního odeslaného e-mailu).
- pop3Url – adresa poštovního serveru příchozí pošty, případně s číslem portu ve tvaru „název serveru:číslo portu“ (výchozí port je 110); zabezpečené spojení SSL se použije jen na portu 995 (například „pop3.firma.cz:995“), na jiném portu se služba připojí bez SSL
- pop3Email – e-mailová adresa technologické schránky
- pop3Name – přihlašovací jméno k technologické schránce
- pop3Password – heslo k technologické schránce
- Hodnoty klíčů, jejichž název obsahuje slovo „password“, se při načtení konfiguračního souboru samy dešifrují, takže je kód služby čte už v otevřené podobě. Hodnotu zapsanou v otevřené podobě (jako „pop3heslo“ v příkladu výše) služba při načtení konfiguračního souboru přepíše v souboru zašifrovanou hodnotou; konfigurační soubor proto musí být pro účet, pod kterým služba běží, zapisovatelný, jinak heslo zůstane v souboru v otevřené podobě. Totéž platí pro klíč, jehož název je uvedený jako hodnota klíče „encrypt“ zapsaného v souboru před ním; každý klíč „encrypt“ určuje jediný klíč.
- Kromě uvedených klíčů čte framework z konfiguračního souboru i tyto volitelné klíče:
- logLevel – úrovně záznamů, které se zapisují do logu, oddělené středníkem nebo čárkou (VERBOSE, NOTICE, WARNING, ERROR, FATAL, nebo ALL pro všechny); bez klíče se zapisují všechny úrovně
- logDir – adresář logu služby; bez klíče se log zapisuje do podadresáře „Logs“ adresáře, ve kterém leží program služby, a leží-li program kdekoli pod adresářem „bin“, do podadresáře „Logs“ adresáře, který „bin“ obsahuje
- proxy, proxyUser, proxyPassword – proxy server pro odchozí HTTP požadavky služby a přihlašovací údaje k němu; prázdná hodnota klíče „proxy“ proxy server vypne
- logServiceConnectionString – připojovací řetězec databáze, do jejíž tabulky „ng_sluzbawindows“ se zapisuje evidence běhu služby (viz kapitola Evidence běhu služby)
- errorCc – e-mailová adresa příjemce kopie notifikací o chybách ve službě
- smtpUserName, smtpPassword – přihlašovací údaje k poštovnímu serveru odchozí pošty
- smtpSsl – zabezpečené spojení s poštovním serverem odchozí pošty; uplatní se jen při vyplněných klíčích „smtpUserName“ a „smtpPassword“
- headerLabel – text, který se vloží na začátek předmětu e-mailů odesílaných podle konfigurace služby
- defaultSenderEmail – e-mailová adresa, z jejíž domény se sestaví hlavička „Message-Id“ e-mailů odesílaných podle konfigurace služby
- Klíče „logLevel“, „logDir“ a „proxy“ platí jen pro konfigurační soubor, ve kterém jsou uvedené; před zpracováním každého dalšího konfiguračního souboru a po zpracování posledního z nich se nastavení vrátí na hodnoty platné po dokončení metody „HandleInitialize“.
9.6. Instalace služby
- K instalaci služby se používá zástupce „nazev-sluzby - user.lnk“, který vznikne automaticky v adresáři programu při spuštění konzolové aplikace „nazev-sluzby.exe“ metodou „Process“. Současně vznikne zástupce „nazev-sluzby - console.lnk“, který spustí jednu iteraci služby v konzolovém režimu.
- Po spuštění zástupce „nazev-sluzby - user.lnk“ je důležité zkontrolovat nastavení účtu, pod kterým se má služba spouštět. Výchozí nastavení je „LocalSystem“, což zajišťuje bezpečné spouštění služby bez budoucích možných komplikací s oprávněním služby.
- Instalace služby se provádí kliknutím na tlačítko „Install“.

- Odinstalace služby se provádí kliknutím na tlačítko „Uninstall“.
- Režim spuštění konzolové aplikace služby (metoda „Process“) určuje první argument příkazové řádky; na velikosti písmen nezáleží a jiný argument skončí chybou:
| Argument | Režim |
| bez argumentu | běh nainstalované služby – takto ji spouští správce služeb systému Windows |
| user | dialog nastavení služby (zástupce „nazev-sluzby - user.lnk“) |
| console | jedna iterace v konzolovém režimu (zástupce „nazev-sluzby - console.lnk“) |
| install, register | instalace služby bez dialogu a její spuštění; účet a režim spuštění se převezmou z vlastností „Account“, „Username“, „Password“ a „ServiceMode“ objektu „InstallOptions“ v souboru „Program.cs“; je-li služba už nainstalovaná, nic se nestane |
| uninstall, unregister | odinstalace služby bez dialogu |
9.7. Výměna programových souborů služby
- Jakmile je služba jednou nainstalována, není možné měnit programové soubory služby, protože jsou neustále chráněny operačním systémem.
- Před výměnou programových souborů je nutné službu zastavit pomocí tlačítka „Stop“, a dialog nastavení služby zavřít pomocí ikony křížku.
- Následně je možné programové soubory služby přepsat, a službu znovu spustit pomocí tlačítka „Start“.
9.8. Evidence běhu služby
- Obsahuje-li databáze formulář s tabulkou „ng_sluzbawindows“, zapíše do ní služba po každém úspěšném zpracování konfiguračního souboru čas posledního a čas příštího spuštění. Přehled služeb mimo provoz a upozornění na ně zajišťuje aplikace postavená nad touto tabulkou.
- Zápis proběhne jen tehdy, doběhne-li metoda „HandleProcess“ bez výjimky. Neprovede se v době technologické pauzy („stopFrom“ až „stopTo“), při chybné nebo neúplné konfiguraci, při nedostupné databázi ani při existenci souboru „Config\UnderConstruction.txt“ v adresáři NET Genia zadaném klíčem „rootPath“.
- Řádek tabulky se jmenuje podle názvu služby („ServiceName“). Je-li mezi konfiguračními soubory sdílený soubor „shared.xml“ nebo „globalconfiguration.xml“, dostane každý konfigurační soubor XML vlastní řádek ve tvaru „název služby (název souboru bez přípony)“; jinak zapisují všechny konfigurační soubory, jejichž evidence míří do téže databáze, do jednoho řádku.
- Čas příštího spuštění je u nainstalované služby s kladným intervalem čas začátku iterace zvýšený o interval. Služba se záporným intervalem čas posledního ani příštího spuštění nezapisuje. Ve všech ostatních případech – interval 0, přímé volání metody „Run“ (například z naplánované úlohy Windows) a spuštění mimo režim služby – je to čas začátku iterace zvýšený o 1 den. Připadne-li vypočtený čas do technologické pauzy, posune se na její konec. Čas se zapisuje v časovém pásmu NET Genia.
- Klíč „logServiceConnectionString“ přesměruje zápis do jiné databáze, než se kterou služba pracuje; chyba při zápisu do této databáze se nikam nezapisuje.
- Programy, které nejsou postavené na třídě „ServiceTemplate“ (například dávkové soubory spouštěné naplánovanou úlohou Windows), se do téže tabulky zapisují programem „LogService.exe“ – viz příručka Utility.