Remove Web Element from WebPage With Selenium - c#

Starting say that i know it's a bad practice to remove WebElement from a WebPage.
For testing purpose, i want understand if i can 'modify' the web page i load 'in local (so client side)' on my webBrowser, using Selenium automation.
In this example, i want to load the 'Google' main page, and try to remove the 'Google' title, from my webBrowser.
I tried using JavaScriptExecutor, but fail.
Here is the code.
Dim driver As IWebDriver
Dim ChromeOptions As New ChromeOptions
Dim driverWait_5 As Support.UI.WebDriverWait
Dim jsExec As OpenQA.Selenium.IJavaScriptExecutor
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
driver = New ChromeDriver("C:\ChromeDriver", ChromeOptions)
driverWait_5 = New Support.UI.WebDriverWait(driver, TimeSpan.FromSeconds(5))
jsExec = CType(driver, OpenQA.Selenium.IJavaScriptExecutor)
Dim address As String = "https://www.google.co.uk/webhp"
driver.Navigate.GoToUrl(address)
Dim element As IWebElement = driverWait_5.Until(ExpectedConditions.ElementIsVisible(By.Id("lga")))
If IsNothing(element) = False Then
jsExec.ExecuteScript("document.getElementById('lga').remove();")
End If
End Sub
Any help?
Updated, after help of #Infern0 and #ali, i updated the code, that now works.
Thanks all.

I'm not very familiar with Vb.Net syntax but the C# version below should work;
private void RemoveGoogleLogo()
{
var driver = new ChromeDriver(#"<<chromePath>>")
{
Url = "https://www.google.co.uk/webhp"
};
driver.Navigate();
var driverWait = new WebDriverWait(driver, TimeSpan.FromSeconds(5));
driverWait.Until(x => x.FindElement(By.Id("lga")).Displayed);
driver.ExecuteScript("document.getElementById('lga').remove();");
}

Related

End-user embedded programable VB inside C#

How would it be possible to build a complete C# application with the feature of creating new functionalities thru new VB files. Those files shouldn't have to be compiled but interpreted in runtime.
I think of it as an embedded VB interpreter, but don't know how it can be accomplished.
You could build a robust base application and then let your technicians adapt it to the particularities of each client (databases, tables, filters, network services,...)
A client of mine has a software with that open functionality but I ignore the details.
It also be great if python could be integrated!
Using VBCodeProvider you can compile VB.NET code at run-time.
The following example, compiles a piece of VB.NET code at run-time and run it:
private void button1_Click(object sender, EventArgs e)
{
using (var vbc = new VBCodeProvider())
{
var parameters = new CompilerParameters(new[] {
"mscorlib.dll",
"System.Windows.Forms.dll",
"System.dll",
"System.Drawing.dll",
"System.Core.dll",
"Microsoft.VisualBasic.dll"});
var results = vbc.CompileAssemblyFromSource(parameters,
#"
Imports System.Windows.Forms
Imports System.Drawing
Public Class Form1
Inherits Form
public Sub New ()
Dim b as Button = new Button()
b.Text = ""Button1""
AddHandler b.Click,
Sub (s,e)
MessageBox.Show(""Hello from runtime!"")
End Sub
Me.Controls.Add(b)
End Sub
End Class");
//Check if compilation is successful, run the code
if (!results.Errors.HasErrors)
{
var t = results.CompiledAssembly.GetType("Form1");
Form f = (Form)Activator.CreateInstance(t);
f.ShowDialog();
}
else
{
var errors = string.Join(Environment.NewLine,
results.Errors.Cast<CompilerError>()
.Select(x => x.ErrorText));
MessageBox.Show(errors);
}
}
}

Selenium can't handle multiple ChromiumWebBrowser instances in C#

I have two instances of the ChromiumWebBrowser in my WinForms project (Visual Studio 2012). My goal is to have the second browser instance "copy" the behavior of the user input in the first browser instance. I can successfully retrieve the input from the first browser, and I managed to hook up Selenium in the project as well.
However, I'm having one issue. Whenever Selenium sends its commands, the first browser is the one that responds to them. For the life of me, I can't seem to figure out how to make the second browser respond. Whenever I completely remove the first browser, the second one starts responding correctly, but adding the first browser again will make only have the first browser use the Selenium commands. I even tried to switch out the moments the browsers are added to the form, but to no avail: whenever there are two available, the wrong one is responsive.
Relevant code:
public BrowserManager(Controller controller, string startingUrl)
{
_controller = controller;
var settings = new CefSettings { RemoteDebuggingPort = 9515 };
Cef.Initialize(settings);
// Input browser
inputBrowser = new ChromiumWebBrowser(startingUrl);
var obj = new XPathHelper(this);
inputBrowser.RegisterJsObject("bound", obj); //Standard object registration
inputBrowser.FrameLoadEnd += obj.OnFrameLoadEnd;
// Output browser
var browserSettings = new BrowserSettings();
var requestContextSettings = new RequestContextSettings { CachePath = "" };
var requestContext = new RequestContext(requestContextSettings);
outputBrowser = new ChromiumWebBrowser(startingUrl);
outputBrowser.RequestContext = requestContext;
outputBrowser.AddressChanged += InitializeOutputBrowser;
outputBrowser.Enabled = false;
outputBrowser.Name = "outputBrowser";
}
The selenium part:
public class SeleniumHelper
{
public SeleniumHelper()
{
DoWorkAsync();
}
private Task DoWorkAsync()
{
Task.Run(() =>
{
string chromeDriverDir = #"ActionRecorder\bin\x64\Debug\Drivers";
var chromeDriverService = ChromeDriverService.CreateDefaultService(chromeDriverDir);
chromeDriverService.HideCommandPromptWindow = true;
ChromeOptions options = new ChromeOptions();
options.BinaryLocation = #"ActionRecorder\bin\x64\Debug\ActionRecorder.exe";
options.DebuggerAddress = "127.0.0.1:9515";
options.AddArguments("--enable-logging");
using (IWebDriver driver = new OpenQA.Selenium.Chrome.ChromeDriver(chromeDriverService, options))
{
driver.Navigate().GoToUrl("http://www.google.com");
var query = driver.FindElement(By.Name("q"));
query.SendKeys("A google search test");
query.Submit();
}
});
return null;
}
}
And finally, a screenshot for some visualization:
Some help with the issue would be very much appreciated. If i missed some crucial info, feel free to ask for it. Thanks in advance!
Greetz,
Tybs
The behavior is correct. You have one debug address and you can only have one debug address for CEF. Which means when you use Selenium it is only seeing one browser.
By default Selenium will send an command to current active Tab or Window. Now in your case you have multiple Chrome view embedded, but they are technically Chrome Tab/Windows which you have placed on the same form.
So if you are in luck below code in should be able to move you to the Window you are interested in
driver.SwitchTo().Window(driver.WindowHandles.Last());
See if it works. If it doesn't then your only other workaround would be to change the order of Adding ChromiumWebBrowser and that should reverse the window it works on.
Below are some important threads that you should read from top to bottom. Very relevant to your issue/request
https://code.google.com/archive/p/chromiumembedded/issues/421
https://github.com/cefsharp/CefSharp/issues/1076

VMWare Vim, Getting PortWorldWideName property using c# or vb.net

I try to enumerate all hosts, vm's and storage-adapters in my vCenter-infrastructure by using the vmware.vim-library in vb.net.
But I cannot find a way to get the WWN from the HBA...in powershell there is a property called 'portworldwidename' but this is not available using .net.
foreach($hba in $esx.Config.StorageDevice.HostBusAdapter){
if($hba.GetType().Name -eq "HostFibreChannelHba"){
$wwn = $hba.PortWorldWideName
$wwnhex = "{0:x}" -f $wwn
Write-Host $wwnhex
}
}
This is what I have in vb.net:
Dim c As New VimClient
c.Connect("https://myvcenter/sdk")
c.Login("username", "password")
Dim vmsHosts = c.FindEntityViews(GetType(HostSystem), Nothing, Nothing, Nothing)
For Each evbHostSystem In vmsHosts
Dim hs = CType(evbHostSystem, HostSystem)
Console.WriteLine(hs.Name)
Dim hbas = hs.Config.StorageDevice.HostBusAdapter
For Each hba In hbas
Console.WriteLine(hba.Model)
'hba.portworldwidename is not available...
Next
Next
Thanks for any help!
Regards,
Jan
Found it:
You need to get the type of the returning HBA-object. If it's "HostFibreChannelHba" you need to cast it an 'HostFibreChannelHba'. Then, all properties are available.
Need to take a deeper look at the VI API-Guide :)
Dim hbas = hs.Config.StorageDevice.HostBusAdapter
For Each hba In hbas
Console.WriteLine(hba.Model)
If hba.GetType.Name.Equals("HostFibreChannelHba") Then
Dim fibreHBA = CType(hba, HostFibreChannelHba)
Console.WriteLine(String.Format("{0:x}", fibreHBA.PortWorldWideName))
End If
Next
Regards,
Jan

How can I force web browser control to remember proxy credentials setting?

I'm using .net web browser control to open an url in new window through proxy with credentials. I use this code for that:
Public Function AppendHeader(ByRef OriginalHeader As String, ByVal Addition As String) As Boolean
If OriginalHeader <> "" Then
OriginalHeader = OriginalHeader + vbNewLine
End If
OriginalHeader = OriginalHeader + Addition
OriginalHeader.Trim(vbNewLine.ToCharArray)
End Function
Public Function Base64Enc(ByRef s As String) As String
Base64Enc = Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(s))
End Function
Public Sub Navigate()
Dim webBrowser As WebBrowser = New WebBrowser()
Dim headers As String = ""
AppendHeader(headers, "Proxy-Authorization: Basic " & Base64Enc("user:pass"))
'AppendHeader(headers, "Authorization: Basic " & Base64Enc("user:pass"))
webBrowser.Navigate("http://stackoverflow.com", Guid.NewGuid().ToString(), Nothing, headers)
End Sub
This code helps to hide Windows Security window at the first time, but if loading web page sends requests to other urls this window shows again and again (you can see it on a screenshot below).
So what can I do to solve this problem?
(I'm using winforms and vb.net, but C# is suitable too)
Give this a try I am unable to test it :)
Private Sub webBrowser_Navigating(ByVal sender As Object, ByVal e As WebBrowserNavigatingEventArgs)
Dim credentials As New System.Net.NetworkCredential("user", "pwd", "MyDomain")
Dim proxy As New System.Net.WebProxy("127.0.1.2", 80)
If proxy Is Nothing Then
e.Cancel = True
End If
End Sub

Are there any Outlook Contacts Controls in ASP.NET?

How can I access Microsoft Outlook contacts using ASP.NET? Are there any controls that can do this?
If by control you mean api, there already is one - Exchange Web Services (EWS). Assuming you are dealing with exchange, and have EWS set up. The web services usually sit at:
https://[yourmaildomain.com]/EWS/Exchange.asmx
Here is some quick code - not production tested (also in vb.net)
Dim esb As New ExchangeServiceBinding()
esb.Credentials = New NetworkCredential("someusername", "somepassword")
esb.Url = "https://[yourmaildomain.com]/EWS/Exchange.asmx"
Dim addressType As New EmailAddressType()
With addressType
.EmailAddress = "email#domain.com"
.MailboxType = MailboxTypeType.Mailbox
.MailboxTypeSpecified = True
End With
' properties
Dim itemProperties As New ItemResponseShapeType()
itemProperties.BaseShape = DefaultShapeNamesType.AllProperties
' Identify which folders to search to find items.
Dim folderIDs(0) As DistinguishedFolderIdType
folderIDs(0) = New DistinguishedFolderIdType()
folderIDs(0).Id = DistinguishedFolderIdNameType.contacts
folderIDs(0).Mailbox = addressType
Dim findItemRequest As New FindItemType()
findItemRequest.Traversal = ItemQueryTraversalType.Shallow
findItemRequest.ItemShape = itemProperties
findItemRequest.ParentFolderIds = folderIDs
' send request
Dim findItemResponse As FindItemResponseType = esb.FindItem(findItemRequest)
Dim rmta As ResponseMessageType() = findItemResponse.ResponseMessages.Items
For Each rmt As ResponseMessageType In rmta
If rmt.ResponseClass = ResponseClassType.Success Then
Dim firmt As FindItemResponseMessageType = CType(rmt, FindItemResponseMessageType)
If firmt IsNot Nothing Then
Dim root As FindItemParentType = firmt.RootFolder
Dim obj As Object = root.Item
If TypeOf obj Is ArrayOfRealItemsType Then
Dim items As ArrayOfRealItemsType = DirectCast(obj, ArrayOfRealItemsType)
If items.Items IsNot Nothing Then
For Each it As ItemType In items.Items
If TypeOf it Is ContactItemType Then
Dim cit As ContactItemType = DirectCast(it, ContactItemType)
Response.Write("<p>")
Response.Write(cit.Subject)
Response.Write("<p>")
End If
Next
End If
End If
End If
End If
Next
FROM Microsoft Support:
How to use the Microsoft Outlook Object Library to retrieve a contact by using Visual C#
MSDN:
Outlook Object Model Overview
How to: Access Outlook Contacts (Some more nice how to's at the end)
You would need to create an ActiveX Application that the client would install to allow you access to this. Unless it's an internal development project, don't expect people to install something that gives you access to their email program.

Categories