CreatePushNotificationChannelForApplicationAsync in native C++ - c++

I'm trying to use windows push notifications in native C++ code. But I struggle with implementation. I'm calling CreatePushNotificationChannelForApplicationAsync but it returns
HRESULT_FROM_WIN32(ERROR_NOT_FOUND) : Element not found.
My OS is Win10 and I use Visual Studio 2015.
Here is my code:
#include <wrl.h>
#include <windows.networking.pushnotifications.h>
#include <ppltasks.h>
#pragma comment(lib, "runtimeobject.lib")
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Networking::PushNotifications;
using namespace concurrency;
int main(char* argv[], int argc)
{
RoInitializeWrapper init(RO_INIT_MULTITHREADED);
if ( FAILED(init) )
return 0;
ComPtr<IPushNotificationChannelManagerStatics> channelManager;
HRESULT hr = GetActivationFactory(HStringReference(L"Windows.Networking.PushNotifications.PushNotificationChannelManager").Get(), &channelManager);
if ( FAILED(hr) )
return 0;
IAsyncOperation<PushNotificationChannel*>* asyncOp;
hr = channelManager->CreatePushNotificationChannelForApplicationAsync(&asyncOp); // return HRESULT_FROM_WIN32(ERROR_NOT_FOUND)
if ( FAILED(hr) )
return 0;
// create task to obtain uri from asyncOp
return 0;
}
On the other hand it is pretty straightforward in WinRT.
namespace WnsPushAPI
{
public ref class WnsWrapper sealed
{
public:
void ObtainUri()
{
IAsyncOperation<PushNotificationChannel^>^ channelOperation = PushNotificationChannelManager::CreatePushNotificationChannelForApplicationAsync();
auto channelTask = create_task(channelOperation);
channelTask.then([this](PushNotificationChannel^ channel) {
// ... Save URI for latter use. channel->Uri->Data()
channel->PushNotificationReceived += ref new TypedEventHandler<PushNotificationChannel^, PushNotificationReceivedEventArgs^>(this, &WnsWrapper::OnNotify);
}, task_continuation_context::use_current());
}
void OnNotify(PushNotificationChannel^ sender, PushNotificationReceivedEventArgs^ e)
{
// do something
};
};
}
I also checked generated code with /d1ZWtokens compiler switch but I didn't find anything useful.
Documentation for push notification for native C++ is really poorly written and I couldn't find and example in native C++.

Your code is okay. The problem lies in the fact that you can only register for push notifications from Windows Store applications. You cannot do that from desktop applications. The error comes from the fact that the system cannot find your AppX package identity.

I also faced same HRESULT_FROM_WIN32(ERROR_NOT_FOUND) error while trying to use WNS from my desktop app. Just in case anyone also faces this issue I'd like to mention CreatePushNotificationChannelForApplicationAsync works fine from Desktop Bridge. Here is the code that I used. Note it is winrt based, and I think WRL based code also would work without any problem, just need to wrap desktop app with Desktop Bridge.
winrt::init_apartment();
PushNotificationChannelManagerForUser manager = PushNotificationChannelManager::GetDefault();
IAsyncOperation<PushNotificationChannel> async = manager.CreatePushNotificationChannelForApplicationAsync();
async.Completed([](auto && result, auto && status) {
auto channel = result.GetResults();
});

Related

What is the equivalent for win32com.client.GetObject() in CPP?

What is the equivalent for win32com.client.GetObject() in CPP ?
I am trying to get the SAPGUI object in CPP
SapGuiAuto = win32com.client.GetObject("SAPGUI")
Referring to these quotes from the below article - https://blogs.sap.com/2020/08/02/sap-gui-scripting-api-from-the-past-for-future-automation/
The SAP GUI Scripting API is in the file sapfewse.ocx (FEWSE = Front End Windows Scripting Engine), in the directory C:\Program Files (x86)\SAP\FrontEnd\SapGui. It is a Component Object Model (COM) library and registered in the Windows registry. On this way you can use it from any COM-enabled programming language
There is no "C++" way of doing it. There are, however, ways of doing it on Windows using Microsoft libraries.
I'd recommend using CComDispatchDriver class. Haven't tested this...but it will get you close.
// .. include standard windows stuff
#include <comdef.h>
#include <atlbase.h>
class ComInit
{
public:
ComInit()
{
CoInitialize(NULL);
}
~ComInit()
{
CoUnintialize();
}
ComInit(const ComInit& ) = delete;
ComInit& operator=(const ComInit&) = delete;
};
int main(int argc, char* argv)
{
ComInit _cominit;
CComDispatchDriver disp;
disp.CoCreateInstance(L"Excel.Application");
_variant_t vName;
disp.GetPropertyByName(L"Name", &vName);
return 0;
}

c++/cli dll wrapper for native c++ to be used in LabView

I'm trying to write a c++/cli wrapper for IO Industries Core2 DVR, which will then be used by LabView. The company provided a SDK with with all the headers (written in c++) and boost library. I've managed to build a wrapper that builds and LabView is able to see the function through the .net pallet.
// ManagedProject.h
#pragma once
#include "core_api_helper.h"
#include "core_api.h"
using namespace System;
using namespace CoreApi;
namespace ManagedProject {
//Setup class
public ref class Setup
{
private:
public:
unsigned int initializeTest();
};
}
// This is the DLL Wrapper.
#include "stdafx.h"
#include "ManagedProject.h"
#include "core_api_helper.h"
#include "core_api.h"
#include "resource.h"
using namespace CoreApi;
using namespace Common;
using namespace ManagedProject;
//Global handles
//A handle to the Core Api
InstanceHandle g_hApi;
//A handle to the Core Api Device Collection
DeviceCollectionHandle g_hCoreDeviceCollection;
unsigned int Setup::initializeTest()
{
try
{
//Initialize the Core API (must be called before any other Core API functions)
//Returns a handle to the Core Api
g_hApi = Instance::initialize();
// get a collection of Core devices
g_hCoreDeviceCollection = g_hApi->deviceCollection();
unsigned int deviceCount = g_hCoreDeviceCollection->deviceCount();
return deviceCount;
}
catch (GeneralException& e)
{
e.what();
return 3;
}
}
However when I run LabView through Visual studio 2015 in debug mode I run into the problem below, and what is returned to LabView is the 3 from the catch block.
First break in debug mode (NULL ptr)
NOTE: InstanceHandle is a shared_ptr
As can be seen the variable is a NULL pointer, the same thing happens for the g_hCoreDeviceCollectoin as well. I think I need to Instantiate it with the new command but am a little unsure as InstanceHandle is a shared_ptr.
Any help would be much appreciated
The C++/CLI has great feature called mixed mode. You can uses both managed and native data types in the same code (in the same C++/CLI class). Try to use object from that SDK written in C++ directly in your wrapper.

How to initialize an instance of IVectorView for C++/WRL?

I'm trying to call get_Skus() method of IStoreProduct to retrieve its Skus property using C++/WRL (not C++/CX) and I can't find any suitable code examples. That method is defined as such (as I get it from the header file in Visual Studio):
virtual /* [propget] */ HRESULT STDMETHODCALLTYPE get_Skus(
/* [out][retval] */ __RPC__deref_out_opt IVectorView<ABI::Windows::Services::Store::StoreSku*> **value) = 0;
So when I try to do:
#include <Windows.Services.Store.h>
#include <wrl.h>
using namespace ABI::Windows::Services::Store;
using namespace ABI::Windows::Foundation::Collections;
IVectorView<StoreSku*> pStrSkus;
//IStoreProduct* pStorePrdct = ...;
if (SUCCEEDED(pStorePrdct->get_Skus(&pStrSkus)))
{
}
it gives me an error that:
'ABI::Windows::Foundation::Collections::IVectorView'
: cannot instantiate abstract class
I'm relatively new to WRL. Can someone show me how am I supposed to call that method?
You forgot a star - it should have been this:
IVectorView<StoreSku*>* pStrSkus;
if (SUCCEEDED(pStorePrdct->get_Skus(&pStrSkus)))
{
...
pStrSkus->Release();
}
Even better, use a ComPtr instead, so you don't have to release it manually:
ComPtr<IVectorView<StoreSku*>> pStrSkus;
if (SUCCEEDED(pStorePrdct->get_Skus(&pStrSkus)))
{
...
}

UWP C# app calling Windows Runtime Component written in C++

I am trying to create a Windows Runtime(WinRT) Component written in C++(c++-cx) which can be called from my UWP C# app. I followed this MSDN Tutorial
It all went fine. I am able to build & run the code/sample specified in the above link on both Windows-10 Desktop & Mobile
I then tried to create a even simpler WinRT Component. I followed the same steps as above tutorial. Created a Windows Runtime Component project (File->New->Project->Visual C++ ->Windows->Universal->Windows Runtime Component(Universal Windows))
Now my class has only one function, getNum which basically returns a uint16
This is my Class header file
#pragma once
#include <collection.h>
namespace WRT_sample
{
public ref class Class1 sealed
{
public:
Class1();
uint16 getNum();
};
}
This is the corresponding cpp file:
#include "Class1.h"
using namespace WRT_sample;
using namespace Platform;
Class1::Class1()
{
}
uint16 Class1::getNum()
{
return 100;
}
I am using the same class names(Class1.h & Class1.cpp) which VS-2015 provides when I create a new WinRT project.
This is how I make a call to WinRT class from my C# code:
namespace CS_WRT_sample
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
initWRT();
}
void initWRT()
{
try
{
var nativeObj = new Class1();
var num = nativeObj.getNum();
this.Result2.Text = "Num from Cpp: " + num.ToString();
Debug.WriteLine("Num from Cpp: " + num);
}
catch (Exception ex)
{
Debug.WriteLine(ex.Message);
this.Result3.Text = ex.Message;
}
}
}
}
I am able to build & run my code on Desktop(x86/x64 Local Machine), but when I try to run on Mobile(x86 Emulator or ARM device), it fails with the following error:
Exception thrown: 'System.IO.FileNotFoundException' in CS_WRT_sample.exe
The specified module could not be found. (Exception from HRESULT: 0x8007007E)**
This is the stack trace which I see:
System.StubHelpers.StubHelpers.GetWinRTFactoryObject(IntPtr pCPCMD)
at WRT_sample.Class1..ctor()
at CS_WRT_sample.MainPage.initWRT()
My VS-2015 details:
MS Visual Studio Professional 2015
Version 14.0.25123.00 Update 2
MS .NET Framework
Version 4.6.01038
I am not sure, why I am hitting the issue, as I followed the same steps mentioned in the MSDN tutorial.
Any help will be highly appreciated.
You will run into this if you use a direct reference to a C++ winmd, instead of a P2P reference. This is easy to check in your .csproj:
For example, your .csproj should not have this line:
..\Debug\Abc_def\Abc_Def.winmd
Instead, consider using something like:
{1ee77824-eaa8-40f1-9b56-6f8ffa44e727}
Abc_Def

What can I do about loading this resource into a unit testing DLL?

I just ported all of my tests from Google Test to Visual Studio 2012's unit test framework. (Long story; Google's assertions are better but Microsoft's works with the Dev11 Unit Test Explorer out of the box, which makes getting code coverage really easy ...)
I got everything ported over fine, except for the following class, which reads a newline-delimited text file from a Win32 resource, and then allows for quick lookups against that resource:
#include "pch.hpp"
#include "resource.h"
#include <functional>
#include <algorithm>
#include <iostream>
#include <iterator>
#include <boost/algorithm/string/split.hpp>
#include <boost/algorithm/string/case_conv.hpp>
#include <windows.h>
#include "Win32Exception.hpp"
#include "Whitelist.hpp"
using Instalog::SystemFacades::Win32Exception;
namespace Instalog {
Whitelist::Whitelist( __int32 whitelistId , std::vector<std::pair<std::wstring, std::wstring>> const& replacements )
{
using namespace std::placeholders;
HRSRC resourceHandle = ::FindResource(0, MAKEINTRESOURCEW(whitelistId), L"WHITELIST");
if (resourceHandle == 0)
{
Win32Exception::ThrowFromLastError();
}
HGLOBAL resourceGlobal = ::LoadResource(0, resourceHandle);
if (resourceGlobal == 0)
{
Win32Exception::ThrowFromLastError();
}
void * resourceData = ::LockResource(resourceGlobal);
if (resourceData == 0)
{
Win32Exception::ThrowFromLastError();
}
wchar_t const* resourceDataCasted = static_cast<wchar_t const*>(resourceData);
DWORD resourceLen = ::SizeofResource(0, resourceHandle);
auto sourceRange = boost::make_iterator_range(resourceDataCasted, resourceDataCasted + (resourceLen / sizeof(wchar_t)));
boost::algorithm::split(innards, sourceRange, std::bind1st(std::equal_to<wchar_t>(), L'\n'));
std::for_each(innards.begin(), innards.end(), std::bind(boost::algorithm::to_lower<std::wstring>, _1, std::locale()));
std::for_each(innards.begin(), innards.end(), [&replacements] (std::wstring &a) {
std::for_each(replacements.begin(), replacements.end(), [&a] (std::pair<std::wstring, std::wstring> const&b) {
if (boost::algorithm::starts_with(a, b.first))
{
a.replace(a.begin(), a.begin() + b.first.size(), b.second);
}
});
});
std::sort(innards.begin(), innards.end());
}
bool Whitelist::IsOnWhitelist( std::wstring checked ) const
{
boost::algorithm::to_lower(checked);
return std::binary_search(innards.begin(), innards.end(), checked);
}
void Whitelist::PrintAll( std::wostream & str ) const
{
std::copy(innards.begin(), innards.end(), std::ostream_iterator<std::wstring, wchar_t>(str, L"\n"));
}
}
Unfortunately, Dev11's test projects generate DLLs, not EXEs, as under Google Test's system. So, while before I was able to embed the resource into the EXE and pass NULL to FindResource's first parameter, now Visual Studio is loading the DLL into its process during testing. Visual Studio certainly doesn't have my custom WHITELIST resource type inside, so this code blows up.
Is there some way I can either
Tell this code somehow to look in the right binary, either the testing DLL or the EXE, depending on context? (Currently this code is in a static library which gets linked with both the real EXE and the testing DLL) or
Embed relatively large (a few MB) text files into a C++ program cleanly without using the Win32 resource infrastructure at all?
It should be noted that putting the resource into a satellite DLL (which might have been a reasonable solution) is not an option; a requirement of this project is single EXE xcopy deployment.
Figured it out. I used the GetCurrentModule hack here -> How do I get the HMODULE for the currently executing code? . This gave the the HMODULE I needed to pass into the XxxResource APIs.