0

I want to get a list of installed MIDI Devices in Windows 10, using the Windows 10 UWP MIDI API. This article shows example code to get a list of MIDI devices and their IDs, using C#:

using Windows.Devices.Midi;
using Windows.Devices.Enumeration;
...
private async void ListMidiDevices()
{
    // Enumerate Input devices

    var deviceList = DeviceInformation.FindAllAsync(
             MidiInPort.GetDeviceSelector());

    foreach (var deviceInfo in deviceList)
    {
        Console.WriteLine(deviceInfo.Id);
        Console.WriteLine(deviceInfo.Name);
        Console.WriteLine("----------");
    }

    // Output devices are enumerated the same way, but 
    // using MidiOutPort.GetDeviceSelector()
}

I tried inserting the code for ListMidiDevices in the Visual Studio Community 2015 "Hello World" example program. I put the code block in place of Console.WriteLine("Hello World!"); in the "hello world" console example. I added the "using" statements above in the proper place.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Windows.Devices.Midi;
using Windows.Devices.Enumeration;

namespace ConsoleApplicationHelloWorld
{
    class Program
    {
        static void Main(string[] args)
        {
            // Enumerate Input devices

            var deviceList = await DeviceInformation.FindAllAsync(
                     MidiInPort.GetDeviceSelector());

            foreach (var deviceInfo in deviceList)
            {
                System.Diagnostics.Debug.WriteLine(deviceInfo.Id);
                System.Diagnostics.Debug.WriteLine(deviceInfo.Name);
                System.Diagnostics.Debug.WriteLine("----------");
            }

            // Output devices are enumerated the same way, but 
            // using MidiOutPort.GetDeviceSelector()        }
        }
    }

Edit - VS wasn't building the UWP type. I upgraded to VS Community 2019, and installed ConsoleAppUniversal.vsix. Then I could create a new project - Console App C# Universal:

using System;
using Windows.Devices.Midi;
using Windows.Devices.Enumeration;

// This example code shows how you could implement the required main function for a 
// Console UWP Application. You can replace all the code inside Main with your own custom code.

// You should also change the Alias value in the AppExecutionAlias Extension in the 
// Package.appxmanifest to a value that you define. To edit this file manually, right-click
// it in Solution Explorer and select View Code, or open it with the XML Editor.

namespace ConsoleAppCsharpUniversal
{
    class Program
    {
        static void Main(string[] args)
        {
            if (args.Length == 0)
            {
                Console.WriteLine("starting - no args");

                // Enumerate Input devices

                var deviceList =  DeviceInformation.FindAllAsync(
                         MidiInPort.GetDeviceSelector());

                foreach (var deviceInfo in deviceList)
                {
                    Console.WriteLine(deviceInfo.Id);
                    Console.WriteLine(deviceInfo.Name);
                    Console.WriteLine("----------");
                }
                Console.WriteLine("finish - no args");


            }
            else
            {
                for (int i = 0; i < args.Length; i++)
                {
                    Console.WriteLine($"arg[{i}] = {args[i]}");
                }
            }
            Console.WriteLine("Press a key to continue: ");
            Console.ReadLine();
        }
    }
}

Now the only remaining error is "foreach statement cannot operate on variables of type IAsyncOperation<DeviceInformationCollection> because IAsyncOperation<DeviceInformationCollection> does not contain a public instance definition for GetEnumerator"

Is there another way to access the device information without using an async method?

Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91
tim11g
  • 1,935
  • 5
  • 27
  • 41
  • Can you use an `async` helper method and just have `Main` wait for it to finish? Otherwise you should be able to manually hook things up but it's easier to just use `await`. Also, if the MIDI APIs need to show any kind of consent UI (*I don't know if they do or not*) then a console app won't work, since the prompts require a `CoreWindow` (at least today). – Peter Torr - MSFT Jan 06 '20 at 01:43

1 Answers1

0

You have to make sure your project is targeting at least C# 7.1 (I think the template does have this out-of-the-box in VS 2019) and use the async Main method feature:

Your method signature will change to:

public static async Task Main(string[] args)
{
   ...
}

And then you need to await the FindAllAsync method:

var deviceList = await DeviceInformation.FindAllAsync(
                         MidiInPort.GetDeviceSelector());

Note: You can change the C# version by opening the csproj file in a text editor and adding the following into a <PropertyGroup>:

<LangVersion>7.1</LangVersion>

or even (if you want the latest features):

<LangVersion>latest</LangVersion>
Martin Zikmund
  • 38,440
  • 7
  • 70
  • 91