Using Visual Studio 2019 16.10.2 how do you include .NET components in a C++ / WinRT Console programme?
The indexOf method of IVector requires a UInt32 struct from System.
How is the System utilised in this context? Trying to use the namespace results in a
"System' : a namespace with this name does not exist"
This has been covered already on SO, but only for a C++/CLI application and not in the context of a C++/WinRT console app. The solutions provided in that post also do not work.
#include "pch.h"
#include <Windows.h>
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
using winrt::Windows::Foundation::Collections::IVector;
using namespace System;
int main()
{
IVector<int> foo;
foo.Append(1);
UInt32 bar;
foo.indexOf(1, bar);
return EXIT_SUCCESS;
}
In this case pch.h is empty.
When you select the appropriate language from the documentation's language dropdown list in the top right corner (C++/WinRT) you'll see the C++/WinRT-specific signature:
bool IndexOf(T const& value, uint32_t & index);
You'll need to replace
UInt32 bar;
with
uint32_t bar{};
Related
I've been hiding under the MFC rock for many years so I can stick to standard C++ but still write Windows Desktop apps. With C++/WinRT and WinUI 3.0, it appears that I may finally have an opportunity to modernize my code. The problem is that I know nothing about XAML or the Windows API. To fix this problem, I'm trying to work my way through Petzold's "Programming Windows, 6th ed.", replacing the C# code with C++/WinRT. When all I have to do is write XAML, all is copacetic. However, when I get to p. 24, I'm supposed to adjust TextBlock properties in code. Here's the C#:
TextBlock tb = new TextBlock();
tb.Text = "Hello, Windows 8!";
tb.FontFamily = new FontFamily("Times New Roman");
tb.FontSize = 96;
tb.FontStyle = FontStyle.Italic;
...
and here's my attempt at a replacement:
TextBlock tb;
tb.Text(L"Hello, Windows 8!");
tb.FontFamily(FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(FontStyle::Italic);
...
All goes well until the last line. "FontStyle::Italic" is not recognized. I have similar issues with the enums for Color and HorizontalAlignment. What is the correct way to access these enums? Have I forgotten an include or a "using"? Here's what I currently have:
#include <winrt/Windows.Foundation.h>
#include <winrt/Windows.Foundation.Collections.h>
#include <winrt/Windows.ApplicationModel.Activation.h>
#include <winrt/Microsoft.UI.Composition.h>
#include <winrt/Microsoft.UI.Text.h>
#include <winrt/Microsoft.UI.Xaml.h>
#include <winrt/Microsoft.UI.Xaml.Controls.h>
#include <winrt/Microsoft.UI.Xaml.Controls.Primitives.h>
#include <winrt/Microsoft.UI.Xaml.Data.h>
#include <winrt/Microsoft.UI.Xaml.Interop.h>
#include <winrt/Microsoft.UI.Xaml.Markup.h>
#include <winrt/Microsoft.UI.Xaml.Media.h>
#include <winrt/Microsoft.UI.Xaml.Navigation.h>
#include <winrt/Microsoft.UI.Xaml.Shapes.h>
and
using namespace winrt;
using namespace Microsoft::UI::Text;
using namespace Microsoft::UI::Xaml::Controls;
using namespace Microsoft::UI::Xaml::Controls::Primitives;
using namespace Microsoft::UI::Xaml::Media;
I hope there's a short answer to my long question.
To be sure, you'd need to post a little more detail (like what error message you're getting). But I'll take a guess that perhaps your code is missing a namespace qualifier. I'm just going off the UWP Windows namespace types, not the WinUI Microsoft namespace, but this code builds for me:
#include <winrt/Windows.UI.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Media.h>
void f()
{
winrt::Windows::UI::Xaml::Controls::TextBlock tb;
tb.Text(L"Hello");
tb.FontFamily(winrt::Windows::UI::Xaml::Media::FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(winrt::Windows::UI::Text::FontStyle::Italic);
tb.SelectionHighlightColor(winrt::Windows::UI::Xaml::Media::SolidColorBrush(winrt::Windows::UI::Colors::Red()));
tb.HorizontalAlignment(winrt::Windows::UI::Xaml::HorizontalAlignment::Center);
}
As does this:
#include <winrt/Windows.UI.h>
#include <winrt/Windows.UI.Text.h>
#include <winrt/Windows.UI.Xaml.h>
#include <winrt/Windows.UI.Xaml.Controls.h>
#include <winrt/Windows.UI.Xaml.Media.h>
using namespace winrt;
using namespace winrt::Windows::UI;
using namespace winrt::Windows::UI::Text;
using namespace winrt::Windows::UI::Xaml;
using namespace winrt::Windows::UI::Xaml::Controls;
using namespace winrt::Windows::UI::Xaml::Media;
void f()
{
TextBlock tb;
tb.Text(L"Hello");
tb.FontFamily(FontFamily(L"Times New Roman"));
tb.FontSize(96);
tb.FontStyle(FontStyle::Italic);
tb.SelectionHighlightColor(SolidColorBrush(Colors::Red()));
tb.HorizontalAlignment(HorizontalAlignment::Center);
}
In an attempt to incorporate a windows platform feature into an otherwise crossplatform application, I've made a one-function VC++ DLL in visual studio that uses Windows.Management.Deployment.PackageManager to get some details on all installed windows store apps.
The function works fine as a standalone application, and I can successfully build the DLL with MSVC that links properly with my MinGW main application (I can happily return primitive data from the dll, etc) - but any attempt to execute a function from the dll containing code relating to PackageManager crashes my application in runtime with the unhelpful code -529697949.
Here's some minimal code blocks that replicate:
main.cpp in the main application:
#include <QCoreApplication>
#include "mylib/WindowsAppsLib.h"
#include <QDebug>
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
auto hi = (Helpers::sayHi());
qDebug() << (hi);
return a.exec();
}
dll header:
#pragma once
#define WINDOWSAPPSLIB_API __declspec(dllexport)
namespace Helpers
{
extern "C" WINDOWSAPPSLIB_API const char* sayHi();
}
dll source:
#include "stdafx.h"
#include <sddl.h>
#include <collection.h>
#include "WindowsAppsLib.h"
#include <windows.h>
#using <Windows.winmd>
using namespace Platform;
using namespace Windows::Foundation;
using namespace Windows::Foundation::Collections;
using namespace std;
const char* Helpers::sayHi()
{
auto packageManager = ref new Windows::Management::Deployment::PackageManager();
auto packages = packageManager->FindPackages();
return "Hi!";
}
Without the two lines relating to packagemanger, the program runs fine and prints "Hi!". When included, the program crashes with code -529697949 as soon as sayHi() is called. The two lines in themselves have their dependencies available and don't cause exceptions.
Any clues on how I might proceed to investigate this? Nothing I've been able to get out of this system is getting me closer to identifying the problem. Is this the sensible way to access Windows.Management.Deployment.PackageManager from within a plain C++ MinGW application to begin with?
Intro
First of all, I would like to say that I have read through the previous answers for this type of question, including this excellently written one.
However, I do not understand enough about C++ to be able to use the more "advanced" fixes.
I have ensured that the right type of console has been selected (Console (/SUBSYSTEM:CONSOLE) for those interested), and have the required imports with the possible exception of an IDL mentioned somewhere (that falls into the lack of understanding category).
If this is a duplicate, I would be more than happy to use the post I duplicated, but I have not been able to find anything that can help someone of my skill level.
Technical Information
IDE: Visual Studio
Platform: Windows
Code
headers.h
#pragma once
#include <stdio.h>
#include <iostream>
#include <string>
#include <windows.h>
#include <Shobjidl.h>
#include <time.h>
#include <stdlib.h>
#include <tchar.h>
main.cpp
#include "headers.h"
using namespace std;
int main() {
string x = "C://Users/student/Desktop/i-should-buy-a-boat.jpg";
x.c_str();
wstring tempx = std::wstring(x.begin(), x.end());
LPCWSTR sw = tempx.c_str();
HRESULT SetWallpaper(
LPCWSTR monitorID,
LPCWSTR wallpaper
);
SetWallpaper(NULL, sw);
}
SetWallpaper() is not a standalone function exported by the Win32 API. It is a method of the IDesktopWallpaper interface (see here).
So you need to use code that is more like this instead:
#include "headers.h"
int main()
{
std::wstring x = L"C:\\Users\\student\\Desktop\\i-should-buy-a-boat.jpg";
CoInitialize(NULL);
IDesktopWallpaper *p;
if (SUCCEEDED(CoCreateInstance(__uuidof(DesktopWallpaper), 0, CLSCTX_LOCAL_SERVER, __uuidof(IDesktopWallpaper), (void**)&p)))
{
p->SetWallpaper(NULL, x.c_str());
p->Release();
}
CoUninitialize();
return 0;
}
How to Add Timeout for a test method in C++ in Microsoft unit testing using CppUnitTestFramework ? Most of the Solutions I found online are for CSharp projects where I can add lines like [TEST_METHOD,TIME_OUT(80)] or such ,but those are not working while testing C++ (VC++) code
I have tried the below code
#include "stdafx.h"
#include "CppUnitTest.h"
#include "../src/factorial_dp.cpp"
#include "stdio.h"
using namespace Microsoft::VisualStudio::CppUnitTestFramework;
namespace spec
{
TEST_CLASS(factorial_dpSpec)
{
public:
//Add Timout for these methods
TEST_METHOD(Smallnumber)
{
int result = fact(5);
Assert::AreEqual(120, result, L"5 fact should be 120", LINE_INFO());
}
};
}
Use managed test classes.
and you can keep Timeouts in that .
[TestMethod(), Timeout(3000)]
void functionName()
{
//
}
PLEASE SEE UPDATE BELOW
(RESOLVED) Also I have extended this into a second question here Implement a C# DLL COM File In Unmanaged C++ Program
I have researched this to the end of the internet without finding a real, understandable, human example of how to do this.
I have a C# DLL that encrypts and decrypts text.
I don't want to / don't have the intellectual capability to rewrite this in C++ un-managed code. So instead I created a C++/CLR class that interfaces with the C# dll.
NOW I need to know how to call the managed C++ from my unmanaged code.
Here is my managed code and it is verified that it works
// clrTest.cpp : main project file.
#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>
using namespace cSharpRiJHarn;
using namespace System;
String^ Encrypt(String ^s)
{
return RijndaelLink::encrypt(s);
}
String^ Decrypt(String ^s)
{
return RijndaelLink::decrpyt(s);
}
int main()
{
//Console::WriteLine(Encrypt("It Works"));
//Console::WriteLine(Decrypt(Encrypt("It Works")));
//Console::ReadLine();
return 0;
}
Now ONCE AGAIN I HAVE researched this.
I have seen allllllll the bad/overly complicated explanations
I know I need to use something called COM or Interop
I don't know how this works and I am just looking for a very simple explanation.
Thanks for the help.
UPDATE
I have turned the C# DLL into a COM File
using System;
using System.Runtime.InteropServices;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace cSharpRiJHarn
{
[Guid("GuiD CODE REMOVED")]
public interface DBCOM_Interface
{
[DispId(1)]
String encrypt(string s);
[DispId(2)]
String decrpyt(string s);
}
[Guid("GuiD CODE REMOVED"),
InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface DBCOM_Events
{
}
[Guid("GuiD CODE REMOVED"),
ClassInterface(ClassInterfaceType.None),
ComSourceInterfaces(typeof(DBCOM_Events))]
public class RijndaelLink : DBCOM_Interface
{
public String encrypt(String s)
{
return Rijndael.EncryptString(s);
}
public String decrpyt(String s)
{
return Rijndael.DecryptString(s);
}
}
}
Now I am just need to know how to implement this in unmanaged C++...
I have tried both adding just the files to the C++ project and also adding the entire cSharpRiJHarn Project to this solution. Neither work.
#import "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include <iostream>
//using namespace cSharpRiJHarn;
int main(){
cSharpRiJHarn::RijndaelLink::encrypt("It works");
char ch;
std::cin>>ch;
return 0;
}
This is one of the errors I am getting.
Error 6 error C2653: 'cSharpRiJHarn' : is not a class or namespace
name
and
Error 8 IntelliSense: cannot open source file
"C:/.../.../Documents/Visual Studio
2010/Projects/unmannagedCPPExample/unmannagedCPPExample/Debug/cSharpRiJHarn.tlh" c:......\documents\visual
studio
2010\projects\unmannagedcppexample\unmannagedcppexample\unmannagedcppexample.cpp
You could use the cool C++ Marshaling library provided by Microsoft, something like this:
#include "cSharpRiJHarn"
#include "stdafx.h"
#include <string>
#include <stdio.h>
#include "msclr\marshal_cppstd.h" // marshaling library
using namespace cSharpRiJHarn;
using namespace System;
using namespace msclr::interop; // marshaling library
std::wstring Encrypt(std::wstring s)
{
return marshal_as<std::wstring>(RijndaelLink::encrypt(marshal_as<String^>(s)));
}
std::wstring Decrypt(std::wstring s)
{
return marshal_as<std::wstring>(RijndaelLink::decrypt(marshal_as<String^>(s)));
}
First, your methods receive and return a String^ which is a managed object. Unmanaged code does not know this type, and cannot create such object. So, you will need to wrap the function call such that the function marshal the managed type to something that the unmanaged code can understand.
After that, you can add the DllExport attribute to the managed method, as discussed here.