I am writing some UEM (= Unified Endpoint Management) tools and need to sync my client
with the UEM Server. To do this i use C++ and winrt (= Windows runtime)
I extracted a part of the code to show you my problem. The code works after you change one line in a generated header file. The program does what is is supposed to do and
does it fast. To run the code, you need an MDM enrolled Windows Client. To recreate the problem, you only need your compiler.
#include "pch.h"
using namespace winrt;
using namespace Windows::Foundation;
using namespace Windows::Management;
#include <iostream>
#include <chrono>
#include <thread>
using namespace std;
int main()
{
winrt::init_apartment(); //initialise winrt
//create a session
auto session = winrt::Windows::Management::MdmSessionManager().TryCreateSession();
//start the sync
session.StartAsync();
//show some output
cout << "Start async command launched.\n";
while (session.State() != MdmSessionState::Completed)
{
switch (session.State())
{
case MdmSessionState::NotStarted:
cout << "Not started\n";
break;
case MdmSessionState::Starting:
cout << "Starting\n";
break;
case MdmSessionState::Connecting:
cout << "Connecting\n";
break;
case MdmSessionState::Communicating:
cout << "Communicating\n";
break;
case MdmSessionState::AlertStatusAvailable:
cout << "Alert occured\n";
break;
case MdmSessionState::Retrying:
cout << "Retrying\n";
break;
case MdmSessionState::Completed:
cout << "Completed\n";
break;
default:
cout << "Unknown Status";
break;
}
std::this_thread::sleep_for(chrono::milliseconds(10)); //make it slower
}
cout << "Finished.\n";
}
The output looks like this:
Start async command launched.
Not started
Not started
Not started
Not started
Not started
Connecting
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Communicating
Finished.
On the server side I can verify that the client has synced, so far so good.
Every time I clean and completely recompile my project, I get the following error:
Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
Fehler MSB6006 "CL.exe" wurde mit dem Code 2 beendet. WinRTtest C:\Program Files\Microsoft Visual Studio\2022\Community\MSBuild\Microsoft\VC\v170\Microsoft.CppCommon.targets 702
Schweregrad Code Beschreibung Projekt Datei Zeile Unterdrückungszustand
Fehler C2280 "winrt::Windows::Management::MdmSessionManager::MdmSessionManager(void)" : Es wurde versucht, auf eine gelöschte Funktion zu verweisen WinRTtest C:\Dataport\transfer\WinRTtest\WinRTtest\main.cpp 17
The problem is easy to find. My compiler recreates "Windows.Mangement.2.h" and generated the following code:
// WARNING: Please don't edit this file. It was generated by C++/WinRT v2.0.220531.1
#pragma once
#ifndef WINRT_Windows_Management_2_H
#define WINRT_Windows_Management_2_H
#include "winrt/impl/Windows.Management.1.h"
WINRT_EXPORT namespace winrt::Windows::Management
{
struct __declspec(empty_bases) MdmAlert : winrt::Windows::Management::IMdmAlert
{
MdmAlert(std::nullptr_t) noexcept {}
MdmAlert(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Management::IMdmAlert(ptr, take_ownership_from_abi) {}
MdmAlert();
};
struct __declspec(empty_bases) MdmSession : winrt::Windows::Management::IMdmSession
{
MdmSession(std::nullptr_t) noexcept {}
MdmSession(void* ptr, take_ownership_from_abi_t) noexcept : winrt::Windows::Management::IMdmSession(ptr, take_ownership_from_abi) {}
};
struct MdmSessionManager
{
MdmSessionManager() = delete;
[[nodiscard]] static auto SessionIds();
static auto TryCreateSession();
static auto DeleteSessionById(param::hstring const& sessionId);
static auto GetSessionById(param::hstring const& sessionId);
};
}
#endif
The headache comes from the following line of code:
"MdmSessionManager() = delete;"
To make the program compile, I commented this line out. Yes, I know and I read the warning: "// WARNING: Please don’t edit this file. It was generated by C++/WinRT v2.0.220531.1"
The question is: "Why does winrt generates the MdmSessionManager and deletes its constructor? If I just change it and compile the project, it works. (until I do a full recompile) This is very inconvenient.
Might this be a bug in the c++ winrt language projection? Am I doing something wrong?
I would expect the language projection to make it possible to construct a "MdmSessionManager" so it can be used in code. It does not feel right to delete it’s constructor. Perhaps this is done for a certain reason. It would be nice if somebody can explain the reason behind it.
>Solution :
MdmSessionManager contains static class members exclusively. As such it is not intended to be instantiated, hence its default constructor is delete-d.
To access its class members you’ll need to use the qualified name, e.g.
auto session = winrt::Windows::Management::MdmSessionManager::TryCreateSession();