Meningkatkan peristiwa di komponen Windows Runtime

Catatan

Untuk informasi selengkapnya tentang menaikkan peristiwa di Komponen Windows Runtime C++/WinRT , lihat Menulis peristiwa di C++/WinRT.

Jika komponen Windows Runtime Anda memunculkan peristiwa jenis delegasi yang ditentukan pengguna pada utas latar belakang (utas pekerja), dan Anda ingin JavaScript dapat menerima peristiwa tersebut, maka Anda dapat menerapkan dan/atau menaikkannya dengan salah satu cara ini.

  • (Opsi 1) Naikkan peristiwa melalui Windows.UI.Core.CoreDispatcher untuk membasmi peristiwa ke konteks utas JavaScript. Meskipun biasanya ini adalah opsi terbaik, dalam beberapa skenario mungkin tidak memberikan performa tercepat.
  • (Opsi 2) Gunakan Objek>Windows.Foundation.EventHandler< (tetapi kehilangan informasi jenis peristiwa). Jika Opsi 1 tidak layak, atau jika performanya tidak memadai, maka ini adalah pilihan kedua yang baik asalkan kehilangan informasi jenis dapat diterima. Jika Anda menulis Komponen Runtime C# Windows, maka jenis Objek> Windows.Foundation.EventHandler< tidak tersedia; sebagai gantinya, jenis tersebut diproyeksikan ke System.EventHandler, jadi Anda harus menggunakannya sebagai gantinya.
  • (Opsi 3) Buat proksi dan stub Anda sendiri untuk komponen. Opsi ini adalah yang paling sulit diterapkan, tetapi mempertahankan informasi jenis dan mungkin memberikan performa yang lebih baik dibandingkan dengan Opsi 1 dalam skenario yang menuntut.

Jika Anda hanya menaikkan peristiwa di utas latar belakang tanpa menggunakan salah satu opsi ini, klien JavaScript tidak akan menerima peristiwa tersebut.

Latar belakang

Semua komponen dan aplikasi Windows Runtime pada dasarnya adalah objek COM, apa pun bahasa yang Anda gunakan untuk membuatnya. Di Windows API, sebagian besar komponen adalah objek COM tangkas yang dapat berkomunikasi dengan baik dengan objek di utas latar belakang dan pada utas UI. Jika objek COM tidak dapat dibuat lincah, maka diperlukan objek pembantu yang dikenal sebagai proksi dan stub untuk berkomunikasi dengan objek COM lain di seluruh batas utas latar belakang UI. (Dalam istilah COM, ini dikenal sebagai komunikasi antara apartemen utas.)

Sebagian besar objek di Windows API tangkas atau memiliki proksi dan stub bawaan. Namun, proksi dan stub tidak dapat dibuat untuk jenis generik seperti Windows.Foundation. TypedEventHandler<TSender, TResult> karena jenisnya tidak lengkap sampai Anda memberikan argumen jenis. Hanya dengan klien JavaScript bahwa kurangnya proksi atau stub menjadi masalah, tetapi jika Anda ingin komponen Anda dapat digunakan dari JavaScript serta dari C++ atau bahasa .NET, maka Anda harus menggunakan salah satu dari tiga opsi berikut.

(Opsi 1) Naikkan acara melalui CoreDispatcher

Anda dapat mengirim peristiwa dari jenis delegasi yang ditentukan pengguna dengan menggunakan Windows.UI.Core.CoreDispatcher, dan JavaScript akan dapat menerimanya. Jika Anda tidak yakin opsi mana yang akan digunakan, coba opsi ini terlebih dahulu. Jika latensi antara pengaktifan peristiwa dan penanganan peristiwa menjadi masalah, maka coba salah satu opsi lainnya.

Contoh berikut menunjukkan cara menggunakan CoreDispatcher untuk meningkatkan peristiwa yang sangat diketik. Perhatikan bahwa argumen jenis adalah Toast, bukan Objek.

public event EventHandler<Toast> ToastCompletedEvent;
private void OnToastCompleted(Toast args)
{
    var completedEvent = ToastCompletedEvent;
    if (completedEvent != null)
    {
        completedEvent(this, args);
    }
}

public void MakeToastWithDispatcher(string message)
{
    Toast toast = new Toast(message);
    // Assume you have a CoreDispatcher at class scope.
    // Initialize it here, then use it from the background thread.
    var window = Windows.UI.Core.CoreWindow.GetForCurrentThread();
    m_dispatcher = window.Dispatcher;

    Task.Run( () =>
    {
        if (ToastCompletedEvent != null)
        {
            m_dispatcher.RunAsync(CoreDispatcherPriority.Normal,
            new DispatchedHandler(() =>
            {
                this.OnToastCompleted(toast);
            })); // end m_dispatcher.RunAsync
         }
     }); // end Task.Run
}

(Opsi 2) Gunakan Objek> EventHandler<tetapi kehilangan informasi jenis

Catatan

Jika Anda menulis Komponen Runtime C# Windows, maka jenis Objek> Windows.Foundation.EventHandler< tidak tersedia; sebagai gantinya, jenis tersebut diproyeksikan ke System.EventHandler, jadi Anda harus menggunakannya sebagai gantinya.

Cara lain untuk mengirim peristiwa dari utas latar belakang adalah dengan menggunakan Windows.Foundation.EventHandler<Object> sebagai jenis peristiwa. Windows menyediakan instansiasi konkret dari jenis generik ini dan menyediakan proksi dan stub untuk itu. Kelemahannya adalah bahwa informasi jenis argumen dan pengirim peristiwa Anda hilang. Klien C++ dan .NET harus tahu melalui dokumentasi jenis apa yang akan dilemparkan kembali ketika peristiwa diterima. Klien JavaScript tidak memerlukan informasi jenis asli. Mereka menemukan properti arg, berdasarkan namanya dalam metadata.

Contoh ini memperlihatkan cara menggunakan Objek> Windows.Foundation.EventHandler<di C#:

public sealed Class1
{
// Declare the event
public event EventHandler<Object> ToastCompletedEvent;

    // Raise the event
    public async void MakeToast(string message)
    {
        Toast toast = new Toast(message);
        // Fire the event from a background thread to allow this thread to continue
        Task.Run(() =>
        {
            if (ToastCompletedEvent != null)
            {
                OnToastCompleted(toast);
            }
        });
    }

    private void OnToastCompleted(Toast args)
    {
        var completedEvent = ToastCompletedEvent;
        if (completedEvent != null)
        {
            completedEvent(this, args);
        }
    }
}

Anda menggunakan peristiwa ini di sisi JavaScript seperti ini:

toastCompletedEventHandler: function (event) {
   var toastType = event.toast.toastType;
   document.getElementById("toasterOutput").innerHTML = "<p>Made " + toastType + " toast</p>";
}

(Opsi 3) Membuat proksi dan stub Anda sendiri

Untuk keuntungan performa potensial pada jenis peristiwa yang ditentukan pengguna yang memiliki informasi jenis yang sepenuhnya dipertahankan, Anda harus membuat objek proksi dan stub Anda sendiri dan menyematkannya dalam paket aplikasi Anda. Biasanya, Anda harus menggunakan opsi ini hanya dalam situasi yang jarang terjadi di mana kedua opsi lainnya tidak memadai. Selain itu, tidak ada jaminan bahwa opsi ini akan memberikan performa yang lebih baik daripada dua opsi lainnya. Performa aktual tergantung pada banyak faktor. Gunakan profiler Visual Studio atau alat pembuatan profil lainnya untuk mengukur performa aktual dalam aplikasi Anda dan menentukan apakah peristiwa tersebut sebenarnya merupakan penyempitan.

Sisa artikel ini menunjukkan cara menggunakan C# untuk membuat komponen Windows Runtime dasar, lalu menggunakan C++ untuk membuat DLL untuk proksi dan stub yang akan memungkinkan JavaScript menggunakan Windows.Foundation.TypedEventHandler<TSender, peristiwa TResult> yang dinaikkan oleh komponen dalam operasi asinkron. (Anda juga dapat menggunakan C++ atau Visual Basic untuk membuat komponen. Langkah-langkah yang terkait dengan pembuatan proksi dan stub sama.) Panduan ini didasarkan pada Membuat sampel komponen dalam proses Windows Runtime (C++/CX) dan membantu menjelaskan tujuannya.

Panduan ini memiliki bagian-bagian ini.

  • Di sini Anda akan membuat dua kelas Windows Runtime dasar. Satu kelas mengekspos peristiwa jenis Windows.Foundation.TypedEventHandler<TSender, TResult>, dan kelas lainnya adalah jenis yang dikembalikan ke JavaScript sebagai argumen untuk TValue. Kelas-kelas ini tidak dapat berkomunikasi dengan JavaScript hingga Anda menyelesaikan langkah-langkah selanjutnya.
  • Aplikasi ini mengaktifkan objek kelas utama, memanggil metode, dan menangani peristiwa yang dimunculkan oleh komponen Windows Runtime.
  • Ini diperlukan oleh alat yang menghasilkan kelas proksi dan stub.
  • Anda kemudian menggunakan file IDL untuk menghasilkan kode sumber C untuk proksi dan stub.
  • Daftarkan objek proxy-stub sehingga runtime COM dapat menemukannya, dan mereferensikan DLL proxy-stub dalam proyek aplikasi.

Untuk membuat komponen Windows Runtime

Di Visual Studio, pada bilah menu, pilih File > Proyek Baru. Dalam kotak dialog Proyek Baru , perluas JavaScript > Universal Windows lalu pilih Aplikasi Kosong. Beri nama proyek ToasterApplication lalu pilih tombol OK .

Tambahkan komponen C# Windows Runtime ke solusi: Di Penjelajah Solusi, buka menu pintasan untuk solusi, lalu pilih Tambahkan > Proyek Baru. Perluas Visual C# > Microsoft Store lalu pilih Komponen Runtime Windows. Beri nama proyek ToasterComponent lalu pilih tombol OK . ToasterComponent akan menjadi namespace layanan akar untuk komponen yang akan Anda buat di langkah-langkah selanjutnya.

Di Penjelajah Solusi, buka menu pintasan untuk solusi, lalu pilih Properti. Dalam kotak dialog Halaman Properti , pilih Properti Konfigurasi di panel kiri, lalu di bagian atas kotak dialog, atur Konfigurasi ke Debug dan Platform ke x86, x64, atau ARM. Pilih tombol OK.

Penting Platform = CPU apa pun tidak akan berfungsi karena tidak valid untuk DLL Win32 kode asli yang akan Anda tambahkan ke solusi nanti.

Di Penjelajah Solusi, ganti nama class1.cs menjadi ToasterComponent.cs sehingga cocok dengan nama proyek. Visual Studio secara otomatis mengganti nama kelas dalam file agar sesuai dengan nama file baru.

Dalam file .cs, tambahkan direktif penggunaan untuk namespace Windows.Foundation untuk membawa TypedEventHandler ke dalam cakupan.

Saat Anda memerlukan proksi dan stub, komponen Anda harus menggunakan antarmuka untuk mengekspos anggota publiknya. Di ToasterComponent.cs, tentukan antarmuka untuk pemanggang roti, dan satu lagi untuk Toast yang dihasilkan pemanggang roti.

Catatan Di C# Anda dapat melewati langkah ini. Sebagai gantinya, pertama-tama buat kelas, lalu buka menu pintasannya dan pilih Antarmuka Ekstrak Refaktor>. Dalam kode yang dihasilkan, berikan aksesibilitas publik antarmuka secara manual.

	public interface IToaster
        {
            void MakeToast(String message);
            event TypedEventHandler<Toaster, Toast> ToastCompletedEvent;

        }
        public interface IToast
        {
            String ToastType { get; }
        }

Antarmuka IToast memiliki string yang dapat diambil untuk menggambarkan jenis toast. Antarmuka IToaster memiliki metode untuk membuat toast, dan peristiwa untuk menunjukkan bahwa toast dibuat. Karena peristiwa ini mengembalikan bagian tertentu (yaitu, jenis) toast, peristiwa ini dikenal sebagai peristiwa yang ditik.

Selanjutnya, kita memerlukan kelas yang mengimplementasikan antarmuka ini, dan bersifat publik dan disegel sehingga dapat diakses dari aplikasi JavaScript yang akan Anda programkan nanti.

	public sealed class Toast : IToast
        {
            private string _toastType;

            public string ToastType
            {
                get
                {
                    return _toastType;
                }
            }
            internal Toast(String toastType)
            {
                _toastType = toastType;
            }

        }
        public sealed class Toaster : IToaster
        {
            public event TypedEventHandler<Toaster, Toast> ToastCompletedEvent;

            private void OnToastCompleted(Toast args)
            {
                var completedEvent = ToastCompletedEvent;
                if (completedEvent != null)
                {
                    completedEvent(this, args);
                }
            }

            public void MakeToast(string message)
            {
                Toast toast = new Toast(message);
                // Fire the event from a thread-pool thread to enable this thread to continue
                Windows.System.Threading.ThreadPool.RunAsync(
                (IAsyncAction action) =>
                {
                    if (ToastCompletedEvent != null)
                    {
                        OnToastCompleted(toast);
                    }
                });
           }
        }

Dalam kode sebelumnya, kita membuat roti panggang dan kemudian memutar item kerja kumpulan utas untuk mengaktifkan pemberitahuan. Meskipun IDE mungkin menyarankan agar Anda menerapkan kata kunci tunggu ke panggilan asinkron, itu tidak diperlukan dalam hal ini karena metode tidak melakukan pekerjaan apa pun yang tergantung pada hasil operasi.

Catatan Panggilan asinkron dalam kode sebelumnya menggunakan ThreadPool.RunAsync hanya untuk menunjukkan cara sederhana untuk menembakkan peristiwa pada utas latar belakang. Anda dapat menulis metode khusus ini seperti yang ditunjukkan dalam contoh berikut, dan itu akan berfungsi dengan baik karena penjadwal Tugas .NET secara otomatis melakukan marsekal asinkron/menunggu panggilan kembali ke utas UI.  

	public async void MakeToast(string message)
    {
        Toast toast = new Toast(message)
        await Task.Delay(new Random().Next(1000));
        OnToastCompleted(toast);
    }

Jika Anda membangun proyek sekarang, proyek harus dibangun dengan bersih.

Untuk memprogram aplikasi JavaScript

Sekarang kita dapat menambahkan tombol ke aplikasi JavaScript untuk menyebabkannya menggunakan kelas yang baru saja kita tentukan untuk membuat toast. Sebelum melakukan ini, kita harus menambahkan referensi ke proyek ToasterComponent yang baru saja kita buat. Di Penjelajah Solusi, buka menu pintasan untuk proyek ToasterApplication, pilih Tambahkan > Referensi, lalu pilih tombol Tambahkan Referensi Baru . Dalam kotak dialog Tambahkan Referensi, di panel kiri di bawah Solusi, pilih proyek komponen, lalu di panel tengah, pilih ToasterComponent. Pilih tombol OK.

Di Penjelajah Solusi, buka menu pintasan untuk proyek ToasterApplication lalu pilih Atur sebagai Proyek Startup.

Di akhir file default.js, tambahkan namespace layanan untuk berisi fungsi untuk memanggil komponen dan dipanggil kembali olehnya. Namespace akan memiliki dua fungsi, satu untuk membuat roti panggang dan satu untuk menangani peristiwa lengkap roti panggang. Implementasi makeToast membuat objek Toaster, mendaftarkan penanganan aktivitas, dan membuat toast. Sejauh ini, penanganan aktivitas tidak banyak, seperti yang ditunjukkan di sini:

	WinJS.Namespace.define("ToasterApplication"), {
       makeToast: function () {

          var toaster = new ToasterComponent.Toaster();
          //toaster.addEventListener("ontoastcompletedevent", ToasterApplication.toastCompletedEventHandler);
          toaster.ontoastcompletedevent = ToasterApplication.toastCompletedEventHandler;
          toaster.makeToast("Peanut Butter");
       },

       toastCompletedEventHandler: function(event) {
           // The sender of the event (the delegate's first type parameter)
           // is mapped to event.target. The second argument of the delegate
           // is contained in event, which means in this case event is a
           // Toast class, with a toastType string.
           var toastType = event.toastType;

           document.getElementById('toastOutput').innerHTML = "<p>Made " + toastType + " toast</p>";
        },
    });

Fungsi makeToast harus dikaitkan dengan tombol. Perbarui default.html untuk menyertakan tombol dan beberapa ruang untuk menghasilkan hasil pembuatan roti panggang:

    <body>
        <h1>Click the button to make toast</h1>
        <button onclick="ToasterApplication.makeToast()">Make Toast!</button>
        <div id="toasterOutput">
            <p>No Toast Yet...</p>
        </div>
    </body>

Jika kami tidak menggunakan TypedEventHandler, kami sekarang dapat menjalankan aplikasi di komputer lokal dan mengklik tombol untuk membuat roti panggang. Tetapi di aplikasi kami, tidak ada yang terjadi. Untuk mengetahui alasannya, mari kita debug kode terkelola yang mengaktifkan ToastCompletedEvent. Hentikan proyek, lalu pada bilah menu, pilih Debug > properti Aplikasi Pemanggang Toaster. Ubah Jenis Debugger menjadi Hanya Terkelola. Sekali lagi pada bilah menu, pilih Pengecualian Debug>, lalu pilih Pengecualian Runtime Bahasa Umum.

Sekarang jalankan aplikasi dan klik tombol buat roti panggang. Debugger menangkap pengecualian cast yang tidak valid. Meskipun tidak jelas dari pesannya, pengecualian ini terjadi karena proksi hilang untuk antarmuka tersebut.

proksi hilang

Langkah pertama dalam membuat proksi dan stub untuk komponen adalah menambahkan ID unik atau GUID ke antarmuka. Namun, format GUID yang akan digunakan berbeda tergantung pada apakah Anda mengkoding dalam C#, Visual Basic, atau bahasa .NET lainnya, atau di C++.

Untuk menghasilkan GUID untuk antarmuka komponen (C# dan bahasa .NET lainnya)

Pada bilah menu, pilih Alat > Buat GUID. Dalam kotak dialog, pilih 5. [Guid("xxxxxxxxx-xxxx... xxxx")]. Pilih tombol GUID Baru lalu pilih tombol Salin.

alat generator guid

Kembali ke definisi antarmuka, lalu tempelkan GUID baru tepat sebelum antarmuka IToaster, seperti yang ditunjukkan dalam contoh berikut. (Jangan gunakan GUID dalam contoh. Setiap antarmuka unik harus memiliki GUID sendiri.)

[Guid("FC198F74-A808-4E2A-9255-264746965B9F")]
        public interface IToaster...

Tambahkan direktif penggunaan untuk namespace System.Runtime.InteropServices.

Ulangi langkah-langkah ini untuk antarmuka IToast.

Untuk menghasilkan GUID untuk antarmuka komponen (C++)

Pada bilah menu, pilih Alat > Buat GUID. Dalam kotak dialog, pilih 3. GUID struct const statis = {...}. Pilih tombol GUID Baru lalu pilih tombol Salin.

Tempel GUID tepat sebelum definisi antarmuka IToaster. Setelah Anda menempelkan, GUID harus menyerupai contoh berikut. (Jangan gunakan GUID dalam contoh. Setiap antarmuka unik harus memiliki GUID sendiri.)

// {F8D30778-9EAF-409C-BCCD-C8B24442B09B}
    static const GUID <<name>> = { 0xf8d30778, 0x9eaf, 0x409c, { 0xbc, 0xcd, 0xc8, 0xb2, 0x44, 0x42, 0xb0, 0x9b } };

Tambahkan direktif penggunaan untuk Windows.Foundation.Metadata untuk membawa GuidAttribute ke dalam cakupan.

Sekarang konversi GUID const secara manual ke GuidAttribute sehingga diformat seperti yang ditunjukkan dalam contoh berikut. Perhatikan bahwa kurung kurawal diganti dengan tanda kurung dan tanda kurung, dan titik koma berikutnya dihapus.

// {E976784C-AADE-4EA4-A4C0-B0C2FD1307C3}
    [GuidAttribute(0xe976784c, 0xaade, 0x4ea4, 0xa4, 0xc0, 0xb0, 0xc2, 0xfd, 0x13, 0x7, 0xc3)]
    public interface IToaster
    {...

Ulangi langkah-langkah ini untuk antarmuka IToast.

Sekarang setelah antarmuka memiliki ID unik, kita dapat membuat file IDL dengan mengumpankan file .winmd ke dalam alat baris perintah winmdidl, dan kemudian menghasilkan kode sumber C untuk proksi dan stub dengan mengumpankan file IDL tersebut ke alat baris perintah MIDL. Visual Studio melakukan ini untuk kami jika kami membuat peristiwa pasca-build seperti yang ditunjukkan pada langkah-langkah berikut.

Untuk menghasilkan kode sumber proksi dan stub

Untuk menambahkan peristiwa pasca-build kustom, di Penjelajah Solusi, buka menu pintasan untuk proyek ToasterComponent lalu pilih Properti. Di panel kiri halaman properti, pilih Bangun Peristiwa, lalu pilih tombol Edit Pasca-build. Tambahkan perintah berikut ke baris perintah pasca-build. (File batch harus dipanggil terlebih dahulu untuk mengatur variabel lingkungan untuk menemukan alat winmdidl.)

call "$(DevEnvDir)..\..\vc\vcvarsall.bat" $(PlatformName)
winmdidl /outdir:output "$(TargetPath)"
midl /metadata_dir "%WindowsSdkDir%References\CommonConfiguration\Neutral" /iid "$(ProjectDir)$(TargetName)_i.c" /env win32 /h "$(ProjectDir)$(TargetName).h" /winmd "Output\$(TargetName).winmd" /W1 /char signed /nologo /winrt /dlldata "$(ProjectDir)dlldata.c" /proxy "$(ProjectDir)$(TargetName)_p.c" "Output\$(TargetName).idl"

Penting Untuk konfigurasi proyek ARM atau x64, ubah parameter MIDL /env menjadi x64 atau arm32.

Untuk memastikan file IDL diregenerasi setiap kali file .winmd diubah, ubah Jalankan peristiwa pasca-build menjadi Saat build memperbarui output proyek. Halaman properti Build Events harus menyerupai ini: membangun peristiwa

Bangun kembali solusi untuk menghasilkan dan mengkompilasi IDL.

Anda dapat memverifikasi bahwa MIDL mengompilasi solusi dengan benar dengan mencari ToasterComponent.h, ToasterComponent_i.c, ToasterComponent_p.c, dan dlldata.c di direktori proyek ToasterComponent.

Untuk mengkompilasi kode proksi dan stub ke dalam DLL

Sekarang setelah Anda memiliki file yang diperlukan, Anda dapat mengkompilasinya untuk menghasilkan DLL, yang merupakan file C++. Untuk mempermudah hal ini, tambahkan proyek baru untuk mendukung pembangunan proksi. Buka menu pintasan untuk solusi ToasterApplication lalu pilih Tambahkan > Proyek Baru. Di panel kiri kotak dialog Proyek Baru , perluas Visual C++ > Windows > Univeral Windows, lalu di panel tengah, pilih DLL (aplikasi UWP). (Perhatikan bahwa ini BUKAN proyek Komponen Runtime Windows C++.) Beri nama Proksi proyek lalu pilih tombol OK . File-file ini akan diperbarui oleh peristiwa pasca-build ketika sesuatu berubah di kelas C#.

Secara default, proyek Proksi menghasilkan file header .h dan file C++ .cpp. Karena DLL dibangun dari file yang dihasilkan dari MIDL, file .h dan .cpp tidak diperlukan. Di Penjelajah Solusi, buka menu pintasan untuk mereka, pilih Hapus, lalu konfirmasi penghapusan.

Sekarang setelah proyek kosong, Anda dapat menambahkan kembali file yang dihasilkan MIDL. Buka menu pintasan untuk proyek Proksi, lalu pilih Tambahkan > Item yang Ada. Dalam kotak dialog, navigasikan ke direktori proyek ToasterComponent dan pilih file-file ini: ToasterComponent.h, ToasterComponent_i.c, ToasterComponent_p.c, dan file dlldata.c. Pilih tombol Tambahkan.

Dalam proyek Proksi, buat file .def untuk menentukan ekspor DLL yang dijelaskan dalam dlldata.c. Buka menu pintasan untuk proyek, lalu pilih Tambahkan > Item Baru. Di panel kiri kotak dialog, pilih Kode lalu di panel tengah, pilih file Module-Definition. Beri nama file proxies.def lalu pilih tombol Tambahkan . Buka file .def ini dan ubah untuk menyertakan EKSPOR yang ditentukan dalam dlldata.c:

EXPORTS
    DllCanUnloadNow         PRIVATE
    DllGetClassObject       PRIVATE

Jika Anda membangun proyek sekarang, proyek akan gagal. Untuk mengkompilasi proyek ini dengan benar, Anda harus mengubah cara proyek dikompilasi dan ditautkan. Di Penjelajah Solusi, buka menu pintasan untuk proyek Proksi lalu pilih Properti. Ubah halaman properti sebagai berikut.

Di panel kiri, pilih C/C++ > Prapemroses, lalu di panel kanan, pilih Definisi Praprosesor, pilih tombol panah bawah, lalu pilih Edit. Tambahkan definisi ini dalam kotak:

WIN32;_WINDOWS

Di bawah C/C++ > Header Yang Telah Dikompilasi Sebelumnya, ubah Header yang Telah Dikompilasi sebelumnya menjadi Tidak Menggunakan Header yang Telah Dikompilasi sebelumnya, lalu pilih tombol Terapkan .

Di bawah Linker > General, ubah Abaikan Impor Pustaka ke Yes, lalu pilih tombol Terapkan .

Di bawah Input Linker>, pilih Dependensi Tambahan, pilih tombol panah bawah, lalu pilih Edit. Tambahkan teks ini dalam kotak:

rpcrt4.lib;runtimeobject.lib

Jangan tempelkan pustaka ini langsung ke dalam baris daftar. Gunakan kotak Edit untuk memastikan bahwa MSBuild di Visual Studio akan mempertahankan dependensi tambahan yang benar.

Ketika Anda telah membuat perubahan ini, pilih tombol OK dalam kotak dialog Halaman Properti .

Selanjutnya, ambil dependensi pada proyek ToasterComponent. Ini memastikan bahwa Toaster akan dibangun sebelum proyek proksi dibangun. Ini diperlukan karena proyek Toaster bertanggung jawab untuk menghasilkan file untuk membangun proksi.

Buka menu pintasan untuk proyek Proksi lalu pilih Dependensi Proyek. Pilih kotak centang untuk menunjukkan bahwa proyek Proksi bergantung pada proyek ToasterComponent, untuk memastikan bahwa Visual Studio menyusunnya dalam urutan yang benar.

Verifikasi bahwa solusi dibangun dengan benar dengan memilih Build > Rebuild Solution pada bilah menu Visual Studio.

Untuk mendaftarkan proksi dan stub

Di proyek ToasterApplication, buka menu pintasan untuk package.appxmanifest lalu pilih Buka Dengan. Dalam kotak dialog Buka Dengan, pilih Editor Teks XML lalu pilih tombol OK . Kita akan menempelkan di beberapa XML yang menyediakan pendaftaran ekstensi windows.activatableClass.proxyStub dan yang didasarkan pada GUID di proksi. Untuk menemukan GUID yang akan digunakan dalam file .appxmanifest, buka ToasterComponent_i.c. Temukan entri yang menyerupai entri dalam contoh berikut. Perhatikan juga definisi untuk IToast, IToaster, dan antarmuka ketiga—penanganan aktivitas berjenis yang memiliki dua parameter: Pemanggang Roti dan Toast. Ini cocok dengan peristiwa yang ditentukan di kelas Toaster. Perhatikan bahwa GUID untuk IToast dan IToaster cocok dengan GUID yang ditentukan pada antarmuka dalam file C#. Karena antarmuka penanganan aktivitas yang di ketik dibuat secara otomatis, GUID untuk antarmuka ini juga dibuat secara otomatis.

MIDL_DEFINE_GUID(IID, IID___FITypedEventHandler_2_ToasterComponent__CToaster_ToasterComponent__CToast,0x1ecafeff,0x1ee1,0x504a,0x9a,0xf5,0xa6,0x8c,0x6f,0xb2,0xb4,0x7d);

MIDL_DEFINE_GUID(IID, IID___x_ToasterComponent_CIToast,0xF8D30778,0x9EAF,0x409C,0xBC,0xCD,0xC8,0xB2,0x44,0x42,0xB0,0x9B);

MIDL_DEFINE_GUID(IID, IID___x_ToasterComponent_CIToaster,0xE976784C,0xAADE,0x4EA4,0xA4,0xC0,0xB0,0xC2,0xFD,0x13,0x07,0xC3);

Sekarang kita menyalin GUID, menempelkannya di package.appxmanifest dalam node yang kita tambahkan dan beri nama Extensions, lalu memformat ulang. Entri manifes menyerupai contoh berikut—tetapi sekali lagi, ingatlah untuk menggunakan GUID Anda sendiri. Perhatikan bahwa GUID ClassId dalam XML sama dengan ITypedEventHandler2. Ini karena GUID adalah yang pertama yang tercantum di ToasterComponent_i.c. GUID di sini tidak peka huruf besar/kecil. Alih-alih memformat ulang GUID secara manual untuk IToast dan IToaster, Anda dapat kembali ke definisi antarmuka dan mendapatkan nilai GuidAttribute, yang memiliki format yang benar. Di C++, ada GUID yang diformat dengan benar di komentar. Bagaimanapun, Anda harus memformat ulang GUID yang digunakan secara manual untuk ClassId dan penanganan aktivitas.

	  <Extensions> <!--Use your own GUIDs!!!-->
        <Extension Category="windows.activatableClass.proxyStub">
          <ProxyStub ClassId="1ecafeff-1ee1-504a-9af5-a68c6fb2b47d">
            <Path>Proxies.dll</Path>
            <Interface Name="IToast" InterfaceId="F8D30778-9EAF-409C-BCCD-C8B24442B09B"/>
            <Interface Name="IToaster"  InterfaceId="E976784C-AADE-4EA4-A4C0-B0C2FD1307C3"/>  
            <Interface Name="ITypedEventHandler_2_ToasterComponent__CToaster_ToasterComponent__CToast" InterfaceId="1ecafeff-1ee1-504a-9af5-a68c6fb2b47d"/>
          </ProxyStub>      
        </Extension>
      </Extensions>

Tempelkan simpul XML Ekstensi sebagai anak langsung dari simpul Paket, dan serekan, misalnya, simpul Sumber Daya.

Sebelum melanjutkan, penting untuk memastikan bahwa:

  • ProxyStub ClassId diatur ke GUID pertama dalam file ToasterComponent_i.c. Gunakan GUID pertama yang ditentukan dalam file ini untuk classId. (Ini mungkin sama dengan GUID untuk ITypedEventHandler2.)
  • Jalur adalah jalur relatif paket dari biner proksi. (Dalam panduan ini, proxies.dll berada di folder yang sama dengan ToasterApplication.winmd.)
  • GUID dalam format yang benar. (Ini mudah untuk salah.)
  • ID antarmuka dalam manifes cocok dengan IID dalam file ToasterComponent_i.c.
  • Nama antarmuka unik dalam manifes. Karena ini tidak digunakan oleh sistem, Anda dapat memilih nilai. Ini adalah praktik yang baik untuk memilih nama antarmuka yang dengan jelas cocok dengan antarmuka yang telah Anda tentukan. Untuk antarmuka yang dihasilkan, nama harus menunjukkan antarmuka yang dihasilkan. Anda dapat menggunakan file ToasterComponent_i.c untuk membantu Anda menghasilkan nama antarmuka.

Jika Anda mencoba menjalankan solusi sekarang, Anda akan mendapatkan kesalahan bahwa proxies.dll bukan bagian dari payload. Buka menu pintasan untuk folder Referensi di proyek ToasterApplication lalu pilih Tambahkan Referensi. Pilih kotak centang di samping proyek Proksi. Selain itu, pastikan bahwa kotak centang di samping ToasterComponent juga dipilih. Pilih tombol OK.

Proyek sekarang harus dibangun. Jalankan proyek dan verifikasi bahwa Anda dapat membuat roti panggang.