Catatan
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba masuk atau mengubah direktori.
Akses ke halaman ini memerlukan otorisasi. Anda dapat mencoba mengubah direktori.
Topik ini adalah yang kedua dalam serangkaian artikel yang menunjukkan proses peningkatan proyek Visual Studio C++ yang lebih lama ke versi terbaru Visual Studio. Contoh kode dalam topik ini terakhir dikompilasi dengan Visual Studio 2005.
COMSpy
COMSpy adalah program yang memantau dan mencatat aktivitas komponen layanan pada komputer. Komponen berlayanan adalah komponen COM+ yang berjalan pada sistem dan dapat digunakan oleh komputer pada jaringan yang sama. Mereka dikelola oleh fungsionalitas Layanan Komponen di windows Panel Kontrol.
Langkah 1. Mengonversi file proyek
File proyek mengonversi dengan mudah dan menghasilkan laporan migrasi. Ada beberapa entri dalam laporan yang memberi tahu kami tentang masalah yang mungkin perlu kami tangani. Berikut adalah salah satu masalah yang dilaporkan (perhatikan bahwa sepanjang topik ini, pesan kesalahan terkadang dipersingkat untuk keterbacaan, misalnya untuk menghapus jalur lengkap):
ComSpyAudit\ComSpyAudit.vcproj: MSB8012: $(TargetPath) ('C:\Users\UserName\Desktop\spy\spy\ComSpyAudit\.\XP32_DEBUG\ComSpyAudit.dll') does not match the Librarian's OutputFile property value '.\XP32_DEBUG\ComSpyAudit.dll' ('C:\Users\UserName\Desktop\spy\spy\XP32_DEBUG\ComSpyAudit.dll') in project configuration 'Unicode Debug|Win32'. This may cause your project to build incorrectly. To correct this, please make sure that $(TargetPath) property value matches the value specified in %(Lib.OutputFile).
Salah satu masalah yang sering terjadi dalam memutakhirkan proyek adalah pengaturan Linker OutputFile dalam kotak dialog properti proyek mungkin perlu ditinjau. Untuk proyek sebelum Visual Studio 2010, OutputFile adalah salah satu pengaturan yang bermasalah dengan wizard konversi otomatis, jika diatur ke nilai non-standar. Dalam hal ini, jalur untuk file output diatur ke folder non-standar, XP32_DEBUG. Untuk mengetahui lebih lanjut tentang kesalahan ini, kami berkonsultasi dengan posting blog yang terkait dengan peningkatan proyek Visual Studio 2010, yang merupakan peningkatan yang melibatkan perubahan dari vcbuild ke msbuild, perubahan signifikan. Menurut informasi ini, nilai default untuk pengaturan File Output saat Anda membuat proyek baru adalah $(OutDir)$(TargetName)$(TargetExt), tetapi ini tidak diatur selama konversi karena tidak mungkin bagi proyek yang dikonversi untuk memverifikasi bahwa semuanya benar. Namun, mari kita coba masukkan itu untuk OutputFile dan lihat apakah itu berfungsi. Itu, sehingga kita bisa melanjutkan. Jika tidak ada alasan khusus untuk menggunakan folder output nonstandar, sebaiknya gunakan lokasi standar. Dalam hal ini, kami memilih untuk meninggalkan lokasi output sebagai non-standar selama proses porting dan peningkatan; $(OutDir) menyelesaikan ke folder XP32_DEBUG di Konfigurasi debug dan folder ReleaseU untuk konfigurasi Rilis .
Langkah 2. Mendapatkannya untuk membangun
Membangun proyek port, sejumlah kesalahan dan peringatan terjadi.
ComSpyCtl tidak dikompilasi karena kesalahan pengkompilasi ini:
atlcom.h(611): error C2664: 'HRESULT CComSpy::IPersistStreamInit_Save(LPSTREAM,BOOL,ATL::ATL_PROPMAP_ENTRY *)': cannot convert argument 3 from 'const ATL::ATL_PROPMAP_ENTRY *' to 'ATL::ATL_PROPMAP_ENTRY *'atlcom.h(611): note: Conversion loses qualifiersatlcom.h(608): note: while compiling class template member function 'HRESULT ATL::IPersistStreamInitImpl<CComSpy>::Save(LPSTREAM,BOOL)'\spy\spy\comspyctl\ccomspy.h(28): note: see reference to class template instantiation 'ATL::IPersistStreamInitImpl<CComSpy>' being compiled
Kesalahan mereferensikan Save metode pada IPersistStreamInitImpl kelas di atlcom.h.
STDMETHOD(Save)(_Inout_ LPSTREAM pStm, _In_ BOOL fClearDirty)
{
T* pT = static_cast<T*>(this);
ATLTRACE(atlTraceCOM, 2, _T("IPersistStreamInitImpl::Save\n"));
return pT->IPersistStreamInit_Save(pStm, fClearDirty, T::GetPropertyMap());
}
Masalahnya adalah bahwa konversi yang diterima versi pengkompilasi yang lebih lama tidak lagi valid. Agar sesuai dengan standar C++, beberapa kode yang sebelumnya diizinkan tidak lagi diizinkan. Dalam hal ini, tidak aman untuk meneruskan pointer non-const ke fungsi yang mengharapkan penunjuk const. Solusinya adalah menemukan deklarasi IPersistStreamInit_Save pada CComSpy kelas dan menambahkan pengubah const ke parameter ketiga.
HRESULT CComSpy::IPersistStreamInit_Save(LPSTREAM pStm, BOOL /* fClearDirty */, const ATL_PROPMAP_ENTRY* pMap)
Dan perubahan IPersistStreamInit_Loadserupa dengan .
HRESULT IPersistStreamInit_Load(LPSTREAM pStm, const ATL_PROPMAP_ENTRY* pMap);
Kesalahan berikutnya berkaitan dengan pendaftaran.
error MSB3073: The command "regsvr32 /s /c "C:\Users\username\Desktop\spy\spy\ComSpyCtl\.\XP32_DEBUG\ComSpyCtl.lib"error MSB3073: echo regsvr32 exec. time > ".\XP32_DEBUG\regsvr32.trg"error MSB3073:error MSB3073: :VCEnd" exited with code 3.
Kami tidak memerlukan perintah pendaftaran pasca-build ini lagi. Sebagai gantinya, kita cukup menghapus perintah build kustom, dan menentukan di pengaturan Linker untuk mendaftarkan output.
Berurusan dengan peringatan
Proyek ini menghasilkan peringatan linker berikut.
warning LNK4075: ignoring '/EDITANDCONTINUE' due to '/SAFESEH' specification
Opsi /SAFESEH pengkompilasi tidak berguna dalam mode debug, yaitu kapan /EDITANDCONTINUE berguna, jadi perbaikan di sini adalah menonaktifkan /SAFESEH untuk konfigurasi Debug saja. Untuk melakukan ini dalam dialog properti, kita membuka dialog properti untuk proyek yang menghasilkan kesalahan ini, dan pertama-tama kita mengatur Konfigurasi ke Debug (sebenarnya Debug Unicode), lalu di bagian Linker Advanced, reset properti Image Has Safe Exception Handlers ke Tidak ()./SAFESEH:NO
Kompiler memperingatkan kita yang PROP_ENTRY_EX tidak digunakan lagi. Ini tidak aman dan pengganti yang direkomendasikan adalah PROP_ENTRY_TYPE_EX.
BEGIN_PROPERTY_MAP(CComSpy)
PROP_ENTRY_EX( "LogFile", DISPID_LOGFILE, CLSID_ComSpyPropPage, IID_IComSpy)
PROP_ENTRY_EX( "ShowGridLines", DISPID_GRIDLINES, CLSID_ComSpyPropPage, IID_IComSpy)
PROP_ENTRY_EX( "Audit", DISPID_AUDIT, CLSID_ComSpyPropPage, IID_IComSpy)
PROP_ENTRY_EX( "ColWidth", DISPID_COLWIDTH, CLSID_ComSpyPropPage, IID_IComSpy)
PROP_PAGE(CLSID_StockFontPage)
END_PROPERTY_MAP()
Kami mengubah kode di ccomspy.h dengan demikian, menambahkan jenis COM yang sesuai.
BEGIN_PROPERTY_MAP(CComSpy)
PROP_ENTRY_TYPE_EX( "LogFile", DISPID_LOGFILE, CLSID_ComSpyPropPage, IID_IComSpy, VT_BSTR)
PROP_ENTRY_TYPE_EX( "ShowGridLines", DISPID_GRIDLINES, CLSID_ComSpyPropPage, IID_IComSpy, VT_BOOL)
PROP_ENTRY_TYPE_EX( "Audit", DISPID_AUDIT, CLSID_ComSpyPropPage, IID_IComSpy, VT_BOOL)
PROP_ENTRY_TYPE_EX( "ColWidth", DISPID_COLWIDTH, CLSID_ComSpyPropPage, IID_IComSpy, VT_UINT)
PROP_PAGE(CLSID_StockFontPage)
END_PROPERTY_MAP()
Kami turun ke beberapa peringatan terakhir, yang juga disebabkan oleh pemeriksaan kesuaian kompilator yang lebih ketat:
\spy\comspyctl\usersub.h(70): warning C4457: declaration of 'var' hides function parameter\spy\comspyctl\usersub.h(48): note: see declaration of 'var'\spy\comspyctl\usersub.h(94): warning C4018: '<': signed/unsigned mismatch ComSpy.cpp\spy\comspyctl\comspy.cpp(186): warning C4457: declaration of 'bHandled' hides function parameter\spy\spy\comspyctl\comspy.cpp(177): note: see declaration of 'bHandled'
Peringatan C4018 berasal dari kode ini:
for (i=0;i<lCount;i++)
CoTaskMemFree(pKeys[i]);
Masalahnya adalah yang i dinyatakan sebagai UINT dan lCount dinyatakan sebagai long, oleh karena itu ketidakcocokan yang ditandatangani/tidak ditandatangani. Akan tidak nyaman untuk mengubah jenis lCount menjadi UINT, karena mendapatkan nilainya dari IMtsEventInfo::get_Count, yang menggunakan jenis long, dan tidak dalam kode pengguna. Jadi kita menambahkan cast ke kode. Pemeran gaya C akan melakukan untuk cast numerik seperti ini, tetapi static_cast adalah gaya yang direkomendasikan.
for (i=0;i<static_cast<UINT>(lCount);i++)
CoTaskMemFree(pKeys[i]);
Peringatan tersebut adalah kasus di mana variabel dideklarasikan dalam fungsi yang memiliki parameter dengan nama yang sama, yang mengarah ke kode yang berpotensi membingungkan. Kami memperbaikinya dengan mengubah nama variabel lokal.
Langkah 3. Pengujian dan penelusuran kesalahan
Kami menguji aplikasi terlebih dahulu dengan menjalankan berbagai menu dan perintah, lalu menutup aplikasi. Satu-satunya masalah yang dicatat adalah pernyataan debug setelah menutup aplikasi. Masalah muncul di destructor untuk CWindowImpl, kelas CSpyCon dasar objek, komponen COM utama aplikasi. Kegagalan pernyataan terjadi dalam kode berikut di atlwin.h.
virtual ~CWindowImplRoot()
{
#ifdef _DEBUG
if(m_hWnd != NULL)// should be cleared in WindowProc
{
ATLTRACE(atlTraceWindowing, 0, _T("ERROR - Object deleted before window was destroyed\n"));
ATLASSERT(FALSE);
}
#endif //_DEBUG
}
hWnd biasanya diatur ke nol dalam WindowProc fungsi, tetapi itu tidak terjadi karena alih-alih default WindowProc, handler kustom dipanggil untuk pesan Windows (WM_SYSCOMMAND) yang menutup jendela. Handler kustom tidak mengatur ke hWnd nol. Melihat kode serupa di kelas MFC CWnd , menunjukkan bahwa ketika jendela sedang dihancurkan, OnNcDestroy dipanggil, dan di MFC, dokumentasi menyarankan bahwa ketika mengambil alih CWnd::OnNcDestroy, basis NcDestroy harus dipanggil untuk memastikan bahwa operasi pembersihan yang tepat terjadi, termasuk memisahkan handel jendela dari jendela, atau dengan kata lain, mengatur hWnd ke nol. Pernyataan ini mungkin telah dipicu dalam versi asli sampel juga, karena kode pernyataan yang sama ada di versi lama atlwin.h.
Untuk menguji fungsionalitas aplikasi, kami membuat Komponen Serviced menggunakan templat proyek ATL, memilih untuk menambahkan dukungan COM+ di wizard proyek ATL. Jika Anda belum bekerja dengan komponen berlayanan sebelumnya, tidak sulit untuk membuatnya dan mendapatkannya terdaftar dan tersedia di sistem atau jaringan untuk digunakan aplikasi lain. Aplikasi COM Spy dirancang untuk memantau aktivitas komponen layanan sebagai bantuan diagnostik.
Kemudian kami menambahkan kelas, memilih Objek ATL, dan menentukan nama objek sebagai Dog. Kemudian di dog.h dan dog.cpp, kami menambahkan implementasinya.
STDMETHODIMP CDog::Wag(LONG* lDuration)
{
// TODO: Add your implementation code here
*lDuration = 100l;
return S_OK;
}
Selanjutnya, kami membangun dan mendaftarkannya (Anda harus menjalankan Visual Studio sebagai Administrator), dan mengaktifkannya menggunakan aplikasi Komponen Layanan di Windows Panel Kontrol. Kami membuat proyek C# Formulir Windows, menyeret tombol ke formulir dari kotak alat, dan mengeklik dua kali itu ke penanganan aktivitas klik. Kami menambahkan kode berikut untuk membuat instans Dog komponen.
private void button1_Click(object sender, EventArgs e)
{
ATLProjectLib.Dog dog1 = new ATLProjectLib.Dog();
dog1.Wag();
}
Ini berjalan tanpa masalah, dan dengan COM Spy aktif dan berjalan dan dikonfigurasi untuk memantau Dog komponen, banyak data muncul yang menunjukkan aktivitas.
Lihat juga
Porting dan Peningkatan: Contoh dan Studi Kasus
Contoh Berikutnya: Spy++
Contoh Sebelumnya: Coretan MFC