/// <summary>
 /// Enable or disable the CreateInstallerButton in a thread-safe way.
 /// </summary>
 /// <param name="enable">true to enable the button, false to disable it.</param>
 private void ThreadSafeEnableControls(bool enable)
 {
     // InvokeRequired required compares the thread ID of the
     // calling thread to the thread ID of the creating thread.
     // If these threads are different, it returns true.
     if (ComponentSummaryText.InvokeRequired)
     {
         var d = new SetTextCallbackWithBool(ThreadSafeEnableControls);
         ComponentSummaryText.Invoke(d, new object[] { enable });
     }
     else
     {
         CreateInstallerButton.Enabled = enable;
         ComponentNamesBox.Enabled     = enable;
     }
 }
 /// <summary>
 /// Adds the specified string to the bottom of the ComponentSummaryText Textbox in a thread-safe manner.
 /// </summary>
 /// <param name="msg">The text to be added</param>
 /// <param name="erasePrevious">true if current text in control should be wiped first</param>
 private void ThreadSafeAddSummaryText(string msg, bool erasePrevious)
 {
     // InvokeRequired required compares the thread ID of the
     // calling thread to the thread ID of the creating thread.
     // If these threads are different, it returns true.
     if (ComponentSummaryText.InvokeRequired)
     {
         var d = new SetCallbackWithTextAndBool(ThreadSafeAddSummaryText);
         ComponentSummaryText.Invoke(d, new object[] { msg, erasePrevious });
     }
     else
     {
         if (erasePrevious)
         {
             ComponentSummaryText.Text = msg;
         }
         else
         {
             ComponentSummaryText.Text += msg;
         }
         ComponentSummaryText.Text += Environment.NewLine;
         ScrollSummaryToBottom();
     }
 }
 private void ScrollSummaryToBottom()
 {
     ComponentSummaryText.SelectionStart = ComponentSummaryText.Text.Length;
     ComponentSummaryText.ScrollToCaret();
 }