StealthRT
StealthRT

Reputation: 10542

WinRT app calling win32 c++ dll sending parameters

Hey all this is the first time working with C++ so be kind :)

I have made a WinRT app that, since of some type of "sandbox" it does for those apps I am unable to access anything outside of that (like what I want to access - my desktop app.

So reading here and there I found out that if you make a C++ Dll and call it from the WinRT app then that would allow you to make calls outside of the "sandbox". But there's a little problem there.

I am currently getting an error of:

Error CS1660 Cannot convert lambda expression to type 'string' because it is not a delegate type.

Using this code here:

void Header_Click(object sender, RoutedEventArgs e)
{
    DisplayFromDLL("tester", s =>
    {
        // response is returned in s - do what you want with it
    });
}

The DisplayFromDLL is where its tossing that error from. More so the "s".

So the C# code I have to call the dll with looks like this:

public sealed partial class GroupedItemsPage : Page
{
    [DllImport("Win32Project1.dll", EntryPoint = "DisplayFromDLL", CallingConvention = CallingConvention.StdCall)]
    public static extern void DisplayFromDLL(string name, String response);

    void Header_Click(object sender, RoutedEventArgs e)
    {
        DisplayFromDLL("tester", s =>
        {
            // response is returned in s
        });
    }

And the C++ dll code:

extern "C"
{
    __declspec(dllexport) void DisplayFromDLL(const char name)
    {
        MessageBox("name is: " + name, "Msg title", MB_OK | MB_ICONQUESTION);
    }
}

So some help would be great to see what side is causing the error and what the situation fixing it might be.

Upvotes: 0

Views: 365

Answers (3)

Seva Alekseyev
Seva Alekseyev

Reputation: 61361

If the limitations of the UWP sandbox get in the way of your design, develop a desktop application. For the platform that's closest to UWP in terms of UI design, go for WPF. You can still publish it to the store, via the Desktop Bridge.

Upvotes: 0

StealthRT
StealthRT

Reputation: 10542

Well I think I found a good way to achieve my goal here.

I have added a simple, small Web Server in C# that WinRT can call. Doing this call allows me to run anything I need to outside the sandbox of the WinRT application.

This is the web server C# code (SimpleWebServer.cs):

using System;
using System.Net;
using System.Text;
using System.Threading;

namespace smallWS
{
    public class WebServer
    {
        private readonly HttpListener _listener = new HttpListener();
        private readonly Func<HttpListenerRequest, string> _responderMethod;

        public WebServer(string[] prefixes, Func<HttpListenerRequest, string> method)
        {
            if (!HttpListener.IsSupported)
                throw new NotSupportedException("Needs Windows XP SP2, Server 2003 or later.");

            if (prefixes == null || prefixes.Length == 0)
                throw new ArgumentException("prefixes");

            if (method == null)
                throw new ArgumentException("method");

            foreach (string s in prefixes)
                _listener.Prefixes.Add(s);

            _responderMethod = method;
            _listener.Start();
        }

        public WebServer(Func<HttpListenerRequest, string> method, params string[] prefixes)
            : this(prefixes, method) { }

        public void Run()
        {
            ThreadPool.QueueUserWorkItem((o) =>
            {
                Console.WriteLine("Webserver running...");
                try
                {
                    while (_listener.IsListening)
                    {
                        ThreadPool.QueueUserWorkItem((c) =>
                        {
                            var ctx = c as HttpListenerContext;
                            try
                            {
                                string rstr = _responderMethod(ctx.Request);
                                byte[] buf = Encoding.UTF8.GetBytes(rstr);
                                ctx.Response.ContentLength64 = buf.Length;
                                ctx.Response.OutputStream.Write(buf, 0, buf.Length);
                            }
                            catch { }
                            finally
                            {
                                ctx.Response.OutputStream.Close();
                            }
                        }, _listener.GetContext());
                    }
                }
                catch { }
            });
        }

        public void Stop()
        {
            _listener.Stop();
            _listener.Close();
        }
    }
}

And also the Program.cs:

using System;
using System.Diagnostics;
using System.Linq;
using System.Net;

namespace smallWS
{
    class Program
    {
        static void Main(string[] args)
        {
            WebServer ws = new WebServer(SendResponse, "http://localhost:8080/metroData/");
            ws.Run();
            Console.WriteLine("Webserver online. Press a key to quit.");

            Console.ReadKey();
            ws.Stop();
        }

        public static string SendResponse(HttpListenerRequest request)
        {
            Process.Start("C:\\windows\\system32\\notepad.exe");
            var dictionary = request.RawUrl.Replace("/metroData/", "").Replace("?", "").Split('&').ToDictionary(x => x.Split('=')[0], x => x.Split('=')[1]);
            return string.Format("<HTML><BODY>My web page.<br>{0}</BODY></HTML>", DateTime.Now);
        }
    }
}

And now GroupedItemsPage.xaml:

String mainURL = "http://localhost:8080/metroData/?";

async void Header_Click(object sender, RoutedEventArgs e)
    {
        var group = (sender as FrameworkElement).DataContext;

        HttpClient httpClient = new HttpClient();
        HttpResponseMessage response = await httpClient.GetAsync(new Uri(mainURL + "something=here&this=that"));
        string responseText = await response.Content.ReadAsStringAsync();
    }

Upvotes: 0

SoronelHaetir
SoronelHaetir

Reputation: 15162

Your definition (in the DLL), the declaration (on the c# side) and the actual calls do not match at all.

Your function as defined takes a single char, your declaration says it takes two strings, but your call provides a string and a function.

Make it so that all of these match.

Upvotes: 1

Related Questions