Try this
public IEnumerable<Component> GetComponents(Control c)
{
FieldInfo fi = c.GetType().GetField("components", BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)!;
if (fi?.GetValue(c) is IContainer container)
{
return container.Components.OfType<Component>();
}
else
{
return Enumerable.Empty<Component>();
}
}
Usage
foreach (Form form in Application.OpenForms)
{
var componentList = GetComponents(form).ToList();
}
And for constrols where Decendant gets all controls on a form. Note the wrapper for getting all TextBoxes which can be done for other controls also.
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
namespace WindowsFormsLibrary.LanguageExtensions
{
public static class FormExtensions
{
public static IEnumerable<T> Descendant<T>(this Control control) where T : class
{
foreach (Control child in control.Controls)
{
if (child is T thisControl)
{
yield return (T)thisControl;
}
if (child.HasChildren)
{
foreach (T descendant in Descendant<T>(child))
{
yield return descendant;
}
}
}
}
public static List<TextBox> TextBoxList(this Control control)
=> control.Descendants<TextBox>().ToList();
}
}