C# RichTextBox Control in Windows forms is not visible when built in Release

itnifl
itnifl used Ask the Experts™
on
I have a C# RichTextBox Control in Windows forms that is not visible when built in Release mode. If I run in Debug mode and use the debugger, then the RichTextBox is visible. I am very sure that it is not the code that is setting the RichTextBox as not visible. If that was the case, then the result should be the same in both Debug and Release. I have no conditional code that differs between Release or Debug, thus this can not be affecting this.

Also, when the application is loading after being built in Release mode and run by double clicking the file, it takes a very long time before (up to more then a minute) before the application is started and visible. When the application is run via Visual Studio in Debug mode, it starts instantly and the RichTextBox Control is visible.

I have been trying to solve this some time now, but have not found any solution. I also tried using Process Monitor  to see if there were files that were not loading, but did not find any.

I created a Windows Server 2012 VM and copied the Release compiled exe and dlls over there. When running the application in this VM, it started smoothly and the RichTextBox Control was visible. I myself am running Windows 7, so I tried creating a blank Windows 7 virtual machine and installed .Net 4 Client profile on it. Then checked what would happen when I started the application in there, with same error result(RichTextBox Control not showing and taking a long time to load).

Any ideas to solve this?
Comment
Watch Question

Do more with

Expert Office
EXPERT OFFICE® is a registered trademark of EXPERTS EXCHANGE®
Karrtik IyerSoftware Architect

Commented:
Can you share the code which has been written on load? And also any code written to make richtextboxcontrol visible to true/false?
AndyAinscowFreelance programmer / Consultant
Commented:
What happens if you run the debug build outside of Visual Studio?  (Double click the exe rather than run button in VS).
Do you get the same behaviour as the release build?
AndyAinscowFreelance programmer / Consultant

Commented:
Also reboot your PC.  Does that cure the problem ?
HTML5 and CSS3 Fundamentals

Build a website from the ground up by first learning the fundamentals of HTML5 and CSS3, the two popular programming languages used to present content online. HTML deals with fonts, colors, graphics, and hyperlinks, while CSS describes how HTML elements are to be displayed.

Commented:
You may also try cleaning and rebuilding your solution.  Ensure that you are retrieving the assemblies from the Release directory.  Also ensure that you do not have any specific build events (these may be copying or moving the compiled assemblies to another directory).

-saige-
itniflProgrammer

Author

Commented:
* Running the debug result outside of VS by double clicking the exe in the Debug folder produces same error result.
* Reboot of PC did not make a difference.
* Cleaning and rebuilding did not make a difference (debug nor release).
* Removing post-build event command lines that copy the results to a given folder did not make a difference.
* Starting app directly from the Release folder did not make a difference.

Code that toggles visibility of the RichTextBox (very simple and does not affect the loading procedure, which also should not be different when debugging):
//txtMessage is the RichTextBox control in question,

//When we hit the close button, we hide the RichTextBox control that should be displayed at startup, and show the powershellInteractiveControl:
private void btnClose_Click(object sender, EventArgs e) {
         m_powershellInteractiveControl1.Visible = true;
         txtMessage.Visible = false;
         btnClose.Visible = false;
      }

//When the powershellInteractiveControl sets visible to false, we set visible of txtMessage to true:
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
            m_powershellInteractiveControl1.Visible = visibleState;
            txtMessage.Visible = !visibleState;
            btnClose.Visible = !visibleState;
         };

Open in new window


Switching between these visible states works fine when debugging inside VS, and seems to work fine outside VS when running the Release build, except the RichTextBox control is never shown when running the Release build - even when toggling between these visible states. The button to close it however, is shown, and toggles fine independent of build type.
Top Expert 2015
Commented:
I would try removing the control and then add a new one, with the same name so that the code you already wrote continue to work.

Just for the sake of it, I would also put a temporary second one on the form to see if it behave the same way. If it does not, they the problem is somewhere in your code, not with some kind of installation issue.
AndyAinscowFreelance programmer / Consultant

Commented:
Just what is this line:
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) =>...

To me it looks rather odd.
Karrtik IyerSoftware Architect

Commented:
Can you please post the type of this control?
Also do we need to set m_powershellInteractiveControl1.Visible = visibleState;
Inside control visible change event of same control? (m_powershellInteractiveControl1).
Can this cause some kind of recursion? Just thinking aloud...
Can you please check how it goes with the below code for ControlVisibleChanged event?
[code]
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {            
            txtMessage.Visible = !visibleState;
            btnClose.Visible = !visibleState;
         };
[/code]
AndyAinscowFreelance programmer / Consultant

Commented:
>>Can this cause some kind of recursion?

Precisely why I was asking about that line of code.  I've not found what ControlVisibleChangeEvent  is with an internet search but it looks like it is meant to be an event handler for when the visible state changes - and inside it it might be swapping the visibility state, triggering itself to be run again.  That would explain why it takes so long to run at startup whilst it is busy destroying some resources until it quits.
Karrtik IyerSoftware Architect

Commented:
Can you please try removing the visibility toggling of the power shell control within this event and instead try with code shown below?
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {            
            txtMessage.Visible = !visibleState;
            btnClose.Visible = !visibleState;
         };

Open in new window

itniflProgrammer

Author

Commented:
m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {
            m_powershellInteractiveControl1.Visible = visibleState;
            txtMessage.Visible = !visibleState;
            btnClose.Visible = !visibleState;
         };

Open in new window


m_powershellInteractiveControl1 is a user control with a whole lot of code. I can not post it here, and it is also irrelevant for the question we are discussing. But  ca explain how the code above works. ControlVisibleChangeEvent is a custom event delegate using a Action<bool> delegate, and I assign a anonymous delegate to it. Simply a pointer to a method that is unnamed. The event is declared as so:

public event Action<bool> ControlVisibleChangeEvent = (bool visibleState) => { };

Open in new window

This is a event that is subscribed to by the creator of the object that this event is a property of. You can see above that at instantiaton of the object, a default empty delegate is assigned as a subscription. This is to ensure that the ControlVisibleChangeEvent never is null, and thus when it is called, I do not have to check if it is null or not.
Further down the line of code in the powershellInteractiveControl there is code to handle the close event of this control when a button is pressed inside the control(not the same as previously mentioned), and it triggers all subscriptions to the event I have declared so that all outside subscribers can fire the code that they write in the delegate they assign to my event:

private void btnClose_Click(object sender, EventArgs e) {
	//Invert the visible property:
         this.Visible = !this.Visible;
	//pass the status to all subscribers:
         ControlVisibleChangeEvent(this.Visible);
      }

Open in new window


"Can this cause some kind of recursion?"
No, it should not. ControlVisibleChangeEvent is only fired as I showed above. It is programmed by myself, and is only fired when the close button inside the powershellInteractiveControl is used. I could change that and use it differently, but as of now I don't need to.

" I've not found what ControlVisibleChangeEvent  is with an internet search.."
That is because the event is not a part of a standard msdn class,  framework. It is added to a user control that is created for specifc purposes in this project.

"Can you please try removing the visibility toggling of the power shell control within this event and instead try with code shown below?"

m_powershellInteractiveControl1.ControlVisibleChangeEvent += (bool visibleState) => {            
            txtMessage.Visible = !visibleState;
            btnClose.Visible = !visibleState;
         };

Open in new window


First I tried removing the event subscription all together. What happens is that the main form where the powershellInteractiveControl is added never gets informed by the powershellInteractiveControl that its visibility state has changed, so the code that is in the delegate I declared as the subscriber never gets executed. This means that txtMessage never gets assigned true to the the Visible property, and btnClose the same. Offcourse txtMessage was never visible to begin with unless debugging, but now btnClose never gets visible again after closing the powershellInteractiveControl.

Next I tried your suggestion, only removing the first line in the delegate. This has no effect on any functionality. This is because the powershellInteractiveControl already sets its own visible state in its on btnClose method that I showed you above, right before the event is fired. So actually, I could just as well not include the first line of the delegate I assign to the event, as you suggested. It is just bloated un-needed code.

I have to admit that I have earlier been tampering with InitializeComponent(), but found that it was a bad idea. VS doesn't like that I tamper with the autogenerated code that this method runs. Also when VS autogenerates again, my code there is removed.

Some times I get the error:
"The variable 'm_powershellInteractiveControl1' is either undeclared or was never assigned."
and
"Could not find type 'CreateStation.Controls.PowershellInteractiveControl'. Please make sure that the assembly that contains this type is referenced. If this type is a part of your development project, make sure that the project has been successfully built using settings for your current platform or Any CPU. "

I then have to clean the solution and restart it, then the error is gone. The code that it says is not there, is there. That is why it has struck my mind to remove the PowershellInteractiveControl and try without, then try to add it again.

Now, Jacques Bourgeois (James Burger) suggested to remove the PowershellInteractiveControl. I will try that now and come with a reply in a short while.
itniflProgrammer

Author

Commented:
So here are the results when removing the PowershellInteractiveControl:
* When removed, the code runs fine. The RichTextBox control shows fine.
* If I then add it again, the application displays the same error behaviour as before.
* If I remove all code in the form that contains the PowershellInteractiveControl that refers to it, this makes no difference.
* If I add it again, and remove, and then  re-add the RichTextBox control and give it the same name as the previous one (txtMessage), we are back to where we started.

So  have no Idea, maybe I need to have the PowershellInteractiveControl in another form or something.
Karrtik IyerSoftware Architect
Commented:
Based on your last comment (Thanks for all the details, it definitely helps), it is clear that something inside your custom control (PowerShellIntertactiveControl) is causing this.
Given this, I would start commenting pieces of code inside this custom control (whatever code you have written not generated code), and find out after commenting which piece of code things start to work.
First I shall only keep the UI pieces of your custom control and remove all the event handling or any other logic or code written inside your custom control and then go step by step to un-comment pieces of code to find out which piece makes a difference.
AndyAinscowFreelance programmer / Consultant

Commented:
I've made a small app to try to simulate your methodology.
It works perfectly both inside of VS as as stand alone app.

However I don't see how you raise this custom event so my code isn't necessarily similar to yours.
How do you call this in your code?
private void btnClose_Click(object sender, EventArgs e) {
	//Invert the visible property:
         this.Visible = !this.Visible;
	//pass the status to all subscribers:
         ControlVisibleChangeEvent(this.Visible);  <<<-------------------- HERE
      }

Open in new window


How do you link the button code to your custom controls event?
itniflProgrammer

Author

Commented:
There are two btnClose_Click methods, and two buttons. One is in the powershellInteractiveControl, and one is in the form that holds the control. The method in powershellInteractiveControl raises the event just like you showed in the code on line 5 in your last reply.

Using Karrtik Lyer's method of searching for the code that was doing all the wrong, I ended up with this extension method:
 public static class RichTextBoxExtensions {
      public static void AppendText(this RichTextBox box, string text, Color color) {         
            box.SelectionStart = box.TextLength;
            box.SelectionLength = 0;

            box.SelectionColor = color;
            box.AppendText(text);
            box.SelectionColor = box.ForeColor;
      }
   }
}

Open in new window

It is used by a object that gets instantiated twice, once for the RichTextBox Control (txtMessage) that disappears, and once for a RichTextBox Control that acts as a console in the powershellInteractiveControl. This object of the class PanelHandler handles one RichTextBox control attached to it, makes sure that multiple threads are not writing simultaneously to the RichTextBox it handles, and if so, then doing it in a way that does not make the app crash (checking InvokeRequired etc).

BUT both instances of PanelHandler use the same static extension method shown above. Thats where the trouble starts. I assume, since the extension method is static, then it is shared between these two objects of PanelHandler. Both instances are on each theyr thread, trying to use the extension method AppendText at the same time. I have been experimenting with using InvokeRequired or locking object in the static extension method, but have not succeeded so far. Only thing that works right now is to comment away all the code inside the extension method, then all works fine. But I need it, so I need to fix this.
Karrtik IyerSoftware Architect

Commented:
Good that you have been able to isolate this piece of code. Can you please post the invoke version of this method that you are trying?
itniflProgrammer

Author

Commented:
Here is the code that uses the extension method:
foreach (char c in outText) {
            if (TheTextBox.InvokeRequired) {
               // It's on a different thread, so use Invoke.
               lock(m_LockObject) {
                  PrintTextCallback ourDelegate = new PrintTextCallback(printText);
                  TheTextBox.Invoke(ourDelegate, new object[] { c, TheTextBox, TextColor });
               }               
            }
            else {
               lock (m_LockObject) {
                  // It's on the same thread, no need for Invoke 
                  TheTextBox.AppendText(c.ToString(), TextColor); //Here is the extension method usage
               }
            }
            Thread.Sleep(PrintDelay);
         }

Open in new window


Here is the printText method that is used when InvokeRequired:
private static void printText(Char c, RichTextBox theTextbox, Color printColor) {
         theTextbox.AppendText(c.ToString(), printColor);
         if (c.Equals('\n')) {
            theTextbox.SelectionStart = theTextbox.TextLength;
            theTextbox.ScrollToCaret();
         }
      }

Open in new window


And here is the extension method - that is still breaking:
   public static class RichTextBoxExtensions {
      private static object m_lock = new object();
      public static void AppendText(this RichTextBox box, string text, Color color) {         
         if(box.InvokeRequired) {
            lock(m_lock) {
               //Nothing here, code still breaks
            }
         }
         else {
            lock (m_lock) {
               box.SelectionStart = box.TextLength;
               box.SelectionLength = 0;

               box.SelectionColor = color;
               box.AppendText(text);
               box.SelectionColor = box.ForeColor;
            }
         }   
      }
   }

Open in new window

Commented:
Just as a test for your extension method, I created the following -

Form1.cs -
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EE_Q28911507
{
	public partial class Form1 : Form
	{
		public Form1()
		{
			InitializeComponent();
		}

		private void OnClick(object sender, EventArgs e)
		{
			// Simulate a cross-threaded call for showing the 
			// invoke required handler in action
			Task.Factory.StartNew(() =>
			{
				richTextBox1.AppendText(string.Format("Making the textbox visible: {0}", !richTextBox1.Visible), richTextBox1.Visible ? Color.Blue : Color.Red);
				ControlVisibleChangeEvent(richTextBox1, !richTextBox1.Visible);
			});
		}

		private event Action<object, bool> ControlVisibleChangeEvent = (object sender, bool visible) => 
		{
			(sender as Control).HandleInvokeRequired(c => c.Visible = visible);
		};
	}

	static class Extensions
	{
		public static void AppendText(this RichTextBox box, string text, Color color)
		{
			box.HandleInvokeRequired(_box =>
			{
				_box.SelectionStart = _box.TextLength;
				_box.SelectionLength = 0;

				_box.SelectionColor = color;
				_box.AppendText(text);
				_box.SelectionColor = _box.ForeColor;
			});
		}

		public static void HandleInvokeRequired<T>(this T control, Action<T> action) where T : Control, ISynchronizeInvoke
		{
			//Check to see is the control is not null
			if (control == null)
				throw new ArgumentNullException(string.Format("Cannot execute {0} on {1}.  {1} is null.", action, control));

			//Check to see if the control is disposed.
			if (control is Control && (control as Control).IsDisposed)
				throw new ObjectDisposedException(string.Format("Cannot execute {0} on {1}.  {1} is disposed.", action, control));

			//Check to see if the handle is created for the control.
			if (control is Control && !(control as Control).IsHandleCreated)
				throw new InvalidOperationException(string.Format("Cannot execute {0} on {1}.  Handle is not created for {1}.", action, control));

			//Check to see if the control's InvokeRequired property is true
			if (control.InvokeRequired)
			{
				try
				{
					//Use Invoke() to invoke your action
					control.Invoke(action, new object[] { control });
				}
				catch (Exception ex)
				{
					throw new Exception(string.Format("Cannot execute {0} on {1}.  {2}.", action, control, ex.Message));
				}
			}
			else
			{
				try
				{
					//Perform the action
					action(control);
				}
				catch (Exception ex)
				{
					throw new Exception(string.Format("Cannot execute {0} on {1}.  {2}.", action, control, ex.Message));
				}
			}
		}
	}
}

Open in new window

Which gives me the following output -Initial load.Clicking the button to hide the rich text box.Few more clicks later and making the rich text box visible again.
-saige-
itniflProgrammer

Author

Commented:
it_saige: Thank you very much for this code. I have been looking through it and testing, comparing to my handling of InvokeRequired. I see the concept is essentially the same, but your HandleInvokeRequired would be a good general method to handle all types the are Control and implement ISynchronizeInvoke, and it also performs many good checks. So, I will use that code.

BUT, initially it failed the same way as my code did. BECAUSE, the error actually originated elsewhere IN ADDITION to this code that we have been looking at and that you helped rewrite.

The ADDITIONAL error source was my attempt to star printing to the RichTextBox controls through the PanelHandler in the constructor of the forms right after InitializeComponent() was run. I thought the form would be ready by then, but it was not. So I moved the code that starts the printing to for instance frmMain_Load, that is executed when the form is ready.

I realized this because in your code, you check for IsHandleCreated, and in my case it was always false, which led me to investigate.
itniflProgrammer

Author

Commented:
Sharing the points here a bit unevenly for the different contributions. Thank you all for participating, I am very glad for all the feedback.
AndyAinscowFreelance programmer / Consultant

Commented:
>>...to star printing to the RichTextBox controls...

Glad it is sorted out and thanks for the feedback  BUT in future please tell us the whole story.  Assuming something is at fault is often a bad idea.
itniflProgrammer

Author

Commented:
Too much code to share the whole thing.
AndyAinscowFreelance programmer / Consultant

Commented:
Telling us printing started automatically at start of app could be viewed as important info.
itniflProgrammer

Author

Commented:
Yes, if you know it is important :)

Do more with

Expert Office
Submit tech questions to Ask the Experts™ at any time to receive solutions, advice, and new ideas from leading industry professionals.

Start 7-Day Free Trial