#include "pch.h" #include "RAWinRT.WRL.h" using namespace Microsoft::WRL::Wrappers; using namespace Microsoft::WRL; using namespace ABI::RAWinRT::WRL; using namespace ABI::Windows::ApplicationModel::Background; class ABI::RAWinRT::WRL::TestTask : public RuntimeClass < RuntimeClassFlags<WinRt>, IBackgroundTask > { InspectableClass(RuntimeClass_RAWinRT_WRL_TestTask, BaseTrust); public: STDMETHODIMP Run(IBackgroundTaskInstance *taskInstance) override { return S_OK; } }; ActivatableClass(TestTask);
ãããã®äžå¯è§£ãªãã¯ãããã³ãã¬ãŒããã©ã€ãã©ãªé¢æ°ã
ãããŠãç§ã¯æãåçŽãªãã®ããå§ããããšã«ããŸããã Visual C ++ã§ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®åäžã®ãã¯ã©ã¹ããæã€Windowsã©ã³ã¿ã€ã ã³ã³ããŒãã³ããèšè¿°ããŸãã
ããªããããããæ¥ããã®ã«èå³ããããªããç«ãžããããã
ã³ã³ããŒãã³ããããžã§ã¯ãã®äœæãšã«ã¹ã¿ãã€ãº
æåã«ãVisual Studio 2013 IDEã§ç©ºã®ãœãªã¥ãŒã·ã§ã³ãã¡ã€ã«ãäœæããWindowsã¹ãã¢ã¢ããªã±ãŒã·ã§ã³ã®DLLãããžã§ã¯ããè¿œå ããŸããã
ãããžã§ã¯ãã§ã¯ãNMSPC.TestComponentãšããååãéžæããŸãããããã§ãNMSPCã¯åå空éã§ãã ãã®ãããªåœåã¯ããããžã§ã¯ããäœæããéã®ããªãäžè¬çãªæ £è¡ã§ããããããã¢ç®çã§ãããè¡ããŸããã ãŸããããã©ã«ãã®ããŒã ã¹ããŒã¹ãNMSPC_TestComponentãã察å¿ãããããžã§ã¯ãåã«å€æŽããŸããã
ãã¡ã€ã«ã«ã€ããŠã¯ãçãååã奜ããããããããŒãã¡ã€ã«ãšãœãŒã¹ãã¡ã€ã«ã®ååãTetsComponentã«å€æŽããŸããã ã³ãŒãã«ã³ã³ããŒãã³ããå®è£ ããåã«ãããã€ãã®è¿œå ãã¡ã€ã«ãè¿œå ããŸããã TestComponent.def-åçã©ã€ãã©ãªã«ãã£ãŠãšã¯ã¹ããŒããããé¢æ°ãå®çŸ©ããããã®ãã¡ã€ã«ãTestComponent.idl-ã€ã³ã¿ãŒãã§ã€ã¹ãèšè¿°ããããã®ãã¡ã€ã«
ãããã®ãã¡ã€ã«ããããžã§ã¯ãã«è¿œå ããããæ§æãéå§ããŸããã åæ§æã®èšå®ãåå¥ã«å€æŽããªãããã«ããã«ã¯ããã¹ãŠã®æ§æãšãã©ãããã©ãŒã ãéžæããŠããã©ã¡ãŒã¿ãŒã®ç·šéã«é²ãã ãã§ååã§ãã ã¢ã©ãŒãã¬ãã«èšå®ãæå®ãããã¡ã¿ããŒã¿çæãªãã·ã§ã³ãæå®ãããMIDLã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããããããŒãã¡ã€ã«ã®ååãã³ãã¬ãŒããå€æŽãããruntimeobject.libã®ã¬ã€ã¢ãŠããè¿œå ããããµãã·ã¹ãã ãéžæãããŸããã
次ã«ããããžã§ã¯ããæ§ç¯ããããã®è¿œå ã¹ããããèšå®ããŸããã 圌ã«ã€ããŠããå°ã説æããŸãã
ãã®ã¹ãããã¯ããããžã§ã¯ãã¡ã¿ããŒã¿ã®æ£ããçæãç®çãšããŠããŸãã ã³ãã³ãã©ã€ã³ã¯æ¬¡ã®ããã«èšå®ãããŸããã
del "$(OutDir)$(TargetName).winmd" && mdmerge -partial -i "$(OutDir)." -o "$(OutDir)Output" -metadata_dir "$(WindowsSDK_MetadataPath)" && del "$(OutDir)*.winmd" && copy /y "$(OutDir)Output\*" "$(OutDir)" && rd /q /s "$(OutDir)Output"
å°æ°ã®é£ç¶ããã¹ãããã§æ§æãããåã¹ãããã¯ç¹å®ã®ã¿ã¹ã¯ãå®è¡ããŸãã
- å®å ãã©ã«ããŒããNMSPC.TestComponent.winmdãããžã§ã¯ãã¡ã¿ããŒã¿ãã¡ã€ã«ãåé€ããŸãã
- ã¡ã¿ããŒã¿ãã¡ã€ã«ãçµåããŸãã çµæã¯ãåºåãã©ã«ããŒã®$ïŒOutDirïŒã«é 眮ãããŸãã
- Ouputãã©ã«ããŒãã$ïŒOutDirïŒãã©ã«ããŒã«ã¡ã¿ããŒã¿ãã¡ã€ã«ãã³ããŒããŸãã
- ã³ã³ãã³ããšå ±ã«åºåãã©ã«ããŒãåé€ããŸãã
DEFãMIDLãPCH
èªå°å¿ã®ããWindowsã©ã³ã¿ã€ã ã³ã³ããŒãã³ãã©ã€ãã©ãªã¯ãã©ã³ã¿ã€ã ã«ãã£ãŠäœ¿çšããã2ã€ã®éåžžã«éèŠãªé¢æ°ãDllGetActivationFactoryããã³DllCanUnloadNowããšã¯ã¹ããŒãããå¿ èŠããããŸãã ãããã®é¢æ°ã®ãšã¯ã¹ããŒãã¯ãTestComponent.defãã¡ã€ã«ã§å®çŸ©ãããŸããïŒã³ãŒãã§å®è£ ããå¿ èŠããããŸãããããã«ã€ããŠã¯åŸã§è©³ãã説æããŸãïŒã
EXPORTS DllGetActivationFactory PRIVATE DllCanUnloadNow PRIVATE
次ã«ãTestComponent.idlãã¡ã€ã«ã§ã¯ã©ã¹ã€ã³ã¿ãŒãã§ã€ã¹ã«ã€ããŠèª¬æããŸããã
import "Windows.ApplicationModel.Background.idl"; namespace NMSPC { namespace TestComponent { [version(1.0)] [activatable(1.0)] [marshaling_behavior(agile)] [threading(both)] runtimeclass TestBackgroundTask { [default] interface Windows.ApplicationModel.Background.IBackgroundTask; }; } }
æåã®ãã£ã¬ã¯ãã£ãã¯ãWindows :: ApplicationModel :: Background :: IBackgroundTaskã®ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã€ã³ã¿ãŒãã§ã€ã¹ã®èª¬æãå«ããã¡ã€ã«ãã€ã³ããŒãããŸãã ãã®ãã¡ã€ã«ã¯MIDLã³ã³ãã€ã©ã«ååãªã®ã§ãä»ã®ã€ã³ã¿ãŒãã§ã€ã¹èšè¿°ãã¡ã€ã«ãã€ã³ããŒãããå¿ èŠã¯ãããŸããïŒWindowsã¹ãã¢8.1ãã©ãããã©ãŒã ã®å Žåãã€ã³ã¿ãŒãã§ã€ã¹èšè¿°ãã¡ã€ã«ãšããããŒãã¡ã€ã«ã¯CïŒ\ Program FilesïŒx86ïŒ\ Windows Kits \ 8.1 \ Include \ winrtã«ãããŸãïŒ ã ã¯ã©ã¹ã®åå空éã¯ããããžã§ã¯ãåNMSPC :: TestComponentã«åŸã£ãŠéžæãããŸããã å±æ§ã䜿çšããŠãã¯ã©ã¹ã®ããŒãžã§ã³ïŒããŒãžã§ã³ïŒãããã©ã«ãã³ã³ã¹ãã©ã¯ã¿ãŒã®ååšã®å åïŒèµ·åå¯èœïŒãã¹ã¬ããã®æäœïŒã¹ã¬ããåïŒããã³ããŒã·ã£ãªã³ã°ïŒmarshaling_behaviorïŒãèšå®ããŸããã MIDLã³ã³ãã€ã©ã䜿çšããŠãããã³ã³ãã€ã«ãããšãTetsComponent.hããããŒãã¡ã€ã«ãååŸãããŸããã
ã³ã³ãã€ã«æéãççž®ãããããpch.hãã¡ã€ã«ïŒããªã³ã³ãã€ã«æžã¿ããããŒãã¡ã€ã«ã®çæã«äœ¿çšïŒã«activation.hããã³æ°ããããããŒãã¡ã€ã«ãå«ããããã®ãã£ã¬ã¯ãã£ããè¿œå ã§çºè¡ããŸããã ãããã®ããããŒãã¡ã€ã«ãå«ããå¿ èŠãããããšã¯ãIActivationFactoryã€ã³ã¿ãŒãã§ã€ã¹ã®äŸåé¢ä¿ãšstd :: nothrowå®æ°ã«ãã£ãŠèª¬æãããŠããŸãã
#pragma once #include "targetver.h" #ifndef WIN32_LEAN_AND_MEAN #define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers #endif #include <windows.h> #include <activation.h> #include <new>
ã³ãŒãã«ã¯ã©ã¹ããã¡ã¯ããªããšã¯ã¹ããŒããããé¢æ°ãå®è£ ããããã«æ®ã£ãã ãã§ãã
ã³ãŒã
ãŸããããªã³ã³ãã€ã«æžã¿ããããŒãã¡ã€ã«ã«å ããŠãMIDLã³ã³ãã€ã©ãŒã«ãã£ãŠçæãããTestComponent.hããããŒãã¡ã€ã«ãTestComponent.cppã³ãŒããã¡ã€ã«ã«å«ããŸããã æ £äŸã«ãããã³ã³ãã€ã©çšã«MIDLã«ãã£ãŠçæããããã¹ãŠã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯ABIåå空éã«é 眮ããããããã¯ã©ã¹ãšãã®å®£èšã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯ABI :: NMSPC :: TestComponentã«é 眮ãããããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ãABI :: Windows :: ApplicationModel :: BackgroundïŒåå空éå šäœãã€ã³ããŒãããã®ã§ã¯ãªããåã ã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ã¿ã®äœ¿çšã瀺ããŸããïŒã
#include "pch.h" #include "TestComponent.h" // using namespace ABI::NMSPC::TestComponent; // ABI::Windows::ApplicationModel::Background using ABI::Windows::ApplicationModel::Background::IBackgroundTask; using ABI::Windows::ApplicationModel::Background::IBackgroundTaskInstance;
ããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®å®è£ ã¯ã©ã¹ã¯éåžžã«ã·ã³ãã«ã§ããããšãå€æããŸããã æ¬è³ªçã«ãIUnknownãIInspectableãããã³IBackgroundTaskã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããå¿ èŠããããŸããã
// . // "" IBackgroundTask class ABI::NMSPC::TestComponent::TestBackgroundTask sealed : public IBackgroundTask { // ULONG m_count; public: TestBackgroundTask() throw() : m_count(1) { // InterlockedIncrement(&m_objectsCount); } ~TestBackgroundTask() throw() { // InterlockedDecrement(&m_objectsCount); } #pragma region IUnknown // COM STDMETHODIMP_(ULONG) AddRef() throw() override final { // return InterlockedIncrement(&m_count); } // COM STDMETHODIMP_(ULONG) Release() throw() override { // auto const count = InterlockedDecrement(&m_count); // if (0 == count) { // delete this; } // return count; } // COM STDMETHODIMP QueryInterface(const IID& riid, void** ppvObject) throw() override final { // // IBackgroundTask IInspectable // IInspectable IUnknown if (__uuidof(IUnknown) == riid || __uuidof(IInspectable) == riid || __uuidof(IBackgroundTask) == riid) { *ppvObject = this; } else { *ppvObject = nullptr; // , return E_NOINTERFACE; } // // static_cast<IInspectable*>(*ppvObject)->AddRef(); return S_OK; } #pragma endregion #pragma region IInspectable // WINRT STDMETHODIMP GetIids(ULONG* iidCount, IID** iids) throw() override { // GUID, .. // CoTaskMemAlloc, .. CoTaskMemFree *iids = static_cast<GUID*>(CoTaskMemAlloc(sizeof(GUID))); // NULL if (!*iids) { // return E_OUTOFMEMORY; } // *iidCount = 1; // IBackgroundTask (*iids)[0] = __uuidof(IBackgroundTask); return S_OK; } // WINRT Runtime STDMETHODIMP GetRuntimeClassName(HSTRING* className) throw() override final { // // E_OUTOFMEMORY // if (S_OK != WindowsCreateString( RuntimeClass_NMSPC_TestComponent_TestBackgroundTask, _countof(RuntimeClass_NMSPC_TestComponent_TestBackgroundTask), className)) { return E_OUTOFMEMORY; } return S_OK; } // WINRT TrustLevel STDMETHODIMP GetTrustLevel(TrustLevel* trustLevel) throw() override final { *trustLevel = BaseTrust; return S_OK; } #pragma endregion #pragma region IBackgroundTask // IBackgroundTask STDMETHODIMP Run(IBackgroundTaskInstance* task_instance) throw() override final { // OutputDebugStringW(L"Hello from background task.\r\n"); return S_OK; } #pragma endregion };
ã¯ã©ã¹ã®æºåãã§ããã®ã§ããªããžã§ã¯ããã¡ã¯ããªã¯ã©ã¹ãäœæããå¿ èŠããããŸããã ãã®ãã¡ã¯ããªã¯ã©ã¹ã¯ãactivation.hããããŒãã¡ã€ã«ã§å®çŸ©ãããŠããIActivationFactoryã€ã³ã¿ãŒãã§ã€ã¹ãå®è£ ããå¿ èŠããããŸãã ãã®ã€ã³ã¿ãŒãã§ã€ã¹ã¯ãIInspectableïŒãããã£ãŠIUnknownïŒãç¶æ¿ããããšã«å ããŠãã¡ãœãããå®çŸ©ããŸã
virtual HRESULT STDMETHODCALLTYPE ActivateInstance( /* [out] */ __RPC__deref_out_opt IInspectable **instance) = 0;
MSDNã®ã¡ãœããã®ããã¥ã¡ã³ãã§èª¬æãããŠããããã«ãGetRuntimeClassNameã¡ãœããã®å®è£ ãç°ãªãå¿ èŠããããŸãã
https://msdn.microsoft.com/en-us/library/br205823(v=vs.85).aspx
// . class TestBackgroundTaskFactory sealed : public IActivationFactory { // ULONG m_count; public: TestBackgroundTaskFactory() throw() : m_count(1) { // InterlockedIncrement(&m_objectsCount); } ~TestBackgroundTaskFactory() throw() { // InterlockedDecrement(&m_objectsCount); } // COM STDMETHODIMP_(ULONG) AddRef() throw() override final { // return InterlockedIncrement(&m_count); } // COM STDMETHODIMP_(ULONG) Release() throw() override { // auto const count = InterlockedDecrement(&m_count); // if (0 == count) { // delete this; } // return count; } // COM STDMETHODIMP QueryInterface(const IID& riid, void** ppvObject) throw() override final { if (__uuidof(IUnknown) == riid || __uuidof(IInspectable) == riid || __uuidof(IActivationFactory) == riid) { *ppvObject = this; } else { *ppvObject = nullptr; return E_NOINTERFACE; } static_cast<IInspectable*>(*ppvObject)->AddRef(); return S_OK; } // WINRT STDMETHODIMP GetIids(ULONG* iidCount, IID** iids) throw() override final { // GUID, .. // CoTaskMemAlloc, .. CoTaskMemFree *iids = static_cast<GUID*>(CoTaskMemAlloc(sizeof(GUID))); // NULL if (*iids) { // return E_OUTOFMEMORY; } // *iidCount = 1; // IBackgroundTask (*iids)[0] = __uuidof(IActivationFactory); return S_OK; } // WINRT Runtime STDMETHODIMP GetRuntimeClassName(HSTRING*) throw() override final { // , .. return E_ILLEGAL_METHOD_CALL; } // WINRT TrustLevel STDMETHODIMP GetTrustLevel(TrustLevel* trustLevel) throw() override final { *trustLevel = BaseTrust; return S_OK; } // IActivationFactory STDMETHODIMP ActivateInstance(IInspectable** instance) throw() override final { // null if (nullptr == instance) { // return E_INVALIDARG; } // // , *instance = new (std::nothrow) TestBackgroundTask(); // return *instance ? S_OK : E_OUTOFMEMORY; } };
泚ææ·±ãèªè ã¯ãã¯ã©ã¹ã®ã³ã³ã¹ãã©ã¯ã¿ãšãã¹ãã©ã¯ã¿ã®å¥åŠãªè©³çŽ°ãã€ãŸãå€æ°m_objectsCountã®ã€ã³ã¯ãªã¡ã³ããšãã¯ãªã¡ã³ãã«æ°ä»ãã§ãããã ã¯ã©ã¹ã³ãŒãã®åã«ãã£ã¬ã¯ãã£ãã䜿çšããçŽåŸã«ããã®å€æ°ã宣èšããŸããã ãããŠãDllCanUnloadNowé¢æ°ã®ãšã¯ã¹ããŒããããã©ã€ãã©ãªã§äœ¿çšãããŸãã
// HRESULT WINAPI DllCanUnloadNow() throw() { // return m_objectsCount ? S_FALSE : S_OK; }
ãã®é¢æ°ã«å ããŠãå¥ã®DllGetActivationFactoryãå®çŸ©ãããŸãããããã¯ãã¯ã©ã¹èå¥åïŒWindowsã©ã³ã¿ã€ã ã§ã¯ãã¹ãŠã®åå空éãå«ãæååïŒã§ãã¡ã¯ããªãåãåãããšãç®çãšããŠããŸãã
// , activatableClassId HRESULT WINAPI DllGetActivationFactory(HSTRING activatableClassId, IActivationFactory **factory) throw() { // if (WindowsIsStringEmpty(activatableClassId) || nullptr == factory) { // return E_INVALIDARG; } // if (0 == wcscmp(RuntimeClass_NMSPC_TestComponent_TestBackgroundTask, WindowsGetStringRawBuffer(activatableClassId, nullptr))) { // *factory = new (std::nothrow) TestBackgroundTaskFactory(); return *factory ? S_OK : E_OUTOFMEMORY; } *factory = nullptr; return E_NOINTERFACE; }
CïŒã¢ããªã±ãŒã·ã§ã³ã§ã®ã³ã³ããŒãã³ãã®äœ¿çšã«ã€ããŠèª¬æããåã«ãdllmain.cppãã¡ã€ã«ã§å®çŸ©ãããŠããDllMainé¢æ°ã®æ瀺çãªå®è£ ã«ã€ããŠã説æããŸãã 蚺æç®çã§ã®ã¿äœ¿çšããŸãããããŠãŒã¹ã±ãŒã¹ã¯ç§ã®ãã®ãšã¯ç°ãªãå ŽåããããŸãã
#include "pch.h" BOOL APIENTRY DllMain(HMODULE /* hModule */, DWORD ul_reason_for_call, LPVOID /* lpReserved */) { OutputDebugStringW(L"Hello from DLL.\r\n"); return TRUE; }
ããã§ãã³ã³ããŒãã³ãã©ã€ãã©ãªã®å®è£ ãå®äºããŸããã ãããŠãã¢ããªã±ãŒã·ã§ã³ã§ã®å®çšåãéå§ããããšãã§ããŸããã
CïŒã¢ããªã±ãŒã·ã§ã³
Blank Appãã³ãã¬ãŒãã䜿çšããŠNMSPC.CSTestApppã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ããäœæããããã³ã³ããŒãã³ããããžã§ã¯ããšMicrosoft Visual C ++ 2013ã©ã³ã¿ã€ã ããã±ãŒãžãžã®ãªã³ã¯ãè¿œå ããŸããã
æ®ã£ãã®ã¯ãã¢ããªã±ãŒã·ã§ã³ãããã§ã¹ããã¡ã€ã«ãç·šéããŠãããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®å®çŸ©ãè¿œå ããããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ãç»é²ããã³ãŒããæžãããšã ãã§ããã
ã³ãŒãã¯ãAppã¯ã©ã¹ã®OnLaunchedã¡ãœããã«é 眮ãããŸãã ã³ãŒãã¯åçŽã§ããæåã«ãã¹ãŠã®ã¿ã¹ã¯ç»é²ãåé€ããŠãããã¿ã¹ã¯ãã«ããªããžã§ã¯ããäœæãããããã§ã¹ãã§æå®ãããããªã¬ãŒãèšå®ããŠãã¿ã¹ã¯ãç»é²ããŸãã
foreach (var pair in BackgroundTaskRegistration.AllTasks) { pair.Value.Unregister(true); } var taskBuilder = new BackgroundTaskBuilder { Name = "TestBackgroundTask", TaskEntryPoint = "NMSPC.TestComponent.TestBackgroundTask" }; taskBuilder.SetTrigger(new SystemTrigger(SystemTriggerType.TimeZoneChange, true)); taskBuilder.Register();
C ++ã³ãŒãã®ãã¬ãŒã¯ãã€ã³ãã«ç§»åã§ããããã«ããããã«ãã¢ããªã±ãŒã·ã§ã³ãããžã§ã¯ãã®ãããã°èšå®ã§ããã»ã¹ã¿ã€ãMixedïŒManaged and NativeïŒãèšå®ããŸãã ãšããã§ããã®èšå®ã¯C ++ / CXã¢ããªã±ãŒã·ã§ã³ã«ãé¢é£ããŠããŸãã
ããã§ããããã°ã¢ãŒãã§ã¢ããªã±ãŒã·ã§ã³ãèµ·åããã³ã³ããŒãã³ãç»é²ã³ãŒããå®è¡ãã[ãããã°ã®å Žæ]ã»ã¯ã·ã§ã³ã®[ã©ã€ããµã€ã¯ã«ã€ãã³ã]ãã¿ã³ã䜿çšããŠããã¯ã°ã©ãŠã³ãã¿ã¹ã¯ã®èµ·åããã¹ãã§ããŸããã
ãããå®è¡ãããšãåºåãŠã£ã³ããŠã«éåžžã«å€§äºãªè¡ã衚瀺ããããã®åºåã¯OutputDebugStringWé¢æ°ã䜿çšããŠC ++ã³ãŒãã§ããã°ã©ã ãããŸããã
Hello from DLL. Hello from background task.
ãããã«
çµå±ã®ãšãããWRLã䜿çšããã«ã³ã³ããŒãã³ãã³ãŒããèšè¿°ããããšãå¯èœã§ãã ãã®åé¡ã®è§£æ±ºçã«ãããWindowsã©ã³ã¿ã€ã ç°å¢ã®ã³ã³ããŒãã³ãéã®çžäºäœçšã®å®è¡ã¡ã«ããºã ãšåçãããããç解ããããšãå¯èœã«ãªããŸããã
GitHubã§å ¥æå¯èœãªãœãŒã¹ã³ãŒã
https://github.com/altk/RuntimeComponent