Freigeben über


Komponenten für Windows-Runtime mit C++/CX

Hinweis

Dieses Thema soll Ihnen dabei helfen, Ihre C++/CX-Anwendung zu pflegen. Wir empfehlen aber, C++/WinRT für neue Anwendungen zu nutzen. C++/WinRT ist eine vollständig standardisierte, moderne C++17-Programmiersprache für Windows-Runtime-APIs (WinRT), die als headerdateibasierte Bibliothek implementiert ist und Ihnen einen erstklassigen Zugriff auf die moderne Windows-API bietet. Informationen zum Erstellen einer Windows-Runtime-Komponente mithilfe von C++/WinRT finden Sie unter Windows-Runtime-Komponenten mit C++/WinRT.

In diesem Thema wird gezeigt, wie Sie mit C++/CX eine Windows-Runtime Komponente erstellen– eine Komponente, die von einer universellen Windows-App aufgerufen werden kann, die mit einer beliebigen Windows-Runtime Sprache (C#, Visual Basic, C++ oder JavaScript) erstellt wird.

Es gibt mehrere Gründe für die Erstellung einer Windows-Runtime Komponente in C++.

  • Um den Leistungsvorteil von C++ in komplexen oder rechenintensiven Vorgängen zu erzielen.
  • Um Code wiederzuverwenden, der bereits geschrieben und getestet wurde.

Wenn Sie eine Lösung erstellen, die ein JavaScript- oder .NET-Projekt und ein Windows-Runtime Komponentenprojekt enthält, werden die JavaScript-Projektdateien und die kompilierte DLL in einem Paket zusammengeführt, das Sie lokal im Simulator oder remote auf einem verbundenen Gerät debuggen können. Sie können auch nur das Komponentenprojekt als Erweiterungs-SDK verteilen. Weitere Informationen finden Sie unter Erstellen eines Software Development Kits.

Wenn Sie Ihre C++/CX-Komponente codieren, verwenden Sie im Allgemeinen die reguläre C++-Bibliothek und integrierte Typen, mit Ausnahme der Grenze der abstrakten binären Schnittstelle (ABI), an die Sie Daten an und von Code in einem anderen WINMD-Paket übergeben. Verwenden Sie dort Windows-Runtime Typen und die spezielle Syntax, die C++/CX zum Erstellen und Bearbeiten dieser Typen unterstützt. Verwenden Sie in Ihrem C++/CX-Code außerdem Typen wie Stellvertretung und Ereignis, um Ereignisse zu implementieren, die von Der Komponente ausgelöst und in JavaScript, Visual Basic, C++ oder C# behandelt werden können. Weitere Informationen zur C++/CX-Syntax finden Sie in der Visual C++-Sprachreferenz (C++/CX).

Regeln für Groß- und Kleinschreibung

JavaScript

Bei JavaScript wird die Groß-/Kleinschreibung beachtet. Daher müssen Sie die folgenden Groß-/Kleinschreibungskonventionen einhalten:

  • Wenn Sie auf C++-Namespaces und -Klassen verweisen, verwenden Sie die gleiche Groß-/Kleinschreibung, die auf der C++-Seite verwendet wird.
  • Wenn Sie Methoden aufrufen, verwenden Sie die Kamel-Großschreibung, auch wenn der Methodenname auf der C++-Seite großgeschrieben ist. Beispielsweise muss eine C++-Methode GetDate() aus JavaScript als getDate() aufgerufen werden.
  • Ein aktivierbarer Klassenname und Namespacename dürfen keine UNICODE-Zeichen enthalten.

.NET

Die .NET-Sprachen folgen ihren normalen Groß-/Kleinschreibungsregeln.

Instanziieren des Objekts

Nur Windows-Runtime Typen können über die ABI-Grenze übergeben werden. Der Compiler löst einen Fehler aus, wenn die Komponente einen Typ wie "std::wstring" als Rückgabetyp oder -parameter in einer öffentlichen Methode aufweist. Zu den integrierten Visual C++-Komponentenerweiterungen (C++/CX) gehören die üblichen Skalar wie Int und Double sowie deren Typedef-Entsprechungen int32, float64 usw. Weitere Informationen finden Sie unter Type System (C++/CX).For more information, see Type System (C++/CX).

// ref class definition in C++
public ref class SampleRefClass sealed
{
    // Class members...

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }

};
//Instantiation in JavaScript (requires "Add reference > Project reference")
var nativeObject = new CppComponent.SampleRefClass();
//Call a method and display result in a XAML TextBlock
var num = nativeObject.LogCalc(21.5);
ResultText.Text = num.ToString();

Integrierte C++/CX-Typen, Bibliothekstypen und Windows-Runtime Typen

Eine aktivierbare Klasse (auch als Referenzklasse bezeichnet) ist eine Klasse, die von einer anderen Sprache wie JavaScript, C# oder Visual Basic instanziiert werden kann. Damit eine Komponente von einer anderen Sprache verwendet werden kann, muss eine Komponente mindestens eine aktivierbare Klasse enthalten.

Eine Windows-Runtime Komponente kann mehrere öffentliche aktivierbare Klassen sowie zusätzliche Klassen enthalten, die nur intern für die Komponente bekannt sind. Wenden Sie das WebHostHidden-Attribut auf C++/CX-Typen an, die nicht für JavaScript sichtbar sind.

Alle öffentlichen Klassen müssen sich im selben Stammnamespace befinden, der denselben Namen wie die Metadatendatei der Komponente aufweist. Zum Beispiel kann eine Klasse namens A.B.C.MyClass nur instanziiert werden, wenn sie in einer Metadatendatei definiert ist, die A.winmd oder A.B.winmd oder A.B.C.winmd heißt. Der Name der DLL muss nicht mit dem Namen der WINMD-Datei übereinstimmen.

Clientcode erstellt eine Instanz der Komponente mithilfe des neuen Schlüsselworts (New in Visual Basic) genau wie für jede Klasse.

Eine aktivierbare Klasse muss als öffentliche Referenzklasse versiegelt deklariert werden. Das Schlüsselwort der Referenzklasse weist den Compiler an, die Klasse als Windows-Runtime kompatiblen Typ zu erstellen, und das versiegelte Schlüsselwort gibt an, dass die Klasse nicht geerbt werden kann. Das Windows-Runtime unterstützt derzeit kein generalisiertes Vererbungsmodell. Ein eingeschränktes Vererbungsmodell unterstützt die Erstellung benutzerdefinierter XAML-Steuerelemente. Weitere Informationen finden Sie unter Referenzklassen und -strukturen (C++/CX).For more information, see Ref classes and structs (C++/CX).

Für C++/CX werden alle numerischen Grundtypen im Standardnamespace definiert. Der Platform-Namespace enthält C++/CX-Klassen, die für das Windows-Runtime Typsystem spezifisch sind. Dazu gehören Platform::String-Klasse und Platform::Object-Klasse . Die konkreten Sammlungstypen wie Platform::Collections::Map class and Platform::Collections::Vector class are defined in the Platform::Collections namespace. Die öffentlichen Schnittstellen, die diese Typen implementieren, sind in Windows::Foundation::Collections Namespace (C++/CX) definiert. Es handelt sich um diese Schnittstellentypen, die von JavaScript, C# und Visual Basic verwendet werden. Weitere Informationen finden Sie unter Type System (C++/CX).For more information, see Type System (C++/CX).

Methode, die einen Wert des integrierten Typs zurückgibt

    // #include <valarray>
public:
    double LogCalc(double input)
    {
        // Use C++ standard library as usual.
        return std::log(input);
    }
//Call a method
var nativeObject = new CppComponent.SampleRefClass;
var num = nativeObject.logCalc(21.5);
document.getElementById('P2').innerHTML = num;

Methode, die eine benutzerdefinierte Wertstruktur zurückgibt

namespace CppComponent
{
    // Custom struct
    public value struct PlayerData
    {
        Platform::String^ Name;
        int Number;
        double ScoringAverage;
    };

    public ref class Player sealed
    {
    private:
        PlayerData m_player;
    public:
        property PlayerData PlayerStats
        {
            PlayerData get(){ return m_player; }
            void set(PlayerData data) {m_player = data;}
        }
    };
}

Um benutzerdefinierte Wertstrukturen über die ABI zu übergeben, definieren Sie ein JavaScript-Objekt mit denselben Elementen wie die Wertstruktur, die in C++/CX definiert ist. Anschließend können Sie dieses Objekt als Argument an eine C++/CX-Methode übergeben, sodass das Objekt implizit in den C++/CX-Typ konvertiert wird.

// Get and set the value struct
function GetAndSetPlayerData() {
    // Create an object to pass to C++
    var myData =
        { name: "Bob Homer", number: 12, scoringAverage: .357 };
    var nativeObject = new CppComponent.Player();
    nativeObject.playerStats = myData;

    // Retrieve C++ value struct into new JavaScript object
    var myData2 = nativeObject.playerStats;
    document.getElementById('P3').innerHTML = myData.name + " , " + myData.number + " , " + myData.scoringAverage.toPrecision(3);
}

Ein weiterer Ansatz besteht darin, eine Klasse zu definieren, die IPropertySet implementiert (nicht dargestellt).

In den .NET-Sprachen erstellen Sie einfach eine Variable des Typs, der in der C++/CX-Komponente definiert ist.

private void GetAndSetPlayerData()
{
    // Create a ref class
    var player = new CppComponent.Player();

    // Create a variable of a value struct
    // type that is defined in C++
    CppComponent.PlayerData myPlayer;
    myPlayer.Name = "Babe Ruth";
    myPlayer.Number = 12;
    myPlayer.ScoringAverage = .398;

    // Set the property
    player.PlayerStats = myPlayer;

    // Get the property and store it in a new variable
    CppComponent.PlayerData myPlayer2 = player.PlayerStats;
    ResultText.Text += myPlayer.Name + " , " + myPlayer.Number.ToString() +
        " , " + myPlayer.ScoringAverage.ToString();
}

Überladene Methoden

Eine öffentliche C++/CX-Referenzklasse kann überladene Methoden enthalten, JavaScript verfügt jedoch über eingeschränkte Möglichkeiten, überladene Methoden zu unterscheiden. Sie kann beispielsweise den Unterschied zwischen diesen Signaturen erkennen:

public ref class NumberClass sealed
{
public:
    int GetNumber(int i);
    int GetNumber(int i, Platform::String^ str);
    double GetNumber(int i, MyData^ d);
};

Aber es kann den Unterschied zwischen diesen nicht erkennen:

int GetNumber(int i);
double GetNumber(double d);

In mehrdeutigen Fällen können Sie sicherstellen, dass JavaScript immer eine bestimmte Überladung aufruft, indem Sie das Attribut "Windows::Foundation::Metadata::D efaultOverload " auf die Methodensignatur in der Headerdatei anwenden.

Dieser JavaScript ruft immer die Attributüberladung auf:

var nativeObject = new CppComponent.NumberClass();
var num = nativeObject.getNumber(9);
document.getElementById('P4').innerHTML = num;

.NET

Die .NET-Sprachen erkennen Überladungen in einer C++/CX-Referenzklasse genauso wie in jeder .NET-Klasse.

DateTime

In der Windows-Runtime ist ein Windows::Foundation::D ateTime-Objekt nur eine 64-Bit-Ganzzahl, die die Anzahl von 100-Nanosekundenintervallen vor oder nach dem 1. Januar 1601 darstellt. Es gibt keine Methoden für ein Windows:Foundation::D ateTime-Objekt. Stattdessen projiziert jede Sprache die DateTime so, dass sie in dieser Sprache nativ ist: das Date-Objekt in JavaScript und die System.DateTime- und System.DateTimeOffset-Typen in .NET.

public  ref class MyDateClass sealed
{
public:
    property Windows::Foundation::DateTime TimeStamp;
    void SetTime(Windows::Foundation::DateTime dt)
    {
        auto cal = ref new Windows::Globalization::Calendar();
        cal->SetDateTime(dt);
        TimeStamp = cal->GetDateTime(); // or TimeStamp = dt;
    }
};

Wenn Sie einen DateTime-Wert von C++/CX an JavaScript übergeben, akzeptiert JavaScript ihn als Date-Objekt und zeigt ihn standardmäßig als lange Datumszeichenfolge an.

function SetAndGetDate() {
    var nativeObject = new CppComponent.MyDateClass();

    var myDate = new Date(1956, 4, 21);
    nativeObject.setTime(myDate);

    var myDate2 = nativeObject.timeStamp;

    //prints long form date string
    document.getElementById('P5').innerHTML = myDate2;

}

Wenn eine .NET-Sprache eine System.DateTime-Komponente an eine C++/CX-Komponente übergibt, akzeptiert die Methode sie als Windows::Foundation::D ateTime. Wenn die Komponente eine Windows::Foundation::D ateTime-Methode an eine .NET-Methode übergibt, akzeptiert sie die Framework-Methode als DateTimeOffset.

private void DateTimeExample()
{
    // Pass a System.DateTime to a C++ method
    // that takes a Windows::Foundation::DateTime
    DateTime dt = DateTime.Now;
    var nativeObject = new CppComponent.MyDateClass();
    nativeObject.SetTime(dt);

    // Retrieve a Windows::Foundation::DateTime as a
    // System.DateTimeOffset
    DateTimeOffset myDate = nativeObject.TimeStamp;

    // Print the long-form date string
    ResultText.Text += myDate.ToString();
}

Auflistungen und Arrays

Sammlungen werden immer über die ABI-Grenze hinweg als Handles an Windows-Runtime Typen wie Windows::Foundation::Collections::IVector^ und Windows::Foundation::Collections::IMap^übergeben. Wenn Sie z. B. ein Handle an "Platform::Collections::Map" zurückgeben, wird es implizit in ein Windows::Foundation::Collections::IMap^-Objekt konvertiert. Die Sammlungsschnittstellen werden in einem Namespace definiert, der von den C++/CX-Klassen getrennt ist, die die konkreten Implementierungen bereitstellen. JavaScript- und .NET-Sprachen nutzen die Schnittstellen. Weitere Informationen finden Sie unter Sammlungen (C++/CX) und Array und WriteOnlyArray (C++/CX).

Übergeben von IVector

// Windows::Foundation::Collections::IVector across the ABI.
//#include <algorithm>
//#include <collection.h>
Windows::Foundation::Collections::IVector<int>^ SortVector(Windows::Foundation::Collections::IVector<int>^ vec)
{
    std::sort(begin(vec), end(vec));
    return vec;
}
var nativeObject = new CppComponent.CollectionExample();
// Call the method to sort an integer array
var inVector = [14, 12, 45, 89, 23];
var outVector = nativeObject.sortVector(inVector);
var result = "Sorted vector to array:";
for (var i = 0; i < outVector.length; i++)
{
    outVector[i];
    result += outVector[i].toString() + ",";
}
document.getElementById('P6').innerHTML = result;

Die .NET-Sprachen sehen IVector<T> als IList<T>.

private void SortListItems()
{
    IList<int> myList = new List<int>();
    myList.Add(5);
    myList.Add(9);
    myList.Add(17);
    myList.Add(2);

    var nativeObject = new CppComponent.CollectionExample();
    IList<int> mySortedList = nativeObject.SortVector(myList);

    foreach (var item in mySortedList)
    {
        ResultText.Text += " " + item.ToString();
    }
}

Übergeben von IMap

// #include <map>
//#include <collection.h>
Windows::Foundation::Collections::IMap<int, Platform::String^> ^GetMap(void)
{    
    Windows::Foundation::Collections::IMap<int, Platform::String^> ^ret =
        ref new Platform::Collections::Map<int, Platform::String^>;
    ret->Insert(1, "One ");
    ret->Insert(2, "Two ");
    ret->Insert(3, "Three ");
    ret->Insert(4, "Four ");
    ret->Insert(5, "Five ");
    return ret;
}
// Call the method to get the map
var outputMap = nativeObject.getMap();
var mStr = "Map result:" + outputMap.lookup(1) + outputMap.lookup(2)
    + outputMap.lookup(3) + outputMap.lookup(4) + outputMap.lookup(5);
document.getElementById('P7').innerHTML = mStr;

Die .NET-Sprachen finden Sie unter IMap und IDictionary<K, V>.

private void GetDictionary()
{
    var nativeObject = new CppComponent.CollectionExample();
    IDictionary<int, string> d = nativeObject.GetMap();
    ResultText.Text += d[2].ToString();
}

Eigenschaften

Eine öffentliche Verweisklasse in C++/CX-Komponentenerweiterungen macht öffentliche Datenmember als Eigenschaften verfügbar, indem das Schlüsselwort "Property" verwendet wird. Das Konzept ist identisch mit .NET-Eigenschaften. Eine triviale Eigenschaft ähnelt einem Datenmemm, da seine Funktionalität implizit ist. Eine nicht triviale Eigenschaft verfügt über explizite Get- und Set-Accessoren und eine benannte private Variable, die den "Sicherungsspeicher" für den Wert darstellt. In diesem Beispiel ist die private Membervariable _propertyAValue der Sicherungsspeicher für PropertyA. Eine Eigenschaft kann ein Ereignis auslösen, wenn sich der Wert ändert, und eine Client-App kann sich für den Empfang dieses Ereignisses registrieren.

//Properties
public delegate void PropertyChangedHandler(Platform::Object^ sender, int arg);
public ref class PropertyExample  sealed
{
public:
    PropertyExample(){}

    // Event that is fired when PropertyA changes
    event PropertyChangedHandler^ PropertyChangedEvent;

    // Property that has custom setter/getter
    property int PropertyA
    {
        int get() { return m_propertyAValue; }
        void set(int propertyAValue)
        {
            if (propertyAValue != m_propertyAValue)
            {
                m_propertyAValue = propertyAValue;
                // Fire event. (See event example below.)
                PropertyChangedEvent(this, propertyAValue);
            }
        }
    }

    // Trivial get/set property that has a compiler-generated backing store.
    property Platform::String^ PropertyB;

private:
    // Backing store for propertyA.
    int m_propertyAValue;
};
var nativeObject = new CppComponent.PropertyExample();
var propValue = nativeObject.propertyA;
document.getElementById('P8').innerHTML = propValue;

//Set the string property
nativeObject.propertyB = "What is the meaning of the universe?";
document.getElementById('P9').innerHTML += nativeObject.propertyB;

Die .NET-Sprachen greifen auf Eigenschaften für ein systemeigenes C++/CX-Objekt genauso zu wie in einem .NET-Objekt zu.

private void GetAProperty()
{
    // Get the value of the integer property
    // Instantiate the C++ object
    var obj = new CppComponent.PropertyExample();

    // Get an integer property
    var propValue = obj.PropertyA;
    ResultText.Text += propValue.ToString();

    // Set a string property
    obj.PropertyB = " What is the meaning of the universe?";
    ResultText.Text += obj.PropertyB;

}

Delegaten und Ereignisse

Ein Delegat ist ein Windows-Runtime Typ, der ein Funktionsobjekt darstellt. Sie können Stellvertretungen in Verbindung mit Ereignissen, Rückrufen und asynchronen Methodenaufrufen verwenden, um eine später auszuführende Aktion anzugeben. Wie ein Funktionsobjekt bietet der Delegat die Typsicherheit, indem der Compiler die Rückgabetyp- und Parametertypen der Funktion überprüfen kann. Die Deklaration eines Delegaten ähnelt einer Funktionssignatur, die Implementierung ähnelt einer Klassendefinition, und der Aufruf ähnelt einem Funktionsaufruf.

Hinzufügen eines Ereignislisteners

Sie können das Ereignisschlüsselwort verwenden, um ein öffentliches Mitglied eines angegebenen Delegatentyps zu deklarieren. Clientcode abonniert das Ereignis mithilfe der Standardmechanismen, die in der jeweiligen Sprache bereitgestellt werden.

public:
    event SomeHandler^ someEvent;

In diesem Beispiel wird der gleiche C++-Code wie für den vorherigen Eigenschaftenabschnitt verwendet.

function Button_Click() {
    var nativeObj = new CppComponent.PropertyExample();
    // Define an event handler method
    var singlecasthandler = function (ev) {
        document.getElementById('P10').innerHTML = "The button was clicked and the value is " + ev;
    };

    // Subscribe to the event
    nativeObj.onpropertychangedevent = singlecasthandler;

    // Set the value of the property and fire the event
    var propValue = 21;
    nativeObj.propertyA = 2 * propValue;

}

In den .NET-Sprachen entspricht das Abonnieren eines Ereignisses in einer C++-Komponente dem Abonnieren eines Ereignisses in einer .NET-Klasse:

//Subscribe to event and call method that causes it to be fired.
private void TestMethod()
{
    var objWithEvent = new CppComponent.PropertyExample();
    objWithEvent.PropertyChangedEvent += objWithEvent_PropertyChangedEvent;

    objWithEvent.PropertyA = 42;
}

//Event handler method
private void objWithEvent_PropertyChangedEvent(object __param0, int __param1)
{
    ResultText.Text = "the event was fired and the result is " +
         __param1.ToString();
}

Hinzufügen mehrerer Ereignislistener für ein Ereignis

JavaScript verfügt über eine addEventListener-Methode, mit der mehrere Handler ein einzelnes Ereignis abonnieren können.

public delegate void SomeHandler(Platform::String^ str);

public ref class LangSample sealed
{
public:
    event SomeHandler^ someEvent;
    property Platform::String^ PropertyA;

    // Method that fires an event
    void FireEvent(Platform::String^ str)
    {
        someEvent(Platform::String::Concat(str, PropertyA->ToString()));
    }
    //...
};
// Add two event handlers
var multicast1 = function (ev) {
    document.getElementById('P11').innerHTML = "Handler 1: " + ev.target;
};
var multicast2 = function (ev) {
    document.getElementById('P12').innerHTML = "Handler 2: " + ev.target;
};

var nativeObject = new CppComponent.LangSample();
//Subscribe to the same event
nativeObject.addEventListener("someevent", multicast1);
nativeObject.addEventListener("someevent", multicast2);

nativeObject.propertyA = "42";

// This method should fire an event
nativeObject.fireEvent("The answer is ");

In C# kann eine beliebige Anzahl von Ereignishandlern das Ereignis abonnieren, indem der Operator += verwendet wird, wie im vorherigen Beispiel gezeigt.

Enumerationen

Eine Windows-Runtime Enumeration in C++/CX wird mithilfe der öffentlichen Klassenenume deklariert. Sie ähnelt einer bereichsbezogenen Enumeration in Standard-C++.

public enum class Direction {North, South, East, West};

public ref class EnumExampleClass sealed
{
public:
    property Direction CurrentDirection
    {
        Direction  get(){return m_direction; }
    }

private:
    Direction m_direction;
};

Enumerationswerte werden zwischen C++/CX und JavaScript als ganze Zahlen übergeben. Sie können optional ein JavaScript-Objekt deklarieren, das dieselben benannten Werte wie die C++/CX-Enumeration enthält, und es wie folgt verwenden.

var Direction = { 0: "North", 1: "South", 2: "East", 3: "West" };
//. . .

var nativeObject = new CppComponent.EnumExampleClass();
var curDirection = nativeObject.currentDirection;
document.getElementById('P13').innerHTML =
Direction[curDirection];

Sowohl C# als auch Visual Basic verfügen über Sprachunterstützung für Enumerationen. Diese Sprachen sehen eine öffentliche C++-Enumerationsklasse genauso wie eine .NET-Enumeration.

Asynchrone Methoden

Verwenden Sie die Taskklasse (Concurrency Runtime), um asynchrone Methoden zu nutzen, die von anderen Windows-Runtime Objekten verfügbar gemacht werden. Weitere Informationen finden Sie unter " Parallelismus( Parallelitätslaufzeit)".

Um asynchrone Methoden in C++/CX zu implementieren, verwenden Sie die in "ppltasks.h" definierte create_async-Funktion . Weitere Informationen finden Sie unter Erstellen asynchroner Vorgänge in C++/CX für UWP-Apps. Ein Beispiel finden Sie unter Walkthrough of creating a C++/CX Windows-Runtime component, and calling it from JavaScript or C#. Die .NET-Sprachen verwenden asynchrone C++/CX-Methoden genauso wie jede asynchrone Methode, die in .NET definiert ist.

Ausnahmen

Sie können jeden Ausnahmetyp auslösen, der durch die Windows-Runtime definiert ist. Sie können keine benutzerdefinierten Typen von einem Windows-Runtime Ausnahmetyp ableiten. Sie können COMException jedoch auslösen und ein benutzerdefiniertes HRESULT bereitstellen, auf das über den Code zugegriffen werden kann, der die Ausnahme abfangen soll. Es gibt keine Möglichkeit, eine benutzerdefinierte Nachricht in einer COMException anzugeben.

Tipps zum Debuggen

Wenn Sie eine JavaScript-Lösung debuggen, die über eine Komponenten-DLL verfügt, können Sie den Debugger so festlegen, dass er entweder das Durchlaufen des Skripts oder das Durchlaufen von systemeigenem Code in der Komponente, aber nicht beide gleichzeitig ermöglicht. Um die Einstellung zu ändern, wählen Sie den JavaScript-Projektknoten in Projektmappen-Explorer aus, und wählen Sie dann "Eigenschaften", "Debuggen", "Debuggertyp" aus.

Achten Sie darauf, die entsprechenden Funktionen im Paket-Designer auszuwählen. Wenn Sie beispielsweise versuchen, eine Bilddatei in der Bildbibliothek des Benutzers mithilfe der Windows-Runtime-APIs zu öffnen, müssen Sie das Kontrollkästchen "Bildbibliothek" im Bereich "Funktionen" des Manifest-Designers aktivieren.

Wenn Ihr JavaScript-Code die öffentlichen Eigenschaften oder Methoden in der Komponente nicht erkennt, stellen Sie sicher, dass Sie in JavaScript die Kamelschreibung verwenden. Beispielsweise muss auf die LogCalc C++/CX-Methode in JavaScript als logCalc verwiesen werden.

Wenn Sie ein C++/CX-Windows-Runtime Komponentenprojekt aus einer Projektmappe entfernen, müssen Sie den Projektverweis auch manuell aus dem JavaScript-Projekt entfernen. Andernfalls wird verhindert, dass nachfolgende Debug- oder Buildvorgänge durchgeführt werden. Bei Bedarf können Sie der DLL einen Assemblyverweis hinzufügen.