Connect with us

Entwicklung & Code

Android 17: „Continue on“-Funktion bringt nahtlose App-Übergabe zwischen Geräten


Google hat seine „Continue On“-Funktion im Rahmen der I/O-Session „What’s new in Android“ angekündigt und sie auf der Entwicklerseite näher erläutert. Sie ist Teil von Android 17 und soll Nutzerinnen und Nutzer ermöglichen, eine App auf einem Android-Gerät zu starten und dann auf ein anderes Gerät in ihrem Android-Ökosystem zu wechseln, um die begonnene Aufgabe fortzusetzen.

Weiterlesen nach der Anzeige

Wie der Entwickler auf seiner Developer-Webseite erläutert, ist „Continue On“ für den bidirektionalen Einsatz konzipiert. Das heißt, dass jedes unterstützte Android-Gerät sowohl App-Aktivitäten senden als auch empfangen kann, dabei müssen die Geräte jeweils mit dem gleichen Google-Konto verknüpft sein.

Mit dem Release von Android 17, der im Laufe der kommenden Wochen erwartet wird, soll „Continue On“ zunächst den Übergang von Smartphones zu Tablets unterstützen. Dabei werde in der Taskleiste des Tablets ein Vorschlag für die zuletzt auf dem Smartphone geöffnete App angezeigt. Über diesen können Nutzer die App mit einem Fingertipp starten und dort weitermachen, wo er oder sie aufgehört habe.


Android 17 Continue-on-Funktion: App-Übergabe zwischen Smartphone und Tablet

Android 17 Continue-on-Funktion: App-Übergabe zwischen Smartphone und Tablet

Continue-on-Funktion: App-Übergabe zwischen Smartphone und Tablet.

(Bild: Google)

Als Beispiel nennt Google etwa die Möglichkeit, dasselbe Dokument in Google Docs, das man zuerst auf dem Smartphone genutzt hat, auf dem Tablet zu öffnen und daran weiterzuarbeiten. Ein weiteres Beispiel zeigt, dass die Übergabe auch mit einem Webbrowser funktioniert: Eine E-Mail in Gmail wird an Chrome auf einem Tablet weitergeleitet, wo sie direkt geöffnet wird.


Continue-on-Funktion: App-Übergabe zwischen Smartphone und Tablet per Browser

Continue-on-Funktion: App-Übergabe zwischen Smartphone und Tablet per Browser

Continue-on von Gmail-App auf dem Smartphone in den Chrome-Browser auf dem Tablet.

(Bild: Google)

Trotz der anfänglichen Einschränkungen ähnelt der Ansatz stark Apples „Handoff“-Funktion, mit der iPhone-Nutzer Aufgaben nahtlos auf das iPad oder den Mac übertragen können. Apple hatte dieses Feature schon 2014, also vor über 10 Jahren, eingeführt. Im Hinblick auf Googles baldigen Marktstart der im Zuge der Android Show: I/O Edition angekündigten Googlebooks auf Android-Basis, dürfte die Funktion auch auf dieser neuen Gerätegattung landen, um das Ökosystem zu stärken.

Weiterlesen nach der Anzeige

Erste Informationen zur Handoff-Funktion veröffentlichte Google schon im Februar dieses Jahres in der Dokumentation zu Android 17 im Punkt „Funktionen und APIs“.

Damals erklärte Google, dass die Handoff-Funktion im Hintergrund auf dem Gerät eines Nutzers ausgeführt wird. Das Unternehmen schreibt in der Dokumentation: „Die Handoff-Unterstützung wird auf Basis einzelner Aktivitäten implementiert.“ Um Handoff zu aktivieren, müssen Entwickler die Methode setHandoffEnabled() für die Aktivität aufrufen. „Möglicherweise müssen zusätzliche Daten zusammen mit der Übergabe übermittelt werden, damit die neu erstellte Aktivität auf dem empfangenden Gerät den entsprechenden Status wiederherstellen kann. Implementieren Sie den Rückruf onHandoffActivityRequested(), um ein HandoffActivityData-Objekt zurückzugeben, das Details enthält, die angeben, wie Handoff die Aktivität auf dem empfangenden Gerät verarbeiten und neu erstellen soll.“

Lesen Sie auch


(afl)



Source link

Entwicklung & Code

LMDB 1.0: Datenbank ohne Server und ohne Write-Ahead-Log


Die freie Embedded-Datenbank LMDB (Lightning Memory-Mapped Database) hat Version 1.0 erreicht. Mit dem ersten Major-Release dokumentieren die Entwickler die API und das Verhalten der Bibliothek neu und stellen eine aktualisierte Dokumentation bereit. Für bestehende Anwendungen gibt es einen eigenen Migrationsleitfaden von der 0.9-Serie.

Weiterlesen nach der Anzeige

LMDB ist eine in Anwendungen eingebettete Key/Value-Datenbankbibliothek für lokale Datenhaltung. Sie richtet sich an Entwickler, die eine transaktionssichere Datenbank ohne separaten Serverprozess benötigen, etwa für Verzeichnisdienste, Caches oder Metadaten. Anders als klassische Datenbanksysteme lädt LMDB Daten nicht in einen eigenen Puffer-Cache, sondern bildet die komplette Datenbank per Memory Mapping in den virtuellen Adressraum des Prozesses ab. Lesezugriffe erfolgen dadurch direkt auf die gemappten Speicherbereiche, ohne zusätzliche Speicherallokationen oder Kopieroperationen.

Das Grundprinzip von LMDB bleibt auch mit Version 1.0 unverändert. Die Bibliothek verwendet einen B-Baum als Datenstruktur und überlässt das Caching vollständig dem Betriebssystem. Da Datensätze direkt aus dem Speicherabbild gelesen werden, entfallen Zwischenschritte wie malloc() oder memcpy() beim Auslesen von Daten. Das reduziert den Verwaltungsaufwand und kann insbesondere bei leseintensiven Workloads die Leistung steigern. Grundlage dafür ist die Memory-Mapping-Funktion des Betriebssystems, bei der Dateiinhalte transparent in den virtuellen Speicher eingeblendet werden.

Auch das Transaktionsmodell bleibt erhalten. LMDB bietet ACID-Eigenschaften und setzt auf Multi-Version Concurrency Control (MVCC). Neue Daten werden per Copy-on-Write geschrieben, sodass bereits vorhandene Seiten niemals überschrieben werden. Ein Leser sieht dadurch stets einen konsistenten Datenbestand, während Schreibvorgänge parallel vorbereitet werden können. Ein typisches Beispiel ist ein Dienst, der kontinuierlich Konfigurationsdaten ausliest, während ein Verwaltungswerkzeug Änderungen schreibt: Leser arbeiten ohne Sperren weiter und werden durch den Schreibvorgang nicht blockiert.

Das Nebenläufigkeitsmodell von LMDB unterscheidet sich von vielen anderen Datenbanken. Beliebig viele Prozesse oder Threads können gleichzeitig lesen, Schreibtransaktionen werden dagegen vollständig serialisiert. Zu jedem Zeitpunkt darf nur eine Schreibtransaktion aktiv sein. Dadurch schließt das System Deadlocks zwischen konkurrierenden Schreibern aus. Leser blockieren Schreiber nicht, ebenso wenig müssen Leser auf laufende Schreibvorgänge warten.

Die Entwickler verzichten außerdem bewusst auf ein Write-Ahead-Log oder ein Append-only-Protokoll. Statt regelmäßig Logdateien zusammenzuführen oder Datenbanken zu komprimieren, verwaltet LMDB freie Seiten innerhalb der Datenbank selbst und verwendet sie für spätere Schreibvorgänge erneut. Dadurch wächst die Datenbank im Normalbetrieb nicht unbegrenzt an, wie es bei logbasierten Verfahren ohne Wartung passieren kann.

Weiterlesen nach der Anzeige

Die Release-Notes auf GitHub sowie die Dokumentation weisen auf einige Einschränkungen hin: Lange laufende Lesetransaktionen können verhindern, dass bereits freigegebene Seiten wiederverwendet werden. Dadurch kann die Datenbankdatei unnötig anwachsen. Entwickler sollten deshalb lang andauernde Transaktionen vermeiden und abgebrochene Prozesse regelmäßig auf verwaiste Reader-Einträge prüfen. Dafür stehen unter anderem die Funktion mdb_reader_check sowie das Werkzeug mdb_stat zur Verfügung.

Nicht empfohlen wird außerdem der Einsatz auf Netzwerkdateisystemen. Da LMDB auf Memory Mapping sowie Dateisperren des Betriebssystems setzt, können dort Synchronisationsprobleme auftreten. Auch das gleichzeitige mehrfache Öffnen derselben Datenbank innerhalb eines Prozesses gilt laut Dokumentation als problematisch.


(fo)



Source link

Weiterlesen

Entwicklung & Code

MongoDB integriert Vektorsuche direkt in die Datenbank


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

MongoDB stellt seine Volltextsuche und Vektorsuche nun allgemein für selbst verwaltete Installationen bereit. Die Funktionen sind sowohl für MongoDB Enterprise Advanced als auch für die Community Edition verfügbar. Entwickler können damit Suchabfragen, semantische Suche und hybride Suchverfahren direkt in ihrer Datenbank nutzen, ohne eine separate Suchplattform mit eigener Datensynchronisation betreiben zu müssen.

Weiterlesen nach der Anzeige

MongoDB ist eine dokumentenorientierte NoSQL-Datenbank, die JSON-ähnliche BSON-Dokumente speichert. Sie wird häufig für Anwendungen mit flexiblen Datenmodellen eingesetzt und ist sowohl als Cloud-Dienst MongoDB Atlas als auch für den Eigenbetrieb erhältlich. Bislang standen einige der erweiterten Suchfunktionen vor allem in Atlas zur Verfügung.

Laut der Ankündigung erreichen die Suchfunktionen in selbst verwalteten Umgebungen nun Funktionsparität mit MongoDB Atlas. Unterstützt werden unter anderem die Aggregationsstufen $search, $searchMeta, $vectorSearch, $rankFusion und $scoreFusion. Dadurch lassen sich klassische Volltextsuche und semantische Vektorsuche in einer gemeinsamen Abfrage kombinieren.

Während die Volltextsuche Dokumente anhand von Schlüsselwörtern und sprachabhängigen Merkmalen durchsucht, vergleicht die Vektorsuche numerische Repräsentationen von Inhalten, sogenannte Embeddings. Dadurch lassen sich auch inhaltlich ähnliche Dokumente finden, selbst wenn sie andere Begriffe verwenden. Eine hybride Suche verbindet beide Verfahren und kann so sowohl exakte Treffer als auch semantisch passende Ergebnisse liefern. Solche Ansätze kommen unter anderem in RAG-Systemen (Retrieval-Augmented Generation) zum Einsatz, bei denen Sprachmodelle externe Wissensquellen in ihre Antworten einbeziehen.

MongoDB integriert außerdem eine automatische Erzeugung von Embeddings auf Basis der Modelle von Voyage AI. Entwickler müssen die Vektoren damit nicht mehr selbst außerhalb der Datenbank erzeugen und synchronisieren. Laut MongoDB erfolgt die automatische Embedding-Erstellung derzeit über einen von MongoDB gehosteten Dienst von Voyage AI. Zusätzlich stehen sogenannte Reranker zur Verfügung, die Suchergebnisse nachträglich neu bewerten und in eine relevantere Reihenfolge bringen sollen.

Der Anbieter sieht die Neuerungen vor allem als Baustein für KI-Anwendungen wie Chatbots, Empfehlungssysteme oder KI-Agenten. Statt Daten zwischen Datenbank, Suchmaschine und Vektor-Datenbank zu replizieren, sollen sich Such- und KI-Workloads innerhalb derselben Plattform umsetzen lassen. Die Suchtechnologie basiert dabei auf Apache Lucene.

Weiterlesen nach der Anzeige

In der Community Edition stehen Such- und Vektorsuche ab MongoDB 8.2 ohne zusätzliche Lizenzkosten unter der Server Side Public License (SSPL) zur Verfügung. Die Funktionen laufen in einem separaten Prozess namens mongot, der parallel zum eigentlichen Datenbankprozess mongod betrieben wird. MongoDB hat den Quellcode von mongot nach eigenen Angaben ebenfalls unter der SSPL veröffentlicht.

Für Enterprise-Kunden werden die Suchfunktionen als kostenpflichtige Erweiterung von MongoDB Enterprise Advanced angeboten. Für Kubernetes-basierte Installationen erfolgt die Bereitstellung über MongoDB Controllers for Kubernetes (MCK), sodass sich Such- und Vektorsuche in Kubernetes-basierte On-Premises-, Private-Cloud- oder Hybrid-Cloud-Umgebungen integrieren lassen. Nach Angaben des Herstellers richtet sich das Angebot insbesondere an Unternehmen mit regulatorischen Anforderungen oder isolierten Infrastrukturen, die KI-Anwendungen vollständig unter eigener Kontrolle betreiben möchten.


(fo)



Source link

Weiterlesen

Entwicklung & Code

Neu in .NET 10.0 [30]: Algorithmen für die Post-Quanten-Kryptografie


close notice

This article is also available in
English.

It was translated with technical assistance and editorially reviewed before publication.

.NET 10.0 enthält drei neue asymmetrische Kryptografie-Algorithmen: ML-KEM (FIPS 203), ML-DSA (FIPS 204) und SLH-DSA (FIPS 205), die im August 2024 die US-amerikanischen Bundesbehörde National Institute of Standards and Technology (NIST) verabschiedet hat.

Weiterlesen nach der Anzeige


Der Dotnet-Doktor – Holger Schwichtenberg

Der Dotnet-Doktor – Holger Schwichtenberg

Dr. Holger Schwichtenberg ist technischer Leiter des Expertennetzwerks www.IT-Visions.de, das mit 53 renommierten Experten zahlreiche mittlere und große Unternehmen durch Beratungen und Schulungen sowie bei der Softwareentwicklung unterstützt. Durch seine Auftritte auf zahlreichen nationalen und internationalen Fachkonferenzen sowie mehr als 90 Fachbücher und mehr als 1500 Fachartikel gehört Holger Schwichtenberg zu den bekanntesten Experten für .NET und Webtechniken in Deutschland.

Federal Information Processing Standards (FIPS) sind offizielle technische Standards des NIST:

FIPS Algorithmus Zweck .NET-10.0-Klasse
203 ML‑KEM (CRYSTALS‑Kyber) Schlüsselaustausch für AES u.a. System.Security.Cryptography.MLKem
204 ML‑DSA (CRYSTALS‑Dilithium) Digitale Signatur zur Authentifizierung und Datenintegrität System.Security.Cryptography.MLDsa
205 SLH‑DSA (SPHINCS+) Digitale Signatur (Alternative Signaturen, falls später bei ML‑DSA Schwächen entdeckt werden.) System.Security.Cryptography.SlhDsa
206 FN‑DSA (FALCON) Digitale Signatur (geplantes weiteres optionales Signaturverfahren) keine

Diese Kryptografie-Algorithmen gehören zur Klasse Post-Quanten-Kryptografie (Post-Quantum Cryptography, PQC). Das sind neuere kryptografische Verfahren, die selbst dann sicher bleiben sollen, wenn leistungsstarke Quantencomputer verfügbar sind. Heute etablierte Algorithmen wie RSA und ECC basieren auf mathematischen Problemen, die Quantencomputer recht schnell lösen können. PQC-Algorithmen sollen auch mit Quantencomputern nicht schnell angreifbar sein.


betterCode() .NET 11.0

betterCode() .NET 11.0

(Bild: King / stock.adobe.com)

Das ist neu in .NET 11.0: Dr. Holger Schwichtenberg und weitere Experten präsentieren am 17. November 2026 auf der Online-Konferenz betterCode() .NET 11.0 die Änderungen für Entwicklerinnen und Entwickler. Das Programm steht jetzt fest, Tickets zum Frühbucherpreis sind verfügbar.

Die neuen Klassen findet man im .NET-Namensraum System.Security.Cryptography:

  • System.Security.Cryptography.MLKem
  • System.Security.Cryptography.MLDsa
  • System.Security.Cryptography.SlhDsa

Weiterlesen nach der Anzeige

Microsoft will aber FIPS 206 nicht implementieren: „We do not believe there is a need for any FIPS 206 algorithms in .NET workloads, they are planned as ’never’ until evidence suggests otherwise.“

Windows liefert diese Algorithmen in der Cryptography Next Generation API (CNG) seit Windows Insiders, Canary Channel Build 27852 oder höher mit. Eine stabile Version gibt es seit Windows 11 25H2 und Windows Server 2025. Für macOS- und Linux-Systeme braucht man die OpenSSL-Bibliothek ab Version 3.5. Folgender Code zeigt einige Beispiele für PQC:


using System.Security.Cryptography;	
 
namespace NET10_Console;
 
public class FCL10_PQC
{
 public void GetSupportedStandards()
 {
 
  CUI.Demo("Post-Quantum Cryptography (PQC) in .NET 10.0");
 
  CUI.H2("Prüfung, ob die PQC-Algorithmen verfügbar sind");
  Console.WriteLine("ML-KEM (FIPS 203) für Verschlüsselung: " + System.Security.Cryptography.MLKem.IsSupported);
  Console.WriteLine("ML-DSA (FIPS 204) für Digitale Signaturen: " + System.Security.Cryptography.MLDsa.IsSupported);
 
#pragma warning disable SYSLIB5006 // Type is for evaluation purposes only and is subject to change or removal in future updates. Suppress this diagnostic to proceed.
  Console.WriteLine("SLH-DSA (FIPS 205) für Digitale Signaturen (Alternative/Reserve): " + System.Security.Cryptography.SlhDsa.IsSupported);
 
 
 }
 
 /// 
 /// ML-KEM (quantensicher) schützt den Schlüsselaustausch
 /// AES-256 (quantenresistent) verschlüsselt die Daten
 /// Beide zusammen bieten vollständigen Quantenschutz
 /// 
 public void KEMDemo()
 {
  CUI.Demo(nameof(KEMDemo) + ": Verschlüsselung mit AES unter Verwendung von ML-KEM zum Schlüsselaustausch");
 
  try
  {
   string originalText = "Dies ist ein vertraulicher Text, der mit Post-Quantum Cryptography geschützt wird!";
 
   CUI.H2("Originaltext");
   Console.WriteLine(originalText);
 
   // 1. Empfänger generiert Schlüsselpaar
   CUI.H2("1. Schlüsselpaar generieren (Empfänger)");
   using MLKem receiverKey = MLKem.GenerateKey(MLKemAlgorithm.MLKem1024);
 
   // Export/Import als PEM
   string publicKeyPem = receiverKey.ExportSubjectPublicKeyInfoPem();
   Console.WriteLine($"Öffentlicher Schlüssel (PEM): {publicKeyPem.Substring(0, Math.Min(80, publicKeyPem.Length))}...");
 
   // 2. Sender verwendet öffentlichen Schlüssel für Encapsulation
   CUI.H2("2. Gemeinsames Geheimnis erzeugen (Sender)");
   using MLKem senderKey = MLKem.ImportFromPem(publicKeyPem);
 
   // ML-KEM 1024: Ciphertext = 1568 Bytes, Shared Secret = 32 Bytes
   byte[] ciphertext = new byte[1568];
   byte[] sharedSecretSender = new byte[32];
   senderKey.Encapsulate(ciphertext, sharedSecretSender);
   Console.WriteLine($"Ciphertext Größe: {ciphertext.Length} Bytes");
   Console.WriteLine($"Gemeinsames Geheimnis (Sender): {Convert.ToHexString(sharedSecretSender)}");
 
   // 3. Sender verschlüsselt Daten mit AES unter Verwendung des gemeinsamen Geheimnisses
   CUI.H2("3. Daten mit AES verschlüsseln (Sender)");
   byte[] encryptedData;
   byte[] iv;
   using (Aes aes = Aes.Create())
   {
    aes.Key = sharedSecretSender;
    aes.GenerateIV();
    iv = aes.IV;
    using ICryptoTransform encryptor = aes.CreateEncryptor();
    byte[] plainBytes = System.Text.Encoding.UTF8.GetBytes(originalText);
    encryptedData = encryptor.TransformFinalBlock(plainBytes, 0, plainBytes.Length);
   }
   Console.WriteLine($"Verschlüsselte Daten: {Convert.ToHexString(encryptedData)}");
   Console.WriteLine($"IV: {Convert.ToHexString(iv)}");
 
   // 4. Empfänger extrahiert gemeinsames Geheimnis mit Decapsulation
   CUI.H2("4. Gemeinsames Geheimnis extrahieren (Empfänger)");
   byte[] sharedSecretReceiver = new byte[32];
   receiverKey.Decapsulate(ciphertext, sharedSecretReceiver);
   Console.WriteLine($"Gemeinsames Geheimnis (Empfänger): {Convert.ToHexString(sharedSecretReceiver)}");
   Console.WriteLine($"Geheimnisse identisch: {sharedSecretSender.SequenceEqual(sharedSecretReceiver)}");
 
   // 5. Empfänger entschlüsselt Daten mit AES
   CUI.H2("5. Daten mit AES entschlüsseln (Empfänger)");
   string decryptedText;
   using (Aes aes = Aes.Create())
   {
    aes.Key = sharedSecretReceiver;
    aes.IV = iv;
    using ICryptoTransform decryptor = aes.CreateDecryptor();
    byte[] decryptedBytes = decryptor.TransformFinalBlock(encryptedData, 0, encryptedData.Length);
    decryptedText = System.Text.Encoding.UTF8.GetString(decryptedBytes);
   }
 
   CUI.H2("Entschlüsselter Text");
   CUI.Green(decryptedText);
   CUI.Success($"Verschlüsselung erfolgreich: {originalText == decryptedText}");
  }
  catch (Exception ex)
  {
   CUI.Error(ex);
  }
 }
 
 /// 
 /// ML-DSA (FIPS 204) - Post-Quantum Digitale Signaturen
 /// Quantensichere Alternative zu RSA/ECDSA für digitale Signaturen
 /// 
 public void DSADemo()
 {
  CUI.Demo(nameof(DSADemo) + ": ML-DSA (FIPS 204) - Post-Quantum Digitale Signaturen");
 
  try
  {
   string originalText = "Dieses Dokument muss digital signiert werden, um Integrität und Authentizität zu gewährleisten.";
 
   CUI.H2("Originaldokument");
   Console.WriteLine(originalText);
   byte[] data = System.Text.Encoding.UTF8.GetBytes(originalText);
 
   // 1. Sender generiert Schlüsselpaar
   CUI.H2("1. Schlüsselpaar generieren (Sender)");
   using MLDsa senderKey = MLDsa.GenerateKey(MLDsaAlgorithm.MLDsa87);
   Console.WriteLine($"Algorithmus: {MLDsaAlgorithm.MLDsa87} (höchste Sicherheitsstufe)");
 
   // Export öffentlicher Schlüssel als PEM
   string publicKeyPem = senderKey.ExportSubjectPublicKeyInfoPem();
   Console.WriteLine($"Öffentlicher Schlüssel (PEM): {publicKeyPem.Substring(0, Math.Min(80, publicKeyPem.Length))}...");
 
   // 2. Sender signiert die Daten
   CUI.H2("2. Daten signieren (Sender)");
   byte[] signature = senderKey.SignData(data);
   Console.WriteLine($"Signatur Größe: {signature.Length} Bytes");
   Console.WriteLine($"Signatur: {Convert.ToHexString(signature).Substring(0, Math.Min(100, Convert.ToHexString(signature).Length))}...");
 
   // 3. Empfänger importiert öffentlichen Schlüssel
   CUI.H2("3. Öffentlichen Schlüssel importieren (Empfänger)");
   using MLDsa verifierKey = MLDsa.ImportFromPem(publicKeyPem);
   Console.WriteLine("Öffentlicher Schlüssel erfolgreich importiert");
 
   // 4. Empfänger verifiziert die Signatur
   CUI.H2("4. Signatur verifizieren (Empfänger)");
   bool isValid = verifierKey.VerifyData(data, signature);
 
   if (isValid)
   {
    CUI.Success("✓ Signatur ist gültig! Datenintegrität bestätigt.");
   }
   else
   {
    CUI.Error("✗ Signatur ist ungültig! Daten wurden möglicherweise manipuliert.");
   }
 
   // 5. Manipulationsversuch demonstrieren
   CUI.H2("5. Manipulationsversuch demonstrieren");
   byte[] manipulatedData = System.Text.Encoding.UTF8.GetBytes(originalText + " MANIPULIERT!");
   bool isManipulatedValid = verifierKey.VerifyData(manipulatedData, signature);
 
   if (!isManipulatedValid)
   {
    CUI.Warning("✓ Manipulation wurde erkannt! Signatur ist für geänderte Daten ungültig.");
   }
   else
   {
    CUI.Error("✗ FEHLER: Manipulation wurde nicht erkannt!");
   }
  }
  catch (Exception ex)
  {
   CUI.Error(ex);
  }
 }



Screenshot

Screenshot

Der Screenshot zeigt die Ausgabe des Beispielcodes (Abb. 1).


(rme)



Source link

Weiterlesen

Beliebt