Firstly, check does not change at all inside the loop - you always look at the parameter value. If that is what you want to do, your method can much simpler:
private void checkbox(CheckBox check)
{
btnInstall.Enabled = check.Checked;
}
If that isn't what you need to do, then look at each checkbox inside the loop.
Every time you go round the loop, you check if the current Control is a CheckBox, and if it isn't you disable the button.
So if there are any non-CheckBox controls after the last Checked CheckBox in the form, you will always disable the button regardless of the Checked state.
Move the Disable instruction outside the loop alltogether:
private void checkbox(CheckBox check)
{
btnInstall.Enabled = false;
foreach (Control c in panel.Controls)
{
if (c is CheckBox cb)
{
if (cb.Checked)
{
btnInstall.Enabled = true;
break;
}
}
}
}
And yes, you do want to use a BackgroundWorker to do your install - if you don't the UI will freeze up and you'll never see the progress bar change.