Avatar of itnifl
itnifl
Flag for Norway asked on

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

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?
.NET ProgrammingMicrosoft DevelopmentC#

Avatar of undefined
Last Comment
itnifl

8/22/2022 - Mon
Karrtik Iyer

Can you share the code which has been written on load? And also any code written to make richtextboxcontrol visible to true/false?
SOLUTION
AndyAinscow

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.
AndyAinscow

Also reboot your PC.  Does that cure the problem ?
SOLUTION
it_saige

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
itnifl

ASKER
* 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.
Your help has saved me hundreds of hours of internet surfing.
fblack61
SOLUTION
Jacques Bourgeois (James Burger)

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
AndyAinscow

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

To me it looks rather odd.
Karrtik Iyer

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]
AndyAinscow

>>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.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
Karrtik Iyer

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

itnifl

ASKER
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.
itnifl

ASKER
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.
Experts Exchange has (a) saved my job multiple times, (b) saved me hours, days, and even weeks of work, and often (c) makes me look like a superhero! This place is MAGIC!
Walt Forbes
SOLUTION
Karrtik Iyer

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
AndyAinscow

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?
itnifl

ASKER
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 Iyer

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?
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
itnifl

ASKER
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

ASKER CERTIFIED SOLUTION
it_saige

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
itnifl

ASKER
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.
itnifl

ASKER
Sharing the points here a bit unevenly for the different contributions. Thank you all for participating, I am very glad for all the feedback.
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
AndyAinscow

>>...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.
itnifl

ASKER
Too much code to share the whole thing.
AndyAinscow

Telling us printing started automatically at start of app could be viewed as important info.
⚡ FREE TRIAL OFFER
Try out a week of full access for free.
Find out why thousands trust the EE community with their toughest problems.
itnifl

ASKER
Yes, if you know it is important :)