Home > Back-end >  How to Start and Stop Windows Audio/Video Recorder from C#?
How to Start and Stop Windows Audio/Video Recorder from C#?

Time:01-01

I would like to start and stop the audio and video screen recording function in Windows programmatically in C#/.NET 6 - preferably in a console program.

Manually, this can be done by holding down the Windows/Menu key and the ALT-key while pressing R on the keyboard.

I have tried to use the user32.dll and InterOp to send Alt (MENU) LWIN R key without success. Since I have a GeForce ShadowPlay-enabled video card, I have also tried to capture video sending Alt F9, but this also fails.

I do NOT want to encode the audio and video in the program, just start and stop the Windows Audio/Video Recording. Is there an API for this in Windows or any other way to start/stop recording?

using System.Runtime.InteropServices;

namespace StartStopWindowsBuiltInAudioVideoRecorder
{
    internal class NativeWin32
    {
        public const ushort KEYEVENTF_KEYUP = 0x0002;

        public enum VK : ushort
        {
            MENU = 0x12,
            F9 = 0x78,
            R = 0x52,
            LWIN = 0x5B,
        }

        public struct KEYBDINPUT
        {
            public ushort wVk;
            public ushort wScan;
            public uint dwFlags;
            public long time;
            public uint dwExtraInfo;
        };

        [StructLayout(LayoutKind.Explicit, Size = 28)]
        public struct INPUT
        {
            [FieldOffset(0)] public uint type;
            [FieldOffset(4)] public KEYBDINPUT ki;
        };

        [DllImport("user32.dll")]
        public static extern uint SendInput(uint nInputs, ref INPUT pInputs, int cbSize);

        // Method will hold down Windows and Left Alt while pressing R
        internal static void StartOrStopVideoRecorder()
        {
            NativeWin32.INPUT structInput;
            structInput = new NativeWin32.INPUT();
            structInput.type = (uint)1;
            structInput.ki.wScan = 0;
            structInput.ki.time = 0;
            structInput.ki.dwFlags = 0;
            structInput.ki.dwExtraInfo = 0;

            //Press Alt key
            structInput.ki.wVk = (ushort)NativeWin32.VK.MENU;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
            Thread.Sleep(100);

            //Press LeftWin key
            structInput.ki.wVk = (ushort)NativeWin32.VK.LWIN;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
            Thread.Sleep(100);

            //Press the R key
            structInput.ki.wVk = (ushort)NativeWin32.VK.R;//vk;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
            Thread.Sleep(500);

            //Release the R key
            structInput.ki.dwFlags = NativeWin32.KEYEVENTF_KEYUP;
            structInput.ki.wVk = (ushort)NativeWin32.VK.R;//vk;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
            Thread.Sleep(100);

            //Release LeftWin key
            structInput.ki.wVk = (ushort)NativeWin32.VK.LWIN;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
            Thread.Sleep(100);

            //Release the ALT key
            structInput.ki.wVk = (ushort)NativeWin32.VK.MENU;
            NativeWin32.SendInput((uint)1, ref structInput, Marshal.SizeOf(structInput));
        }
    }
}

I expected the code to start the audio/video recording, but nothing happens. Other software reacts to these keys if configured to listen for them, so the NativeWin32 API still works as it should.

CodePudding user response:

You were missing a few stuff, first of all

SendInput(uint nInputs, INPUT[] pInputs, int cbSize);

Sendinput expects an input array with: MouseInput,KeyboardInput,HardwareInput

In the mouse input dwExtraInfo is a IntPtr public readonly IntPtr dwExtraInfo;

You were using SendInput with ref which should also not be used as far as I know. SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));

Also the Thread.Sleeps are useless, but thats irrelevant.

public const ushort KEYEVENTF_KEYUP = 0x0002;

    public enum VK : ushort
    {
        MENU = 0x12,
        F9 = 0x78,
        R = 0x52,
        LWIN = 0x5B,
    }

    public struct KEYBDINPUT
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public long time;
        public uint dwExtraInfo;
    };

    public struct INPUT
    {
        public int type;
        public InputUnion u;
    }

    [StructLayout(LayoutKind.Explicit)]
    public struct InputUnion
    {
        [FieldOffset(0)] public readonly MouseInput mi;
        [FieldOffset(0)] public KeyboardInput ki;
        [FieldOffset(0)] public readonly HardwareInput hi;
    }
    [StructLayout(LayoutKind.Sequential)]
    public struct MouseInput
    {
        public readonly int dx;
        public readonly int dy;
        public readonly uint mouseData;
        public readonly uint dwFlags;
        public readonly uint time;
        public readonly IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct KeyboardInput
    {
        public ushort wVk;
        public ushort wScan;
        public uint dwFlags;
        public readonly uint time;
        public IntPtr dwExtraInfo;
    }

    [StructLayout(LayoutKind.Sequential)]
    public struct HardwareInput
    {
        public readonly uint uMsg;
        public readonly ushort wParamL;
        public readonly ushort wParamH;
    }

    [DllImport("user32.dll", SetLastError = true)]
    private static extern uint SendInput(uint nInputs, INPUT[] pInputs, int cbSize);
    [DllImport("user32.dll")]
    private static extern IntPtr GetMessageExtraInfo();

    // Method will hold down Windows and Left Alt while pressing R
    internal static void StartOrStopVideoRecorder()
    {
        INPUT[] structInput =
        {
        new INPUT
        {
            type =  1,
            u = new InputUnion
            {
                ki = new KeyboardInput
                {
                    wVk = 0,
                    dwFlags = 0x0,
                    dwExtraInfo = GetMessageExtraInfo()
                }
            }
        } };


        //Press Alt key
        structInput[0].u.ki.wVk = (ushort)VK.MENU;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));

        //Press LeftWin key
        structInput[0].u.ki.wVk = (ushort)VK.LWIN;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));

        //Press the R key
        structInput[0].u.ki.wVk = (ushort)VK.R;//vk;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));
        //Thread.Sleep(500);

        //Release the R key
        structInput[0].u.ki.dwFlags = KEYEVENTF_KEYUP;
        structInput[0].u.ki.wVk = (ushort)VK.R;//vk;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));

        //Release LeftWin key
        structInput[0].u.ki.wVk = (ushort)VK.LWIN;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));

        //Release the ALT key
        structInput[0].u.ki.wVk = (ushort)VK.MENU;
        SendInput((uint)1, structInput, Marshal.SizeOf(typeof(INPUT)));
    }
  • Related