I would like to have a IWebDriver of an already opened browser like Chrome. Because then I need to automate a form authentication and/or a basic authentication.
I thought that this
IWebDriver driver = new RemoteWebDriver(new System.Uri("http://localhost:4445/wd/hub"), new ChromeOptions());
would do the trick but it only opens another chrome window. Instead I would like to "read" an already opened one.
Is it possible with selenium? O r should I use another library?
As per the Selenium Issues page:
https://github.com/seleniumhq/selenium-google-code-issue-archive/issues/18
The issue was closed and marked as not feasible
The process of connecting to an existing browser would be on a per-browser basis.
Doing it in IE might be easy, but doing it in Chrome or Firefox would be problematic.
Eg:
Chrome actually receives the commands from Selenium via network / tcp json requests to a specific port.
When Selenium driver stops running - it loses the port number for the Chrome debugging port.
The port may still be open, but it could be anything between 10000 and 30000 etc
Even if you solve it for Chrome, it would then require another bespoke solution for Firefox.
Unless your authentication has a 'Captcha' or bot check in place, I would suggest just automating the authentication stage.
Generally speaking - it is a good practice for Automated tests to be self-contained and not rely on outside interference or external tests.
A browser should start at the start of the test and be terminated at the end of the test.
Assuming you are using Selenium for testing and not for malicious purposes.
Selenium will not be helpful to you at this stage.
If however, you can live with your answer / solution being on Chrome but not the other browsers.
public static Chrome StartChromeDriver(int port)
{
try
{
string Path = Registry.Installation.GetChromeExecutable();
Process p = new Process();
ProcessStartInfo psi = new ProcessStartInfo(Path);
string args = "--remote-debugging-port="+ port.ToString()+" --user-data-dir=remote-profile";
psi.Arguments = args;
psi.Verb = "runas";
p.StartInfo = psi;
p.Start();
return new Chrome("http://localhost:" + port.ToString());
}
catch (Exception ee)
{
Console.WriteLine(ee.ToString());
return null;
}
}
This will start a chrome process with the debugging port opened to the number you provide.
(You can keep track of this, and reconnect and re-issue commands to the running chrome instance)
public dynamic EnablePage()
{
json = #"{""id"":12345,""method"":""Page.enable""}";
Thread.Sleep(1000);
return this.SendCommand(json);
}
public dynamic EnableRuntime()
{
json = #"{""id"":12345,""method"":""Runtime.enable""}";
Thread.Sleep(1000);
return this.SendCommand(json);
}
public dynamic EnableNetwork()
{
json = #"{""id"":12345,""method"":""Network.enable""}";
Thread.Sleep(1000);
return this.SendCommand(json);
}
This is some code I had lying around.
I was very bored one day and decided to reinvent the wheel with Chrome automation. Basically - this code is how you could automate Chrome without using Selenium at all.
It does have a dependency on WebSockets4Net
But that being said - it could probably be refactored to use TcpClient.
All the commands that are issued to Chrome, are done in the form of a json request.
Eg: the following json command would tell chrome to execute the following javascript - essentially navigating to the url provided.
{
"method": "Runtime.evaluate",
"params": {
"expression": "document.location='urlhere'",
"objectGroup": "console",
"includeCommandLineAPI": true,
"doNotPauseOnExceptions": false,
"returnByValue": false
},
"id": 1
}
public dynamic SendCommand(string cmd)
{
if (EventHandler == null)
{
EventHandler = new Events();
EventHandler.OnNavigateStart += new Events.OnPageNavigateStart(EventHandler_OnNavigateStart);
EventHandler.OnNavigateEnd += new Events.OnPageNavigateEnded(EventHandler_OnNavigateEnd);
}
WebSocket4Net.WebSocket j = new WebSocket4Net.WebSocket(this.sessionWSEndpoint);
ManualResetEvent waitEvent = new ManualResetEvent(false);
ManualResetEvent closedEvent = new ManualResetEvent(false);
dynamic message = null;
byte[] data;
Exception exc = null;
j.Opened += delegate(System.Object o, EventArgs e)
{
j.Send(cmd);
};
j.MessageReceived += delegate(System.Object o, WebSocket4Net.MessageReceivedEventArgs e)
{
message = e.Message;
EventHandler.ParseEvents(e);
waitEvent.Set();
};
j.Error += delegate(System.Object o, SuperSocket.ClientEngine.ErrorEventArgs e)
{
exc = e.Exception;
waitEvent.Set();
};
j.Closed += delegate(System.Object o, EventArgs e)
{
closedEvent.Set();
};
j.DataReceived += delegate(object sender, WebSocket4Net.DataReceivedEventArgs e)
{
data = e.Data;
waitEvent.Set();
};
j.Open();
waitEvent.WaitOne();
if (j.State == WebSocket4Net.WebSocketState.Open)
{
j.Close();
closedEvent.WaitOne();
j = null;
}
if (exc != null)
throw exc;
serializer = null;
serializer = new JavaScriptSerializer();
serializer.RegisterConverters(new[] { converter });
dynamic obj = serializer.Deserialize(message, typeof(object));
message = null;
data = null;
return obj;
}
To demonstrate how this could be used practically - you can implement page-object and create 'types' that encapsulate objects on screen.
For instance:
public class Link : Base.Element
{
public Link(string XPath)
{
this.XPath = String.Copy(XPath);
}
/// <summary>
/// Overriding it - just in case we need to handle clicks differently
/// </summary>
/// <returns></returns>
public virtual bool Click()
{
Sync();
Console.WriteLine(Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).click();"));
return true;
}
public virtual bool WaitForExistance(int iTimeout)
{
return base.WaitForExistance(iTimeout);
}
public virtual bool Exists()
{
return base.Exists();
}
public virtual string GetText()
{
Sync();
dynamic dval = Chrome.Driver.Eval("document.evaluate('" + XPath.Replace("'", "\\\\'") + "', document.documentElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null ).snapshotItem(0).innerText");
return dval.result.result.value;
}
}
Be warned - there were memory leaks in WebSockets4Net when I was using this code - so the application eventually had to be restarted.
Perhaps if WebSockets4Net is removed and replaced - it will work better.
Related
I am trying to transfer a file to my iphone using 32feet bluetooth, but cannot seem to get past the ObexWebResponse.
I have read many post on this but none of the solutions seem to work for me.
The Error i get is
// Connect failed
// The requested address is not valid in its context "address:Guid"
private BluetoothClient _bluetoothClient;
private BluetoothComponent _bluetoothComponent;
private List<BluetoothDeviceInfo> _inRangeBluetoothDevices;
private BluetoothDeviceInfo _hlkBoardDevice;
private EventHandler<BluetoothWin32AuthenticationEventArgs> _bluetoothAuthenticatorHandler;
private BluetoothWin32Authentication _bluetoothAuthenticator;
public BTooth() {
_bluetoothClient = new BluetoothClient();
_bluetoothComponent = new BluetoothComponent(_bluetoothClient);
_inRangeBluetoothDevices = new List<BluetoothDeviceInfo>();
_bluetoothAuthenticatorHandler = new EventHandler<BluetoothWin32AuthenticationEventArgs>(_bluetoothAutenticator_handlePairingRequest);
_bluetoothAuthenticator = new BluetoothWin32Authentication(_bluetoothAuthenticatorHandler);
_bluetoothComponent.DiscoverDevicesProgress += _bluetoothComponent_DiscoverDevicesProgress;
_bluetoothComponent.DiscoverDevicesComplete += _bluetoothComponent_DiscoverDevicesComplete;
ConnectAsync();
}
public void ConnectAsync() {
_inRangeBluetoothDevices.Clear();
_hlkBoardDevice = null;
_bluetoothComponent.DiscoverDevicesAsync(255, true, true, true, false, null);
}
private void PairWithBoard() {
Console.WriteLine("Pairing...");
bool pairResult = BluetoothSecurity.PairRequest(_hlkBoardDevice.DeviceAddress, null);
if (pairResult) {
Console.WriteLine("Success");
Console.WriteLine($"Authenticated equals {_hlkBoardDevice.Authenticated}");
} else {
Console.WriteLine("Fail"); // Instantly fails
}
}
private void _bluetoothComponent_DiscoverDevicesProgress(object sender, DiscoverDevicesEventArgs e) { _inRangeBluetoothDevices.AddRange(e.Devices); }
private void _bluetoothComponent_DiscoverDevicesComplete(object sender, DiscoverDevicesEventArgs e) {
for (int i = 0; i < _inRangeBluetoothDevices.Count; ++i) {
if (_inRangeBluetoothDevices[i].DeviceName == "Uranus") {
_hlkBoardDevice = _inRangeBluetoothDevices[i];
PairWithBoard();
TransferFile();
return;
}
}
// no devices found
}
private void _bluetoothAutenticator_handlePairingRequest(object sender, BluetoothWin32AuthenticationEventArgs e) {
e.Confirm = true; // Never reach this line
}
// not working
// transfers a file to the phone
public void TransferFile() {
string file = "E:\\test.txt",
filename = System.IO.Path.GetFileName(file);
string deviceAddr = _hlkBoardDevice.DeviceAddress.ToString();
BluetoothAddress addr = BluetoothAddress.Parse(deviceAddr);
_bluetoothClient.Connect(BluetoothAddress.Parse(deviceAddr), BluetoothService.SerialPort);
Uri u = new Uri($"obex://{deviceAddr}/{file}");
ObexWebRequest owr = new ObexWebRequest(u);
owr.ReadFile(file);
// error:
// Connect failed
// The requested address is not valid in its context ...
var response = (ObexWebResponse)owr.GetResponse();
Console.WriteLine("Response Code: {0} (0x{0:X})", response.StatusCode);
response.Close();
}
The pairing and authentication works just fine, and I can get the BluetoothService.Handsfree to make a call for me but the transferring of the file fails. Not knowing what the actual error is, I tried almost every service available with no luck.
Can you help me figure out what is going on? This is my first attempt working with Bluetooth services so I still have a ton to learn.
Is it possible to transfer a file from iPhone to Windows desktop via Bluetooth?
However, in case you need to transfer media files (images, videos, etc) from Android device, you can use ObexListener class provided by 32Feet library for this purpose, and then you can simply call _obexListener.GetContext() method that will block and wait for incoming connections.
Once a new connection is received, you can save the received file to local storage, as shown in the below example:
ObexListener _listener = new ObexListener();
_listener.Start();
// This method will block and wait for incoming connections
ObexListenerContext _context = _listener.GetContext();
// Once new connection is received, you can save the file to local storage
_context.Request.WriteFile(#"c:\sample.jpg");
NOTE: When working with OBEX on Windows, make sure to disable the "Bluetooth OBEX Service" Windows service, in order not to let it handle the incoming OBEX requests instead of the desired application.
I walked away from this for a while. and started Trying to use xamiren but then had to create a virtual Mac so that I could have the apple store to just load software on my phone. From there xamerin 'should' work well but its another field and tons more to firgure out.
I want to kill a running IIS Instance programmatically that is occupying a specific port, but it seems there is no way to figure out what IIS Instance is using a specific port.
netstat.exe just shows that the process is having the PID 4, but that's the system process. "netsh http show urlacl" does not display the occupied port at all.
The IIS Express Tray program knows this somehow. When I try to start another IIS Express instance while the port is occupied I get the following error:
"Port '40000' is already being used by process 'IIS Express' (process ID '10632').
Anyone got a clue how I can get this information?
It seems like the PID is 4 (System) because the actual listening socket is under a service called http.
I looked at what iisexpresstray.exe was using to provide a list of all running IISExpress applications. Thankfully it's managed .NET code (all in iisexpresstray.dll) that's easily decompiled.
It appears to have at least three different ways of getting the port number for a process:
Reading /port from the command-line arguments (unreliable as we know)
Running netsh http show servicestate view=requestq and parsing the output
Calling Microsoft.Web.RuntimeStatusClient.GetWorkerProcess(pid) and parsing the site URL
Unfortunately, most of the useful stuff in iisexpresstray.dll like the IisExpressHelper class is declared internal (although I imagine there're tools to generate wrappers or copy the assembly and publicize everything).
I opted to use Microsoft.Web.dll. It was in my GAC, though for some reason wasn't appearing in the list of assemblies available to add as a reference in Visual Studio, so I just copied the file out from my GAC. Once I had Microsoft.Web.dll it was just a matter of using this code:
using (var runtimeStatusClient = new RuntimeStatusClient())
{
var workerProcess = runtimeStatusClient.GetWorkerProcess(process.Id);
// Apparently an IISExpress process can run multiple sites/applications?
var apps = workerProcess.RegisteredUrlsInfo.Select(r => r.Split('|')).Select(u => new { SiteName = u[0], PhysicalPath = u[1], Url = u[2] });
// If we just assume one app
return new Uri(apps.FirstOrDefault().Url).Port;
}
You can also call RuntimeClient.GetAllWorkerProcesses to retrieve only actual worker processes.
I looked into RegisteredUrlsInfo (in Microsoft.Web.dll) as well and found that it's using two COM interfaces,
IRsca2_Core (F90F62AB-EE00-4E4F-8EA6-3805B6B25CDD)
IRsca2_WorkerProcess (B1341209-7F09-4ECD-AE5F-3EE40D921870)
Lastly, I read about a version of Microsoft.Web.Administration apparently being able to read IISExpress application info, but information was very scarce, and the one I found on my system wouldn't even let me instantiate ServerManager without admin privileges.
Here is a C# implementation of calling netsh.exe as recommended within the answer by #makhdumi:
Usage:
static public bool TryGetCurrentProcessRegisteredHttpPort(out List<int> ports, out Exception ex)
{
NetshInvoker netsh = new NetshInvoker();
return netsh.TryGetHttpPortUseByProcessId(Process.GetCurrentProcess().Id, out ports, out ex);
}
Implementation:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
namespace YourCompanyName.Server.ServerCommon.Utility
{
/// <summary>
/// Invoke netsh.exe and extract information from its output.
/// Source: #crokusek, https://stackoverflow.com/questions/32196188
/// #GETah, https://stackoverflow.com/a/8274758/538763
/// </summary>
public class NetshInvoker
{
const string NetshHttpShowServiceStateViewRequestqArgs = "http show servicestate view=requestq";
public NetshInvoker()
{
}
/// <summary>
/// Call netsh.exe to determine the http port number used by a given windowsPid (e.g. an IIS Express process)
/// </summary>
/// <param name="windowsPid">For example an IIS Express process</param>
/// <param name="port"></param>
/// <param name="ex"></param>
/// <returns></returns>
public bool TryGetHttpPortUseByProcessId(Int32 windowsPid, out List<Int32> ports, out Exception ex)
{
ports = null;
try
{
if (!TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out ex))
return false;
if (!pidToUrlMap.TryGetValue(windowsPid, out List<string> urls))
{
throw new Exception(String.Format("Unable to locate windowsPid {0} in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
if (!urls.Any())
{
throw new Exception(String.Format("WindowsPid {0} did not reference any URLs in '{1}' output.",
windowsPid, "netsh " + NetshHttpShowServiceStateViewRequestqArgs));
}
ports = urls
.Select(u => new Uri(u).Port)
.ToList();
return true;
}
catch (Exception ex_)
{
ex = ex_;
return false;
}
}
private bool TryQueryProcessIdRegisteredUrls(out Dictionary<Int32, List<string>> pidToUrlMap, out Exception ex)
{
if (!TryExecNetsh(NetshHttpShowServiceStateViewRequestqArgs, out string output, out ex))
{
pidToUrlMap = null;
return false;
}
bool gotRequestQueueName = false;
bool gotPidStart = false;
int currentPid = 0;
bool gotUrlStart = false;
pidToUrlMap = new Dictionary<int, List<string>>();
foreach (string line in output.Split('\n').Select(s => s.Trim()))
{
if (!gotRequestQueueName)
{
gotRequestQueueName = line.StartsWith("Request queue name:");
}
else if (!gotPidStart)
{
gotPidStart = line.StartsWith("Process IDs:");
}
else if (currentPid == 0)
{
Int32.TryParse(line, out currentPid); // just get the first Pid, ignore others.
}
else if (!gotUrlStart)
{
gotUrlStart = line.StartsWith("Registered URLs:");
}
else if (line.ToLowerInvariant().StartsWith("http"))
{
if (!pidToUrlMap.TryGetValue(currentPid, out List<string> urls))
pidToUrlMap[currentPid] = urls = new List<string>();
urls.Add(line);
}
else // reset
{
gotRequestQueueName = false;
gotPidStart = false;
currentPid = 0;
gotUrlStart = false;
}
}
return true;
}
private bool TryExecNetsh(string args, out string output, out Exception exception)
{
output = null;
exception = null;
try
{
// From #GETah, https://stackoverflow.com/a/8274758/538763
Process p = new Process();
p.StartInfo.FileName = "netsh.exe";
p.StartInfo.Arguments = args;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.Start();
output = p.StandardOutput.ReadToEnd();
return true;
}
catch (Exception ex)
{
exception = ex;
return false;
}
}
}
}
In my case I just output "Command line" column in Task manager and it's getting obvious, which IISExpress is that:
You can run below command to get the information of the executable and its PID
netstat -a -n -o -b | find "iisexpress.exe"
I am using Fiddler to catch updates sent to a page via LightStreamer. I am creating a FiddlerCore proxy and connecting a Selenium ChromeDriver instance to it. My automation navigates Chrome to the page, and data comes through the proxy.
Once loaded, the updates to the page (via LightStreamer) visibly appear on the page but they do not come through the AfterSessionComplete event.
If I run the Fiddler desktop application instead of launching my proxy (comment out "StartProxy()") all of the updates (via LightStreamer) come through and appear inside the application. They appear has HTTPS data, but other HTTPS data appears to come through.
I have also using tried the BeforeResponse event instead of AfterSessionCompleted.
Here's my code:
static void Main(string[] args)
{
StartProxy();
var seleniumProxy = new Proxy { HttpProxy = "localhost:8888", SslProxy = "localhost:8888" };
var chromeOptions = new ChromeOptions { Proxy = seleniumProxy };
var path = Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86) + "\\ChromeDriver\\";
var chromeService = ChromeDriverService.CreateDefaultService(path);
var driver = new ChromeDriver(chromeService, chromeOptions);
driver.Navigate().GoToUrl("https://mywebpage.com");
// page loads and updates start flowing
Console.ReadLine();
driver.Dispose();
StopProxy();
}
private static void FiddlerApplication_AfterSessionComplete(Session session)
{
// data comes through, just not the LightStreamer Data
var respBody = session.GetResponseBodyAsString();
Console.WriteLine(respBody);
// do something with the response body.
}
static void StartProxy()
{
if (FiddlerApplication.IsStarted())
FiddlerApplication.Shutdown();
FiddlerApplication.AfterSessionComplete += FiddlerApplication_AfterSessionComplete;
FiddlerApplication.Startup(8888, FiddlerCoreStartupFlags.DecryptSSL);
}
static void StopProxy()
{
FiddlerApplication.AfterSessionComplete -= FiddlerApplication_AfterSessionComplete;
if (FiddlerApplication.IsStarted())
FiddlerApplication.Shutdown();
}
Thanks for your help.
Update: I've also tried to use the flag: FiddlerCoreStartupFlags.Default instead of FiddlerCoreStartupFlags.DecryptSSL when starting fiddler with no luck.
I've been trying to create an updater app for my .NET application that gets called when an update is detected using a text file that includes the version info. I've created the said updater but it has some problems. When the file is downloaded, it seems like the anti virus software corrupts the file and it can't be opened. Sometimes the updater doesn't run at all and throws an exception ("The underlying connection was closed: The connection was closed unexpectedly.") which seems to also be caused by the local anti virus software. I figured maybe I could download the file in binary format and create the executable locally, but I am not completely sure on how I would do that (or if it would even work). I am still very much a beginner in a lot of areas. So my question is.. how can I efficiently download an update for my application without triggering the anti- virus?
My code:
public Updater()
{
InitializeComponent();
DownloadInfo.RemoteURI = "http://mywebserver.com/Application.exe";
DownloadInfo.NewExecutableName = "update.exe";
DownloadInfo.ExecutableName = "Application.exe";
DownloadInfo.LocDest = AppDomain.CurrentDomain.BaseDirectory;
InvokeUpdate();
}
private void InvokeUpdate()
{
Thread thr = new Thread(() => GetUpdate());
thr.Start();
}
private void GetUpdate()
{
Process[] proc = Process.GetProcessesByName("Application");
if (proc.Length != 0)
proc[0].Kill();
Util.DownloadFile(new Uri(DownloadInfo.RemoteURI), DownloadInfo.LocDest + DownloadInfo.NewExecutableName);
if (File.Exists(DownloadInfo.LocDest + DownloadInfo.ExecutableName))
File.Replace(DownloadInfo.LocDest + DownloadInfo.NewExecutableName, DownloadInfo.LocDest + DownloadInfo.ExecutableName, DownloadInfo.LocDest + "backup.exe");
else
File.Move(DownloadInfo.LocDest + DownloadInfo.NewExecutableName, DownloadInfo.LocDest + DownloadInfo.ExecutableName);
try
{
File.Delete(DownloadInfo.LocDest + "backup.exe");
}
catch { }
try
{
Process.Start(DownloadInfo.LocDest + DownloadInfo.ExecutableName);
}
catch { };
Invoke((MethodInvoker)(() => this.Close()));
}
And my DownloadFile method from my util class..
public static void DownloadFile(Uri remoteURI, string localDest)
{
try
{
using (WebClient webclient = new WebClient())
{
webclient.DownloadFile(remoteURI, localDest);
}
}
catch { }
}
I never used fiddler core before. But after first time using it into my application, a weird problem is happening. Whenever my application is running web browsers are working fine. But other time those all showing error page. I know I did something wrong with fiddler core. I am sending my codes here. Codes are working perfectly. But there is something into my code so that I getting this problem. Please see the code and let me know what am I doing wrong.
static bool bUpdateTitle = true;
static Proxy oSecureEndpoint;
static string sSecureEndpointHostname = "localhost";
static int iSecureEndpointPort = 1106;
private void button1_Click(object senderr, EventArgs e)
{
List<Fiddler.Session> oAllSessions = new List<Fiddler.Session>();
Fiddler.FiddlerApplication.OnNotification += delegate(object sender, NotificationEventArgs oNEA) { MessageBox.Show("** NotifyUser: " + oNEA.NotifyString); };
Fiddler.FiddlerApplication.BeforeRequest += delegate(Fiddler.Session oS)
{
oS.bBufferResponse = false;
Monitor.Enter(oAllSessions);
oAllSessions.Add(oS);
Monitor.Exit(oAllSessions);
if (oS.hostname=="localhost")
{
oS.utilCreateResponseAndBypassServer();
oS.oResponse.headers.HTTPResponseStatus = "200 Ok";
oS.oResponse["Content-Type"] = "text/html; charset=UTF-8";
oS.oResponse["Cache-Control"] = "private, max-age=0";
oS.utilSetResponseBody("<html><body><font size=10>Restricted</font></body></html>");
}
};
Fiddler.CONFIG.IgnoreServerCertErrors = false;
FiddlerApplication.Prefs.SetBoolPref("fiddler.network.streaming.abortifclientaborts", true);
FiddlerCoreStartupFlags oFCSF = FiddlerCoreStartupFlags.Default;
Fiddler.FiddlerApplication.Startup(0, oFCSF);
oSecureEndpoint = FiddlerApplication.CreateProxyEndpoint(iSecureEndpointPort, true, sSecureEndpointHostname);
}
public static void DoQuit()
{
if (null != oSecureEndpoint) oSecureEndpoint.Dispose();
Fiddler.FiddlerApplication.Shutdown();
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
DoQuit();
}
As mentioned in the response to your same message left in the Fiddler discussion group, this means that you ran your program at least once without properly calling Shutdown() (e.g. because it crashed). Clear the incorrect proxy settings from Tools > Internet Options > Connections > LAN Settings when your program isn't running.