?
Solved

Code works in .vbs not in C# app -- Open IE, log in to site, click item

Posted on 2016-10-12
9
Medium Priority
?
119 Views
Last Modified: 2017-01-24
Experts,

I have the following code that logs in to an RWeb portal and clicks the RDP icon to launch it:

'Whatever you want to call this QA Activity:
QAName = "qatest" 

'URL to launch:
strURL = "http://qasite.wizmo.com"

'QA Username and Password:
QAUser = "qauser"
QAPass = "qapass"

'Comma separated list of the icons we are waiting to appear in the list of apps:
IconsToFind = "rdp"

'Icon we are actually going to launch. 0 = First Icon, 1 = Second, etc..
IconToLaunch = 0


'-----------------------------
'Generally no need to modify anything below this line.
'------------------------------

Set objIE = CreateObject("InternetExplorer.Application")
Set objWSH = WScript.CreateObject("WScript.Shell")
With objIE
   .Visible = True
   objWSH.AppActivate objIE
   .Navigate strURL
   '==No point in checking right away - give the page a chance to load
   WScript.Sleep 500
   '==Now check to see if we're done loading and we have the Sign In button available
   Do While .Busy or .readyState <> 4
      WScript.Sleep 500
   Loop
   Do Until (Instr(.Document.Body.InnerHTML,"Sign in") <> 0)
      WScript.Sleep 500
   Loop

   '==Fill out the form and login
   .Document.getElementsByName("DomainUserName").Item(0).Value = QAUser
   .Document.getElementsByName("UserPass").Item(0).Value = QAPass
   .Document.getElementsByName("btnSignIn").Item(0).Click
   '==Give the page a second to load before we start looking for things
   Do While .Busy or .readyState <> 4
      WScript.Sleep 500
   Loop
   WScript.Sleep 500
   Checks = 0
   bFound_RemoteDesktop = False
   iFoundCount = 0 
   'Check if all icons we are waiting for exist
   IconList = Split(IconsToFind, ",")
   For Each Icon in IconList
		If instr(.Document.Body.InnerHTML,Icon) <> 0 then
			iFoundCount = iFoundCount + 1
		End If
   Next
   'Msgbox "Icons found: " & iFoundCount	& " of " & ubound(IconList) + 1
   If iFoundCount = ubound(IconList) + 1  then 
		'Msgbox "All icons found"
   Else
		Msgbox "Some icons missing!!"
		WScript.Quit 0
   End If
  
   '==This will launch the first link
   .Document.getElementsByClassName("tswa_boss").Item(IconToLaunch).onMouseUp
   Msgbox "Click OK once you've finished Q/A of the desktop session"
   If instr(.Document.Body.InnerHTML,"Sign out") <> 0 Then
      '==User is still logged in, let's log them out
      .Document.getElementById("PORTAL_SIGNOUT").Click
      WScript.Sleep 1000
   End If
End With
objIE.Quit   
Msgbox "QA done for " & QAName

Open in new window


Users can run this manually, and it works with no issue.  But for our QA automation, I have a winform c# app that I want to do this login, and it gets through the login process but dies trying to find the class:
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Web;

using SHDocVw;
using System.Threading;


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

        private void button1_Click(object sender, EventArgs e)
        {
            string URL = "http://qasite.wizmo.com";
            string QAUser = "qauser";
            string QAPass = "qapass";
            string IconsToFind = "rdp";
            int IconToLaunch = 0;


            InternetExplorer qaBrowser = new InternetExplorer();
            qaBrowser.Visible = true;
            qaBrowser.Navigate(URL);
            Thread.Sleep(500);
            while (qaBrowser.Busy || qaBrowser.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
            {
                Thread.Sleep(500);
            }

            qaBrowser.Document.GetElementsByName("DomainUserName").Item(0).Value = QAUser;
            qaBrowser.Document.GetElementsByName("UserPass").Item(0).Value = QAPass;
            qaBrowser.Document.GetElementsByName("btnSignIn").Item(0).Click();

            while (qaBrowser.Busy || qaBrowser.ReadyState != SHDocVw.tagREADYSTATE.READYSTATE_COMPLETE)
            {
                Thread.Sleep(500);
            }

            string[] IconList = IconsToFind.Split(',');
            foreach (string icon in IconList)
            {
                //add check to make sure all expected icons are present.
            }

            Thread.Sleep(500);

            //qaBrowser.Document.GetElementByID("PORTAL_SIGNOUT").Click();
            
            qaBrowser.Document.GetElementsByClassName("tswa_boss");//[0].onmouseup();
            //qaBrowser.Document.GetElementByID("PORTAL_SIGNOUT").Click();

        }
    }
}

Open in new window


This is the hill it dies on:
  qaBrowser.Document.GetElementsByClassName("tswa_boss")

Open in new window

with an HRESULT exception.

But the code works just fine in VB...?

The class name for the element is "tswa_boss".  Any ideas what the problem might be?
0
Comment
Question by:Dustin Saunders
  • 6
  • 3
9 Comments
 
LVL 20

Expert Comment

by:Daniel Van Der Werken
ID: 41840862
My guess is that it's a case-sensitivity issue. What's the actual HTML look like that you're working against?
0
 
LVL 14

Author Comment

by:Dustin Saunders
ID: 41840875
Here's the table:
webPageName.png
0
 
LVL 20

Expert Comment

by:Daniel Van Der Werken
ID: 41842123
Okay. That was a try. I was assuming all the Interop was done correctly, but I don't think it is. The way Interop is done betwixt C# and VB.NET is very different. VB.NET lets you be lazy and C# doesn't. Give me a while and I'll get back to this.
0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
LVL 14

Author Comment

by:Dustin Saunders
ID: 41842140
Thanks Daniel, I appreciate your time.
0
 
LVL 14

Author Comment

by:Dustin Saunders
ID: 41848404
I'm getting back around to trying to figure this out today, was wondering if you were able to figure anything out (if not, no worries, but I'm still stumped).
0
 
LVL 20

Accepted Solution

by:
Daniel Van Der Werken earned 2000 total points
ID: 41848718
I didn't get very far myself. The key to Interop with C# is that you can't ignore the parameters that you can ignore with VB .NET.

In my test windows forms app, I set up a class-wide variable like this:

public SHDocVw.InternetExplorer ie = null;

Open in new window


Then, in the class initializer, I simply did this:

            ie = new InternetExplorer();
            ie.DocumentComplete += Ie_DocumentComplete;
            ie.Navigate("www.google.com", Type.Missing, Type.Missing, Type.Missing, Type.Missing);

Open in new window


Note that I specifically set up my ability to hook into the document complete event. Therefore, in my code, I also have this:

        private void Ie_DocumentComplete(object pDisp, ref object URL)
        {
            object op = pDisp;
            object u = URL;
        }

Open in new window


Where I just added the object op = pDisp and such so I could look at it in the debugger. Sure enough, this event fires for me, and pDisp is something COM related. I don't know what though. I would imagine we could hook into it via a cast or a late binding to do what we need. I would need to know what type that object is first.

Notice though, by hooking that event, I got around the whole Thread.Sleep() stuff you were doing. The second thing is that we now have something.

Likewise, according to Microsoft, the pDisp is the top-level WebBrower frame, so we should be able to work with that.

So, that event turns into this:

        private void Ie_DocumentComplete(object pDisp, ref object URL)
        {
            SHDocVw.WebBrowser wbObj = (SHDocVw.WebBrowser)pDisp;

            object iweDoc = wbObj.GetType().InvokeMember("IWebBrowser_Document", BindingFlags.GetField | BindingFlags.GetProperty, Type.DefaultBinder, null, null);
             

            object u = URL;
        }

Open in new window


Note that my InvokeMember() fails because I really don't know anything about the WebBrowser object. Maybe you know more. But, I think we need to work with late binding here, which is what the InvokeMember() allows us to do.

That's where I left of. Does this help?
1
 
LVL 14

Author Comment

by:Dustin Saunders
ID: 41854251
Thanks for the information, I'll touch this again over the weekend and let you know what I find.
0
 
LVL 14

Author Closing Comment

by:Dustin Saunders
ID: 41864281
So far as I can tell the problem comes from security with the way .NET interacts with the IE object and the way VBS does.  I couldn't find a good way around it, but I automated the process in a different way (using Powershell instead for the process to launch the .VBS and then look at our SQL login tables to confirm the login worked) but I appreciate your time testing this problem.
0
 
LVL 14

Author Comment

by:Dustin Saunders
ID: 41977981
I finally got back around to looking at this.  Found the problem.

qaBrowser.Document.GetElementsByClassName("tswa_boss")

Open in new window


Should be
qaBrowser.Document.DocumentElement.GetElementsByClassName("tswa_boss")

Open in new window

0

Featured Post

Free Backup Tool for VMware and Hyper-V

Restore full virtual machine or individual guest files from 19 common file systems directly from the backup file. Schedule VM backups with PowerShell scripts. Set desired time, lean back and let the script to notify you via email upon completion.  

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article aims to explain the working of CircularLogArchiver. This tool was designed to solve the buildup of log file in cases where systems do not support circular logging or where circular logging is not enabled
In real business world data are crucial and sometimes data are shared among different information systems. Hence, an agreeable file transfer protocol need to be established.
This Micro Tutorial will teach you how to add a cinematic look to any film or video out there. There are very few simple steps that you will follow to do so. This will be demonstrated using Adobe Premiere Pro CS6.
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses

864 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question