Freigeben über


Tutorial zu RSS Reader (Rust für Windows mit VS Code)

Im vorherigen Thema wurden Rust für Windows und die Kiste „windows“ vorgestellt.

In diesem Thema können Sie Rust für Windows ausprobieren, indem Sie eine einfache Konsolen-App schreiben, die Titel von Blogbeiträgen aus einem RSS-Feed (Really Simple Syndication) herunterlädt.

  1. Starten Sie eine Eingabeaufforderung (cmd.exe), und wechseln (cd) Sie zu einem Ordner, in dem Sie Ihre Rust-Projekte aufbewahren möchten.

  2. Erstellen Sie mithilfe von Cargo ein neues Rust-Projekt namens rss_reader, und wechseln Sie mithilfe von cd in den neu erstellten Ordner:

    > cargo new rss_reader
    >     Created binary (application) `rss_reader` package
    > cd rss_reader
    
  3. Öffnen Sie als Nächstes das Projekt rss_reader in VS Code.

    code .
    
  4. Implementieren Sie nun das Hauptprojekt rss_reader. Öffnen Sie zunächst die Datei Cargo.toml im Stammverzeichnis des Projekts. Bei einer Datei vom Typ Cargo.toml handelt es sich um eine Textdatei zur Beschreibung eines Rust-Projekts (einschließlich aller zugehörigen Abhängigkeiten).

    Fügen Sie eine Abhängigkeit von der Kiste windows hinzu, wie im folgenden Listing gezeigt. Die Kiste windows ist groß. Um die Buildzeiten kurz zu halten, wählen wir nur die Features Foundation_Collections und Web_Syndication aus, die wir für diesen Code benötigen.

    # Cargo.toml
    ...
    
    [dependencies.windows] 
    version = "0.43.0"
    features = [
        "Foundation_Collections",
        "Web_Syndication",
    ]
    
  5. Öffnen Sie anschließend die Quellcodedatei src/main.rs des Projekts rss_reader. Dort finden Sie den Cargo-Standardcode „Hello, world!“. Fügen Sie am Anfang von main.rs die folgende use-Anweisung hinzu:

    // src\main.rs
    use windows::{
        core::*,
        Foundation::Uri,
        Web::Syndication::SyndicationClient
    };
    
    fn main() {
        println!("Hello, world!");
    }
    

    Durch die use-Deklaration wird der Pfad zu den von uns verwendeten Typen verkürzt. Hier sehen Sie auch den zuvor erwähnten Typ Uri.

  6. Um einen neuen URI zu erstellen, ersetzen Sie die standardmäßige main-Funktion von Cargo durch Folgendes:

    // src\main.rs
    ...
    
    fn main() -> Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
    
        Ok(())
    }
    

    Beachten Sie, dass der Rückgabetyp der main-Funktion ein Result-Wert aus windows::core:: ist. Dies dient der Vereinfachung, da häufig Fehler von Betriebssystem-APIs behandelt werden müssen. windows::core::Result ist für die Fehlerweitergabe sowie für eine präzise Fehlerbehandlung hilfreich.

    Haben Sie den Fragezeichen-Operator am Ende der Codezeile bemerkt? Er wird verwendet, um weniger eingeben zu müssen und die Fehlerweitergabe und Kurzschlusslogik von Rust zu verwenden. Das bedeutet, dass für dieses einfache Beispiel keine umfangreiche manuelle Fehlerbehandlung erforderlich ist. Weitere Informationen zu diesem Feature von Rust finden Sie unter Einfachere Fehlerbehandlung durch den ?-Operator.

    Beachten Sie auch das Makro h! aus der windows-Kiste. Es wird verwendet, um einen HSTRING-Verweis aus einem Rust-Zeichenfolgenliteral zu erstellen. Die WinRT-API verwendet HSTRING sehr häufig für Zeichenfolgenwerte.

  7. Zum Herunterladen des RSS-Feeds erstellen wir ein neues Objekt vom Typ SyndicationClient.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        Ok(())
    }
    

    Die Funktion new ist ein Rust-Konstruktor. Alle Objekte in der windows-Kiste halten die Rust-Konvention und nennen ihre Konstruktoren new.

  8. Nun können Sie SyndicationClient verwenden, um den Feed abzurufen.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        Ok(())
    }
    

    Da es sich bei RetrieveFeedAsync um eine asynchrone API handelt, verwenden wir die blockierende Funktion get, um das Beispiel einfach zu halten. Alternativ können Sie auch den Operator await in einer Funktion vom Typ async verwenden, um kooperativ auf die Ergebnisse zu warten. Eine komplexere App mit einer grafischen Benutzeroberfläche verwendet häufig async.

  9. Nun können Sie die resultierenden Elemente durchlaufen und die Ausgabe auf die Titel beschränken. Außerdem sehen Sie unten einige zusätzliche Codezeilen zum Festlegen eines User-Agent-Headers, da dies für einige RSS-Feeds erforderlich ist.

    // src\main.rs
    ...
    
    fn main() -> windows::core::Result<()> {
        let uri = Uri::CreateUri(h!("https://blogs.windows.com/feed"))?;
        let client = SyndicationClient::new()?;
    
        client.SetRequestHeader(
            h!("User-Agent"),
            h!("Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)"),
        )?;
    
        let feed = client.RetrieveFeedAsync(&uri)?.get()?;
    
        for item in feed.Items()? {
            println!("{}", item.Title()?.Text()?);
        }
    
        Ok(())
    }
    
  10. Überprüfen Sie als Nächstes, ob das Erstellen und Ausführen funktioniert. Klicken Sie hierzu auf Ausführen>Ohne Debuggen ausführen (oder drücken Sie STRG+F5). Wenn unerwartete Meldungen angezeigt werden, stellen Sie sicher, dass Sie das Tutorial zu Hello, world! (Rust mit VS Code) erfolgreich abgeschlossen haben.

    Befehle zum Debuggen und Ausführen stehen auch im Text-Editor zur Verfügung. Geben Sie alternativ an einer Eingabeaufforderung rss_reader im Ordner cargo run ein, um das Programm zu erstellen und dann auszuführen.

    In den Text-Editor eingebettete Befehle zum Debuggen und Ausführen

    Weiter unten im Terminalbereich von VS Code sehen Sie, dass Cargo die Kiste windows erfolgreich herunterlädt und kompiliert, die Ergebnisse zwischenspeichert und so nachfolgende Buildvorgänge beschleunigt. Anschließend wird das Beispiel erstellt und ausgeführt, und es wird eine Liste mit Blogbeitragstiteln angezeigt.

    Liste mit Blogbeitragstiteln

So einfach ist das Programmieren mit Rust für Windows. Im Hintergrund wird jedoch viel Arbeit in die Erstellung der Tools investiert, damit Rust Dateien vom Typ .winmd auf der Grundlage von ECMA-335 (Common Language Infrastructure, CLI) analysieren sowie zur Laufzeit ordnungsgemäß die COM-basierte binäre Anwendungsschnittstelle (Application Binary Interface, ABI) unter Berücksichtigung von Sicherheits- und Effizienzaspekten nutzen kann.

Anzeigen eines Nachrichtenfelds

Wir haben gesagt, dass Sie mit Rust für Windows eine beliebige (vergangene, aktuelle und zukünftige) Windows-API aufrufen können. Daher werden in diesem Abschnitt einige Windows-Meldungsfelder gezeigt.

  1. Genau wie beim RSS-Projekt können Sie an der Eingabeaufforderung mit cd in den Ordner mit Ihren Rust-Projekten wechseln.

  2. Erstellen Sie ein neues Projekt mit dem Namen message_box, und öffnen Sie es in VS Code:

    > cargo new message_box
    >     Created binary (application) `message_box` package
    > cd message_box
    > code .
    
  3. Öffnen Sie Cargo.toml in VS Code, und fügen Sie die Windows-Abhängigkeiten für dieses Projekt hinzu:

     # message_box\Cargo.toml
     ...
    
     [dependencies.windows]
     version = "0.43.0"
     features = [
         "Win32_Foundation",
         "Win32_UI_WindowsAndMessaging",
     ]
    
  4. Öffnen Sie nun die Datei src/main.rs des Projekts, und fügen Sie die use-Deklarationen mit den neuen Namespaces hinzu (wie unten gezeigt). Fügen Sie schließlich Code hinzu, um die Funktionen MessageBoxA und MessageBoxW aufzurufen. Die Windows-API-Dokumente sind hauptsächlich in C/C++ geschrieben, daher ist es hilfreich, die API-Dokumente mit den Dokumenten für die Rust-Projektionen in der windows-Kiste zu vergleichen: MessageBoxA (Rust) und MessageBoxW (Rust).

    // src\main.rs
    use windows::{
        core::*,
        Win32::UI::WindowsAndMessaging::*
    };
    
    fn main() {
        unsafe {
            MessageBoxA(None, s!("Ansi"), s!("World"), MB_OK);
            MessageBoxW(None, w!("Wide"), w!("World"), MB_OK);
        }
    }
    

    Wie Sie sehen können, müssen wir diese Win32-APIs in einem unsafe-Block verwenden (siehe Unsichere Blöcke). Beachten Sie auch die Makros s! und w!, die die Argumente LPCSTR und LPCWSTR aus Rust-UTF-8-Zeichenfolgenliteralen erstellen, ähnlich wie Sie ein HSTRING-Element mit dem Makro h! für rss_reader erstellt haben. Rust ist nativer Unicode-Text mit UTF-8-Zeichenfolgen. Daher wird die Verwendung der Windows-APIs für Unicode-Doppelbytezeichen (W-Suffix) den ANSI-APIs (A-Suffix) vorgezogen. Dies kann wichtig sein, wenn Sie nicht englischen Text in Ihrem Code verwenden.

Beim Erstellen und Ausführen zeigt Rust dieses Mal zwei Windows-Nachrichtenfelder an.