Ranorex

Application.ShowForm =>System.InvalidOperationException

 
Post new topic   Reply to topic    Ranorex Forum Index -> RanorexNet
View previous topic :: View next topic  
Author Message
ssp



Joined: 20 Dec 2007
Posts: 4

PostPosted: Thu Dec 20, 2007 4:07 pm    Post subject: Application.ShowForm =>System.InvalidOperationException
Hello,

I try to automate a Winforms form using the Application.ShowForm method. But this results in a System.InvalidOperationException:

Quote:
Additional information: Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement BrowserForm erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.


I also tried it using a delegate. E.G.:
Code: click into code to enlarge

delegate Ranorex.Form ShowFormDelegate(System.Windows.Forms.Form i_form);

...

m_clientForm = (Ranorex.Form)browser.Invoke(new ShowFormDelegate(Application.ShowForm), browser);


where m_clientForm is a Ranorex.Form and browser is a System.Windows.Forms.Form.

Unfortunately the result is the same:
Quote:
A first chance exception of type 'System.InvalidOperationException' occurred in System.Windows.Forms.dll

Additional information: Ungültiger threadübergreifender Vorgang: Der Zugriff auf das Steuerelement BrowserForm erfolgte von einem anderen Thread als dem Thread, für den es erstellt wurde.


The call stack of the exception:
Quote:
> System.Windows.Forms.dll!System.Windows.Forms.Control.Handle.get() + 0xdf bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.SetVisibleCore( bool value = true) + 0xcb bytes
System.Windows.Forms.dll!System.Windows.Forms.Form.SetVisibleCore(boo l value = true) + 0xb7 bytes
System.Windows.Forms.dll!System.Windows.Forms.Control.Visible.set(boo l value) + 0xe bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadConte xt.RunMessageLoopInner(int reason = -1, System.Windows.Forms.ApplicationContext context = {System.Windows.Forms.ApplicationContext}) + 0xee bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.ThreadConte xt.RunMessageLoop(int reason, System.Windows.Forms.ApplicationContext context) + 0x53 bytes
System.Windows.Forms.dll!System.Windows.Forms.Application.Run(System. Windows.Forms.Form mainForm) + 0x2e bytes
RanorexNet.dll!Ranorex.Application.ShowForm.AnonymousMethod() + 0x2c bytes
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.WaitCallback_Co ntext(object state) + 0x2f bytes
mscorlib.dll!System.Threading.ExecutionContext.Run(System.Threading.E xecutionContext executionContext, System.Threading.ContextCallback callback, object state) + 0x81 bytes
mscorlib.dll!System.Threading._ThreadPoolWaitCallback.PerformWaitCall back(object state) + 0x6c bytes


What am I doing wrong?

Thanks,

Stefan
Back to top
View user's profile Send private message
Support Team
Site Admin


Joined: 07 Jul 2006
Posts: 256

PostPosted: Thu Dec 20, 2007 5:55 pm    Post subject:
Please explain what do you want to do and post your code lines.

Gabor
Ranorex Team
Back to top
View user's profile Send private message Visit poster's website
ssp



Joined: 20 Dec 2007
Posts: 4

PostPosted: Thu Dec 20, 2007 6:30 pm    Post subject:
Background information:
I want to automate an .net Control embedded in an html-page in internet explorer (like a java applet).
To gain more control over the test runs I am trying to integrate the web browser control in my test project. So instead of calling
Code: click into code to enlarge
Application.Start("C:\\Program Files\\Internet Explorer\\iexplore.exe " +  url);

(which works just fine) I've put a web browser control on a form and I am now trying to automate this form.
The reason behind this is that I can catch events from the internet explorer (like "Navigated") and use them to synchronize my test runs (instead of Application.Sleep for an estimated time).

The code:
I have a Windows Forms class called BrowserForm (hosting the IE-control) and now I am trying to automate this form:

But (as written above) neither:

Code: click into code to enlarge
           BrowserForm browser = new BrowserForm();
            browser.DocumentURL = new Uri(url);

            m_clientForm = Application.ShowForm(browser);


nor

Code: click into code to enlarge
            BrowserForm browser = new BrowserForm();
            browser.DocumentURL = new Uri(url);

            m_clientForm = (Ranorex.Form)browser.Invoke(new ShowFormDelegate(Application.ShowForm), browser);


works. I only get an exception.
Back to top
View user's profile Send private message
Support Team
Site Admin


Joined: 07 Jul 2006
Posts: 256

PostPosted: Thu Dec 20, 2007 6:53 pm    Post subject:
OK, please consider that the classes in the Ranorex namespace are not inherited from the classes in System.Windows.Forms.
So you cannot cast a System.Windows.Forms Form to Ranorex.Form.

But you can embed your explorer control in the test application and automate it in the same process.

Jenö
Ranorex Team
Back to top
View user's profile Send private message Visit poster's website
ssp



Joined: 20 Dec 2007
Posts: 4

PostPosted: Fri Dec 21, 2007 10:10 am    Post subject:
Quote:
OK, please consider that the classes in the Ranorex namespace are not inherited from the classes in System.Windows.Forms.
So you cannot cast a System.Windows.Forms Form to Ranorex.Form.


I am aware of that. And I am not casting a Windows.Forms.Form to a Ranorex.Form (at least I can't see that). The line
Code: click into code to enlarge
(Ranorex.Form)browser.Invoke(new ShowFormDelegate(Application.ShowForm), browser)


calls the ShowForm method of the ranorex.application using a delegate in the same thread of the Windows.Form. Since ShowForm returns a Ranorex.Form the delegate call should return a Ranorex.Form, too. The cast is necessary because the invoke method of the Windows.Form.Form returns an object.


Quote:
But you can embed your explorer control in the test application and automate it in the same process.


This is exactly what I am trying to do. But it is not working, because of the System.InvalidOperationException.

It looks like ShowForm is called from a different thread than the one which created the Windows.Forms.Form. I tried to overcome that using a delegate and the Invoke method, but so far without luck.
I could provide you a test project.

Stefan
Back to top
View user's profile Send private message
Support Team
Site Admin


Joined: 07 Jul 2006
Posts: 256

PostPosted: Fri Dec 21, 2007 11:59 am    Post subject:
Hi Stefan!

The problem is that your BrowserForm is constructed in the main thread (the one that calls new BrowserForm();) and that Application.ShowForm tries to show and access the constructed BrowserForm from another thread. This is not allowed by the windows infrastructure.

There are two options on how to create the BrowserForm: from the main thread or from a separate thread.
If you create the BrowserForm from the main thread, you can easily access all properties and methods of the BrowserForm, but actions in the main thread will block the BrowserForm and vice versa.
If you construct the BrowserForm from a separate thread, both forms run independently, but you need to Invoke all methods/properties accessing the other form either by using Ranorex or the Form.Invoke method.

The following example uses the second technique. The CreateFormButton_Click method starts a thread that constructs and runs a new form. Then it waits till the new form is constructed (by use of a ManualResetEvent) and creates a RanorexNet.Form from the Handle of the newly created form. It then uses Ranorex to set the title of the newly created form.

Code: click into code to enlarge
private void CreateFormButton_Click(object sender, EventArgs e)
{
    formCreated = new ManualResetEvent(false);

    Thread thread = new Thread(new ThreadStart(CreateAndShowForm));
    thread.IsBackground = false;
    thread.SetApartmentState(ApartmentState.STA);
    thread.Start();

    formCreated.WaitOne();
    formCreated.Close();
    formCreated = null;

    Form theCreatedForm = new Form(lastCreatedFormHandle);
    theCreatedForm.Text = "MyNewlyCreatedForm";
}

private ManualResetEvent formCreated;
private IntPtr lastCreatedFormHandle = IntPtr.Zero;

private void CreateAndShowForm()
{
    Form1 createdForm = new Form1();
    createdForm.webBrowser1.Url = new Uri("http://www.google.at/");
    lastCreatedFormHandle = createdForm.Handle;
    formCreated.Set();
    System.Windows.Forms.Application.Run(createdForm);
}


If you set the IsBackground property of the created thread to true, the constructed form will be closed if the main thread (that calls the CreateFormButton_Click method) exits.

We will adapt the Application.ShowForm method for the next release to make it easier to use.

Alex
Ranorex Support Team


Last edited by Support Team on Wed Jan 02, 2008 2:30 pm; edited 1 time in total
Back to top
View user's profile Send private message Visit poster's website
ssp



Joined: 20 Dec 2007
Posts: 4

PostPosted: Fri Dec 21, 2007 5:04 pm    Post subject:
Hi Alex,

thanks, now I can start the form and automate it.

I have still some problems stopping the form thread, but this has to wait after the holidays.

Happy holidays!

Stefan
Back to top
View user's profile Send private message
Support Team
Site Admin


Joined: 07 Jul 2006
Posts: 256

PostPosted: Wed Jan 02, 2008 5:31 pm    Post subject:
Happy new year!

If you set the IsBackground property of the created thread to false (see the supplied example above), you must close the form (or manually abort the form process) in order to end the process.

Otherwise (IsBackground = true) the form thread is aborted (and the form discarded) when all the foreground threads of the application have exited and the process exits therefore.

Alex
Ranorex Support Team
Back to top
View user's profile Send private message Visit poster's website
Display posts from previous:   
Post new topic   Reply to topic    Ranorex Forum Index -> RanorexNet All times are GMT + 2 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum