0

I have a C# Class Library, that reads Bluetooth LE Characteristics. I want to use this DLL to get the read values in my VB6 app. My Problem is: I need the complete code to get the result. That means i have to call the main function from my VB6 program, but i have no idea what parameters i have to use and how i can get the right return value. My Dll:

 using SDKTemplate;
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using Windows.Storage.Streams;
using System.Threading.Tasks;
using System.Runtime.Remoting.Messaging;
using System.Runtime.InteropServices;
namespace BleSirLo
{
    public class Program
    {

        public byte[] ret = new byte[6];
        static void Main(string[] args)
        {
            Task t = MainAsync(args);
            t.Wait();
            // or, if you want to avoid exceptions being wrapped into AggregateException:
            //  MainAsync().GetAwaiter().GetResult();
        }

        static async Task MainAsync(string[] args)
        {
            Program p = new Program();
            p.StartBleDeviceWatcher();
        }
            
        private List<DeviceInformation> UnknownDevices = new List<DeviceInformation>();
        private List<DeviceInformation> _knownDevices = new List<DeviceInformation>();
        private IReadOnlyList<GattCharacteristic> characteristics;
        private IReadOnlyList<GattDeviceService> services;

        private GattDeviceService currentSelectedService = null;
        private GattCharacteristic currentSelectedCharacteristic = null;

        private DeviceWatcher deviceWatcher;

        public bool done = false;

        private void StartBleDeviceWatcher()
        {
            // Additional properties we would like about the device.
            // Property strings are documented here https://msdn.microsoft.com/en-us/library/windows/desktop/ff521659(v=vs.85).aspx
            string[] requestedProperties = { "System.Devices.Aep.DeviceAddress", "System.Devices.Aep.IsConnected", "System.Devices.Aep.Bluetooth.Le.IsConnectable" };

            // BT_Code: Example showing paired and non-paired in a single query.
            string aqsAllBluetoothLEDevices = "(System.Devices.Aep.ProtocolId:=\"{bb7bb05e-5972-42b5-94fc-76eaa7084d49}\")";

            deviceWatcher =
                    DeviceInformation.CreateWatcher(
                        aqsAllBluetoothLEDevices,
                        requestedProperties,
                        DeviceInformationKind.AssociationEndpoint);

            // Register event handlers before starting the watcher.
            deviceWatcher.Added += DeviceWatcher_Added;
            deviceWatcher.Updated += DeviceWatcher_Updated;
            deviceWatcher.Removed += DeviceWatcher_Removed;
            deviceWatcher.EnumerationCompleted += DeviceWatcher_EnumerationCompleted;
            deviceWatcher.Stopped += DeviceWatcher_Stopped;

            // Start over with an empty collection.
            _knownDevices.Clear();
            //deviceWatcher.Stop();
            deviceWatcher.Start();
            while(true)
                if (done == true)
                    break;

        }

        private void DeviceWatcher_Added(DeviceWatcher sender, DeviceInformation deviceInfo)
        {
            //Debug.WriteLine(String.Format("Device Found!" + Environment.NewLine + "ID:{0}" + Environment.NewLine + "Name:{1}", deviceInfo.Id, deviceInfo.Name));

            //notify user for every device that is found
            if (sender == deviceWatcher)
            {
                if ((deviceInfo.Name == "Ei Gude, wie?") || (deviceInfo.Name == "Ei Gude, Wie?"))
                {
                    sender.Stop();
                    ConnectDevice(deviceInfo);
                }
            }
        }
        private void DeviceWatcher_Updated(DeviceWatcher sender, DeviceInformationUpdate deviceInfo)
        {
        }
        private void DeviceWatcher_Removed(DeviceWatcher sender, DeviceInformationUpdate deviceInfo)
        {
        }
        private void DeviceWatcher_EnumerationCompleted(DeviceWatcher sender, object args)
        {
        }
        private void DeviceWatcher_Stopped(DeviceWatcher sender, object args)
        {
        }

        //trigger StartBleDeviceWatcher() to start bluetoothLe Operation
        private void Scan()
        {
            //empty devices list
            _knownDevices.Clear();
            UnknownDevices.Clear();

            //finally, start scanning
            StartBleDeviceWatcher();
        }

        private async void ConnectDevice(DeviceInformation deviceInfo)
        {
            //get bluetooth device information
            BluetoothLEDevice bluetoothLeDevice = await BluetoothLEDevice.FromIdAsync(deviceInfo.Id);
            //Respond(bluetoothLeDevice.ConnectionStatus.ToString());

            //get its services
            GattDeviceServicesResult result = await bluetoothLeDevice.GetGattServicesAsync();

            //verify if getting success 
            if (result.Status == GattCommunicationStatus.Success)
            {
                //store device services to list
                services = result.Services;

                //loop each services in list
                foreach (var serv in services)
                {
                    //get serviceName by converting the service UUID
                    string ServiceName = Utilities.ConvertUuidToShortId(serv.Uuid).ToString();

                    //if current servicename matches the input service name
                    if (ServiceName == "65520") //ServiceTxtBox.Text)
                    {
                        //store the current service
                        currentSelectedService = serv;

                        //get the current service characteristics
                        GattCharacteristicsResult resultCharacterics = await serv.GetCharacteristicsAsync();

                        //verify if getting characteristics is success 
                        if (resultCharacterics.Status == GattCommunicationStatus.Success)
                        {
                            //store device services to list
                            characteristics = resultCharacterics.Characteristics;

                            //loop through its characteristics
                            foreach (var chara in characteristics)
                            {
                                //get CharacteristicName by converting the current characteristic UUID
                                string CharacteristicName = Utilities.ConvertUuidToShortId(chara.Uuid).ToString();

                                //if current CharacteristicName matches the input characteristic name
                                if (CharacteristicName == "65524")//CharacteristicsTxtBox.Text)
                                {
                                    //store the current characteristic
                                    currentSelectedCharacteristic = chara;
                                    //stop method execution
                                    readBuffer();
                                    return;
                                }
                            }
                        }
                    }
                }
            }
        }

        //function that handles the read button event
        private async void readBuffer()
        {
            {
                if (currentSelectedService != null && currentSelectedCharacteristic != null)
                {
                    GattCharacteristicProperties properties = currentSelectedCharacteristic.CharacteristicProperties;

                    //if selected characteristics has read property
                    if (properties.HasFlag(GattCharacteristicProperties.Read))
                    {
                        //read value asynchronously
                        GattReadResult result = await currentSelectedCharacteristic.ReadValueAsync();
                        if (result.Status == GattCommunicationStatus.Success)
                        {
                            int a, b, c, d, e, f;
                            var reader = DataReader.FromBuffer(result.Value);
                            //byte [] input = new byte[reader.UnconsumedBufferLength];
                            reader.ReadBytes(ret);
                            a = ret[0];
                            b = ret[1];
                            c = ret[2];
                            d = ret[3];
                            e = ret[4];
                            f = ret[5];
                            Ret_val(ret);
                        }

                    }
                }
            }
        }

        private void Response_TextChanged(object sender, EventArgs e)
        {

        }
 }

In my VB6 program I call the Library like this: (It is obviously not working, but i dont know how i should do it.

    Dim WithEvents CSharpInteropServiceEvents As CSharpInteropService.LibraryInvoke
      Dim load As New LibraryInvokeparam(0) = Me.hwnd
Dim sa as variant
        Set CSharpInteropServiceEvents = load
        sa = load.GenericInvoke("C:\Program Files (x86)\Microsoft Visual Studio\VB98\WINCOM\BleSirLo.dll", "BleSirLo.Program", "Main", param)
StayOnTarget
  • 11,743
  • 10
  • 52
  • 81
Static
  • 87
  • 8
  • Try to use [regasm](https://stackoverflow.com/a/3843526/1997232). – Sinatr Aug 03 '20 at 07:30
  • @Sinatr Thx for your answer! I know about regasm and i already registered the library. If i return set values i can read them out. But my problem is returning the read values from the reader function: reader.ReadBytes(ret); – Static Aug 03 '20 at 07:39
  • What i need is a was to get the read values in VB6. Maybe i can somehow let the main in my Class library run in the background and readout the results every second or so. – Static Aug 03 '20 at 08:45
  • Similar to `Main` you can add easy to use with interop synchronous methods to C#: in one you start communications and another one to return received data if any (it can be blocking and with timeout). Then just poll second one using timer or in dedicated thread. Though you can try to dive more into [events](https://stackoverflow.com/q/7075497/1997232) and such. – Sinatr Aug 03 '20 at 09:14
  • @Sinatr Can you explain to me what exactly you mean with "easy to use with interop synchronous methods"? Im new to the subject and not really familiar with the terms. – Static Aug 03 '20 at 09:32
  • What I mean is simply add synchronous methods, which can be called from outside. I don't have experience with VB6 specifically, so I can't help you with how to call c# method. [Here](https://stackoverflow.com/a/13997232/1997232) is answer to similar question. Try it out. – Sinatr Aug 03 '20 at 09:44
  • The problem with synchronous methods is, that i cant call ReadValueAsync() function, that i need for reading GATT characteristics. I found no synchronous method for reading – Static Aug 03 '20 at 09:54
  • I specifically mention to make those methods *synchronous* to avoid any hassle of passing `Task` around. Look [here](https://stackoverflow.com/q/9343594/1997232) for hints of how to do it. – Sinatr Aug 03 '20 at 10:35
  • @Sinatr Thanks for the link, it was helpful. But i have a final questen: In my ReadBuffer method, which is async, i need to return the read value. Even by making it synchronous with WaitAndUnwrapException, i still cant get a return value because the method has to be async. I think there is something that I dont understand. – Static Aug 03 '20 at 12:16

0 Answers0