Integrate a COM object in a C++ CLR Console App - c++

I am trying to use a COM object in a C++ CLR Console App as I did in C#. (it comes from statconn) I am new with the C++ CLR code and I don't find sample explaining how it works
I did the following things:
using namespace StatConnTools;
using namespace StatConnControls;
using namespace StatConnectorCommonLib;
using namespace STATCONNECTORSRVLib;
STATCONNECTORSRVLib::StatConnector^ oStatCon = gcnew STATCONNECTORSRVLib::StatConnector();
oStatCon::IStatConnector::Init(L"R");
oStatCon::IStatConnector::Close();
I get the message : oStatConn must be a class or namespace when followed by ::
thanks for help

The variable oStatCon is an object, i.e. an instance of a class. The scope operator can only be used on namespaces or classes, like the error message says.
You should be calling Init and Close as normal functions:
oStatCon.Init(L"R");
oStatCon.Close();

Related

Using WRL to access WinRT, I cannot get ActivateInstance to work

I am trying to figure out how to access the WinRT API via WRL in C++, using visual studio 2022 with the latest update 17.1.2.
(Background: I've done a fair amount of old-fashioned Windows desktop programming with the Win32 API. However, I now wish to access parts of the Windows API that are supported only in WinRT, such as access to Bluetooth LE devices. Note that I am trying to avoid UWP applications, as I fear it may cause my applications to be bloated, and am not sure what needed functionality it might remove from my programs. Further, I have tried Microsoft's C++/WinRT, but was having lots of trouble at points where the Microsoft compiler was telling me there was a problem up in the generated C++ headers--not my own code. So I am now trying to work closer to the ground with WRL.)
So, starting with an example provided in MS documentation (uri winRT class, which I can get to work as they wrote it), I have tried to try use of the ActivateInstance WRL class (which is not used in their example).
It seems not to be working for me. But I am probably doing something wrong. Can anyone help?
I have pared down the code to show the precise issue:
#include <roapi.h>
#include <combaseapi.h>
#include <iostream>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
#include <wrl\wrappers\corewrappers.h>
#include <wrl\client.h>
#include <stdio.h>
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
int dummy;
ComPtr<IUriRuntimeClassFactory> uriFactory;
ComPtr<IUriRuntimeClass> uri;
HRESULT hr, hr2;
int main()
{
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
// Get the activation factory for the IUriRuntimeClass interface.
hr = GetActivationFactory(HStringReference(L"Windows.Foundation.Uri").Get(), &uriFactory);
hr2 = ActivateInstance (HStringReference(L"Windows.Foundation.Uri").Get(), &uri);
dummy = 1;
}
What happens is hr returns as S_OK. (Creating the factory. I don't use it here, but it is apparently a valid factory as it works when I leave in the rest of the Microsoft WRL example.)
But, what is confusing me is that hr2 is returning "E_NOTIMPl (not implemented)", and I thought it would get me a smart pointer to the uri class.
(Referencing this MS documentation for ActivateInstance:
and observing that the argument types are the same as
for GetActivationFactory
Thanks

using WRL to access winRT: where do you find the right names to use for the classfactories and classes?

(This is the next iterative question so I can figure out how to use WRL, after this one was answered I believe correctly.)
So I'm trying to build up to being able to access Bluetooth LE devices through WinRT via WRL.
Continuing in the pattern of a Microsoft example (which is for the uri WinRT class), I am trying at this point just to get the class factory for the DeviceWatcher Class. ( Documentation for that class seems to be here ), this is my pared-down example code:
#include <roapi.h>
#include <combaseapi.h>
#include <iostream>
#include <windows.foundation.h>
#include <windows.foundation.collections.h>
#include <wrl\wrappers\corewrappers.h>
#include <wrl\client.h>
#include <stdio.h>
#include <windows.devices.enumeration.h>
using namespace ABI::Windows::Foundation;
using namespace Microsoft::WRL;
using namespace Microsoft::WRL::Wrappers;
using namespace ABI::Windows::Devices::Enumeration;
int dummy;
ComPtr<IUriRuntimeClassFactory> uriFactory;
ComPtr<IUriRuntimeClass> uri;
ComPtr<IDeviceWatcherRuntimeClassFactory> devWatcherFactory; //This line produces the only error, "IDeviceWatcherRuntimeClassFactory undefined"
//(When the line is omitted, the code compiles, links, and produces the smart pointer to a uri class)
HRESULT hr, hr2, hr3;
int main()
{
// Initialize the Windows Runtime.
RoInitializeWrapper initialize(RO_INIT_MULTITHREADED);
// Get the activation factory for the IUriRuntimeClass interface.
ComPtr<IUriRuntimeClassFactory> uriFactory;
HRESULT hr = GetActivationFactory(HStringReference(RuntimeClass_Windows_Foundation_Uri).Get(), &uriFactory);
// Create a string that represents a URI.
HString uriHString;
hr = uriHString.Set(L"http://www.microsoft.com");
// Create the IUriRuntimeClass object.
ComPtr<IUriRuntimeClass> uri;
hr2 = uriFactory->CreateUri(uriHString.Get(), &uri);
dummy = 1;
}
It is the MS example, up to the point of its uri WinRT class construction, and compiles and links and correctly constructs the uri class smart pointer when I leave out my added line that declares the ComPtr for IDeviceWatcherRuntimeClassFactory
The line is my attempt to just create a smart-pointer for the DeviceWatcher class factory, and it fails with identified "IDeviceWatcherRuntimeClassFactory undefined". (It also fails if I use small "d" as the second letter of the type argument.
In using "IDeviceWatcherRuntimeClassFactory", I'm trying to proceed by exact analogy to the MS example.
Besides the MS online documentation for the DeviceWatcher class (3), which doesn't seem to help me, I've also tried looking at what VS2022 solution explorer shows as the expansion of the header windows.devices.enumeration.h (which also does not seem to be telling me what name to use as far as I can figure out).
I've also tried using the VS2022 Object Browser, pointed to a custom component set of all .winmd files in C:\Windows\System32\WinMetaData, and again the information is not helping me, given my level of knowledge.
Can someone give me a sound method, for an arbitrary WinRT class, to figure out the type to use for the smart pointer to the class factory?
And, to save another iteration, once I can make a smart pointer to the factory, I will
need to make a smart pointer to the class itself (in my case, to DeviceWatcher). Can someone tell me what exact name to use for the ComPtr type?
Thanks.

how to call uwp class library in win32 C++ console application

I wanna call a uwp app with Uri in a win32 C++ console application.The first thing I thought is using LaunchUriAsync, but I couldn't find Windows.System.Launcher.LaunchUriAsync in win32 C++. So I wanna create a uwp class library to call LaunchUriAsync and win32 call this library. I find an example and now I can load the library sucessfully, but GetProcAddress always returns null. Not sure whether it is feasible calling uwp class library in win32 console. Pls help me out. The project is at https://github.com/vincent1000/win32CallUwpLibrary
The code is very simple:
UWP Classy Library:
namespace ExportedCodeSolution
{
public class Class1
{
[DllExport(ExportName = "callUri", CallingConvention = CallingConvention.StdCall)]
static public async void callUri()
{
Console.WriteLine("call URI start");
await Launcher.LaunchUriAsync(new Uri("www.bing.com"));
}
}
}
And Win32 Console:
using CallUriFn = void(__stdcall*) ();
int main()
{
HMODULE mod = LoadLibraryA("ExportedCodeSolution.dll");
CallUriFn fn = reinterpret_cast<CallUriFn>(GetProcAddress(mod, "callUri"));
fn();
}
Also, is any other method to call LaunchUriAsync in win32? I have searched some methods but none works for me.
The solution is trivial: Simply call Launcher.LaunchUriAsync from your console application. The easiest route is to use C++/WinRT. Assuming that you are using Visual Studio with the C++/WinRT extension installed, create a "Windows Console Application (C++/WinRT)", and replace the wizard generated code with this:
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.System.h>
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::System;
int main()
{
init_apartment();
Uri uri(L"www.bing.com");
Launcher::LaunchUriAsync(uri).get();
}
This will compile, but fail at runtime due to "www.bing.com" not being a valid URI. This needs to be replaced with a valid URI (e.g. "https://www.bing.com").

How to use namespace - Microsoft.Phone.Info - in native C++ on in WP 8.1 or WP 8

I'm working in a native C++ enviroment on WP8.1.
Let's say I want to call a functions like
Microsoft.Phone.Info::DeviceExtendedProperties.GetValue( "DeviceUniqueId" );
The problem is no matter how I try, it didn't pass compile.
I know "Microsoft.Phone.Info" is a name space,
in C# ppl wrote:
using Microsoft.Phone.Info;
but in C++, I tried
using namespace Microsoft.Phone.Info;
void func()
{
DeviceExtendedProperties.GetValue("DeviceUniqueId");
}
didn't pass compile. or
void func()
{
Microsoft.Phone.Info::DeviceExtendedProperties.GetValue("DeviceUniqueId");
}
didn't pass compile.
It keeps telling me something like this
'Microsoft' : illegal use of namespace identifier in expression
so how do I use this namespace properly?
Thank you guys for the reading and answering. :-)
I can't find a C++ example for retriving the device ID. :-P
Although many of the properties from DeviceInformation can be found on EasClientDeviceInformation, the device ID is not one of them. Instead, you should look at using the ASHWID which will get you an app-specific hardware ID.
In native WP runtime, using a namespace follows this syntax
using namespace Windows::Phone::Info;
But you will find out that the namespace does not exist in runtime. Only in WP Silverlight.
So you can look at this MSDN webpage that tells you where they moved all the functionality from 8.0 SL to 8.1 runtime.
Windows Phone Silverlight to Windows Runtime namespace and class mappings
Then if you search for "Windows.Phone.Info" it will lead you to the new functions you should call.
Here is the ID : EasClientDeviceInformation class
I guess I got it:
EasClientDeviceInformation^ deviceInfo = ref new EasClientDeviceInformation();
deviceInfo->Id; //<- is what I want

Managed C++ Wrapper for Unmanaged Static Library with static variables hangs

The explanation of the problem is a little long-winded, please bear with me.
I have an unmanaged C++ static library that is used for financial application. It has business day conventions, swap conventions, bond conventions, etc. Most of the conventions rely on static global variables, which are initialized on first use. The library also initializes the holiday calendars on startup by running some queries against a SQL Server database using ODBC.
I have to interact with third-party software using web services. The only way to do this realistically is through C#. That isn't an issue, and I was making good progress. However, I hit a stumbling block when it became necessary to do some date calculations in C#. Since I didn't want to port all my C++ code to C#, I figured the most efficient way to achieve this would be by writing a Managed C++ Class Library DLL that is a wrapper around my unmanaged static library. Everything seems to work fine, I get no compile-time or link-time errors, and I can add the reference to the wrapper and see all the proper object definitions. However, when I try to run my application, it just hangs. I have tried playing around with a bunch of compiler setting for the wrapper DLL, to no avail. If I remove the project dependency on my unmanaged library, everything works fine. I have a strong suspicion that my liberal use of global static variables is causing issues. Is there are way to solve this problem, are at least figure out where the issue is? Example code is below.
Thanks,
Marc.
// FSAManaged.h
#pragma once
using namespace System;
//class XLDate;
namespace FSAManaged {
public ref class Futures
{
public:
static DateTime Expiry(String ^ code, DateTime date);
};
}
The implementation does not even rely on a dependency to the unmanaged static library:
// This is the main DLL file.
#include "stdafx.h"
#include "FSAManaged.h"
namespace FSAManaged
{
DateTime Futures::Expiry(String ^ code, DateTime date) {
return DateTime::Today;
}
}
For completeness' sake, here is AssemblyInfo.cpp:
#include "stdafx.h"
using namespace System;
using namespace System::Reflection;
using namespace System::Runtime::CompilerServices;
using namespace System::Runtime::InteropServices;
using namespace System::Security::Permissions;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly:AssemblyTitleAttribute("FSAManaged")];
[assembly:AssemblyDescriptionAttribute("")];
[assembly:AssemblyConfigurationAttribute("")];
[assembly:AssemblyCompanyAttribute("?????")];
[assembly:AssemblyProductAttribute("FSAManaged")];
[assembly:AssemblyCopyrightAttribute("??????")];
[assembly:AssemblyTrademarkAttribute("")];
[assembly:AssemblyCultureAttribute("")];
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the value or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly:AssemblyVersionAttribute("1.0.*")];
[assembly:ComVisible(false)];
[assembly:CLSCompliantAttribute(true)];
[assembly:SecurityPermission(SecurityAction::RequestMinimum, UnmanagedCode = true)];
Use the debugger. If you test this from C# then Project + Properties, Debug, tick "Enabled unmanaged code debugging". Setting up the symbol server in Tools + Options, Debugging, Symbols is strongly recommended. Run.
When it hangs use Debug + Break All. Debug + Windows + Threads and double-click the thread that is supposed to be doing the job. Debug + Windows + Call stack to see what is going on. Post the stack trace in your question if you can't figure it out. Anything you see in the Output window and the Visual Studio status bar is relevant too.
Static C++ variables are initialized from DllMain. There are lot's of things you should not do in DllMain; triggering the load of yet another Dll being the most important one. This is easy to break if you call into other peoples libraries in from DllMain.
I suggest you make an Init function on your Dll, which you call after the dll is up and running.