Open and close internet browser with C# console application [duplicate] - c#

This question already has answers here:
calling an http url from a .net console application?
(3 answers)
Closed 7 years ago.
I have a simple console application in C# that I'm going to use to poll three URLs in order to update a website that was produced by a third party (stock levels, product images etc.). The console application is as below:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Diagnostics;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Process.Start(#"http://URL1");
System.Diagnostics.Process.Start(#"http://URL2");
System.Diagnostics.Process.Start(#"http://URL3");
}
}
}
This works perfectly but leaves the windows open (three tabs on in a single browser instance). As this will run every hour or so, is there a way I can also get the application to 'kill' the windows once they have been opened? Otherwise the system memory will slowly be consumed by Internet Explorer sessions.
I couldn't find anything else regarding closing browsers from a console application but if I'm wrong please point in the right direction.
Nothing else will be using the browsers so it doesn't need to check if the browser was opened by the console, it just needs to close the application. It will be running as a scheduled task on a remote server. Thanks.
SOLUTION
The simplest way was to change to HttpWebRequest as suggested. Resultant code below:
static void Main(string[] args)
{
HttpWebRequest myReq1 = (HttpWebRequest)WebRequest.Create("http://URL1");
HttpWebRequest myReq2 = (HttpWebRequest)WebRequest.Create("http://URL2");
HttpWebRequest myReq3 = (HttpWebRequest)WebRequest.Create("http://URL3");
}

You do not need a browser instance to request a URL, your console app should request the URL using either a WebClient or an HttpWebRequest.

You can kill the browser process by name:
foreach (var process in Process.GetProcessesByName("iexplore.exe"))
{
process.Kill();
}

Related

C# Based Testing Automation Attaching to Existing Browser

C#, Visual Studio 2015, .NET 4.x Framework, Internet Explorer 11 (or latest Chrome), Windows 8.1 Pro workstation.
For testing purposes, using a Windows Forms or Console application written in C#, I need to automate an existing browser instance running on a Windows 8 or 10 system.
I created a Windows Forms application, and I'm able to automate a browser that I start using the Navigate(...) method within the application using the WebBrowser control and do things like click on a button in a Javascript popup, login using a username and password, select an item from the datagridview and click on the "edit" button associated with that item.
However, once that "edit" button is clicked, additional browser windows are created that are now running outside the "scope" of the WebBrowser control.
The web application opens new instances of the browser using window.open(...,_blank);
I've tried working with the NewWindow event, but I don't seem to be able to grab any kind of "handle" or such to the newly opened windows. The event fires, but what I'm seeing when I debug inside the event is just information about the window that I'm currently working with (not the newly spawned window).
The other things I've tried are Selenium and WatIn.
For both, the examples I had an instance of Internet Explorer 11 running on my Windows 8.1 Pro workstation at www.google.com.
Generally, the examples seem to show that for "attaching to an existing instance" of a browser the examples first firing off the browser. I've tried to connect to an existing browser using both libraries, and I've not had success.
I've tried to use the RemoteWebDriver(...) for Selenium, using the InternetExplorer driver. Another Stack Overflow post indicates I don't need the server component running because the browser and application for testing are on the same machine. My code is as follows:
private void doSeleniumStuff()
{
DesiredCapabilities desired = DesiredCapabilities.InternetExplorer();
using (IWebDriver driver = new RemoteWebDriver(new Uri("http://www.google.com/wd/hub"), desired))
{
IWebElement query = driver.FindElement(By.Name("q"));
query.SendKeys("Cheese");
query.Submit();
var wait = new WebDriverWait(driver, TimeSpan.FromSeconds(10));
wait.Until(d => d.Title.StartsWith("cheese", StringComparison.OrdinalIgnoreCase));
Console.WriteLine("Page title is: " + driver.Title);
}
}
I'm somewhat confused about the URL used in the RemoteWebDriver constructor. The documentation doesn't seem to describe this usage well. What is this "/wd/hub" usage all about?
It failes with:
{"Unexpected error. <!DOCTYPE html>\r\n<html lang=en>\r\n <meta charset=utf-8>\r\n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\r\n <title>Error 404 (Not Found)!!1</title>\r\n <style>\r\n *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}#media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}#media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}#media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\r\n </style>\r\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\r\n <p><b>404.</b> <ins>That’s an error.</ins>\r\n <p>The requested URL <code>/wd/hub/session</code> was not found on this server. <ins>That’s all we know.</ins>\r\n"}
I've tried using the AttachTo(...) method in WatIn.
[STAThread]
private void doWatNStuff()
{
using (IE myIE = Browser.AttachTo<IE>(Find.Any))
{
DomContainer dc = myIE.DomContainer;
}
}
Fails in the using with
{"Could not find an IE window matching constraint: Any. Search expired
after '30' seconds."}
The example code provided for WatIn has the code first creating an instance of IE and then attaching to it. I can't help but think that WatIn can attach to a running instance of a browser, but WatIn must first create that instance.
That won't meet my needs.
My final attempt was to use System.Windows.Automation to get an open Internet Explorer window and try to work with it. While I get the window, all I can get access to are the Windows and Transform patterns. Hence, I could potentially automate the resizing of the browser window and close it. But, I can't get the DOM or anything useful.
There are a few articles out there about using Interop with MSHTML or SHDocVw, but nothing super helpful.
I would appreciate any guidance anyone can provide on using whatever tools possible for a .NET C# Windows Forms or Console application to use to somehow connect to an independently opened browser window on the same Windows machine and automating it.
I've been using WatiN succesfully for this. A console app with Program.cs that looks like the following works for me:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using WatiN.Core;
namespace WatinTest
{
class Program
{
[STAThread]
static void Main(string[] args)
{
var ie = IE.AttachTo<IE>(Find.ByTitle(new Regex(".*")));
foreach (var div in ie.Divs)
{
Console.WriteLine(div.IdOrName);
}
Console.ReadLine();
}
}
}
This is with Windows 10 and WatiN 2.1.0.

Facebook API in a console application

I am new to using Facebook Api and I am using it in visual studio C# , and I downloaded it's library facebook. But I want to know how to start work on it ? Should I use Windows form for it or Console is fine ? Because I just want to Update my status through Api , getting my friend list , read my statuses .
As I run this code before but It didn't show me the output
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Facebook;
namespace Social_network_work
{
class Program
{
static void Main(string[] args)
{
var client = new FacebookClient();
dynamic me = client.Get("totten");
}
}
}
as I am python user but now I have to use visual studio c#. "http://csharpsdk.org/" this link is not showing how to use it in windows 7
Your question doesn't have much to do with Windows 7.
You sample works fine. You just don't have any line writting to the console.
Try :
var client = new FacebookClient();
var me = client.Get("totten");
Console.WriteLine(me);
To keep the command-line open so you can read the output, add the following after
the Console.Writeline line
Console.Readline();
Then when you run it, the output will display, and wait for you to press enter - which will allows the program to continue and exit/quit.
Also, in short, yes you should be able to create the app as a complete command-line application without issue.

C#: GUI to display realtime messages from Windows Service

I've written a C# windows service which can write messages to a custom EventLog or to any number of files. These messages are all marked with some priority (so, for example, only ERRORs and WARNINGs get stored in the EventLog, but if desired a lot more can be stored to a file).
What I'd like to do now is create a GUI that can listen for these messages and display them in real-time. Allowing a user to watch the current messages (at whatever their desired priority level), without the need to store everything to a file. I assume this is a separate program with some form of hook into the service, but I'm unsure of where to start.
This is my first real windows service, so I seem to be missing some keywords for finding out how to do this... Are there any code samples, tutorials, references, etc. for how to do something like this?
UPDATE
A lot of helpful answers, I love it when there's many ways to solve a problem! I think I'm going to implement a self-hosting WCF based solution. I'm still very light on the details as I'm trying to learn about WCF (I believe it will prove quite useful for me in other projects)... but thus far, I've found the videos here to be the most helpful as an intro how-to.
What you can do is have the windows service have way of registering for an event (you can do this through using Windows Communication Foundation). When your error comes up, it fires that event, and your winforms app will be notified. It's called a duplex contract:
http://social.msdn.microsoft.com/Forums/en-US/wcf/thread/0eb69998-0388-4731-913e-fb205528d374/
http://msdn.microsoft.com/en-us/library/ms731184.aspx
Actually the really cool thing is that you can have multiple applications listening this way too. So you can display it on screen, and have another application log it etc. without the two external apps knowing anything about each other.
I know this has already been mentioned, but use Windows Communication Foundation (WCF). Specifically, use the Publish-Subscribe Framework developed by Juval Lowy, author of Programming WCF Services. The details are described in this excellent MSDN article, and the source code is available for free at Lowy's website.
The neat thing about this framework is that it decouples the publisher, e.g., your Windows service, from any subscribers, e.g., your GUI. The publisher "publishes" events that are of interest to the Pub/Sub Service, which is always available. From the publisher's point of view, it doesn't matter if there are any subscribers or not. The Pub/Sub Service takes care of routing events to any and all registered subscribers. In this way, your Windows service publishes events as they occur, your GUI will subscribe/unsubscribe to the Pub/Sub Service when it loads/exits, and the Pub/Sub Service will notify your GUI as events occur.
I have used this setup in my project, and it works extremely well.
I've actually used the BitFactory Logger that has a socket logger that you can use for this purpose.
What you're describing is inter-process communication, which can get messy.
The easiest and most elegant, but probably least reactive, is to have the service write entries as small text files (or append to a log), and have your GUI use a FileSystemWatcher to detect new files or updates to the log file, and read the file. You have to ensure that the service opens the file for appending in a "shared" manner, allowing read-only access while it's writing. Otherwise, you'll block one process or the other, probably causing lost messages.
Processes can communicate through some built-in pipelines. if your service writes messages to its StandardOutput pipe, the GUI can remotely attach a listener and receive events when messages are written. This is probably the most elegant non-file way to do what you want. Research the Process class, especially the OutputDataReceived event. You'll have to go look for the process from your GUI by some uniquely identifying information, using GetProcess().
You need to look for "synchronization" and "inter-process communication". In your case the service would use the global event or semaphore to signal presence of data, and GUI process would check event/semaphore state and read the updates from event log or from file.
There exist more complicated scenarios, but the above is a good starting point.
Observer pattern!
Perhaps a delegate for all observable models that you can hook into with your service?
.NET remoting over IPC channel.
I've found that a Named Pipe communication with a System Tray application was the simplest way to display notifications from a Windows Service. This is because in Windows 10 services run with different permissions than the logged in user, so the notification app needs to perform IPC with the service.
Here you could put this into the server:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleServerApp
{
class Program
{
static void Main(string[] args)
{
StartServer();
Task.Delay(1000).Wait();
}
static void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
StreamWriter writer = new StreamWriter(server);
while (true)
{
var line = reader.ReadLine();
writer.WriteLine(String.Join("", line.Reverse()));
writer.Flush();
}
});
}
}
}
Then put this into your client:
using System;
using System.IO;
using System.IO.Pipes;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleClientApp
{
class Program
{
static void Main(string[] args)
{
//Client
var client = new NamedPipeClientStream("PipesOfPiece");
client.Connect();
StreamReader reader = new StreamReader(client);
StreamWriter writer = new StreamWriter(client);
while (true)
{
string input = Console.ReadLine();
if (String.IsNullOrEmpty(input)) break;
writer.WriteLine(input);
writer.Flush();
Console.WriteLine(reader.ReadLine());
}
}
}
}
Then change your ConsoleServerApp to a Winforms application so that it can display the notification whenever the windows service sends it a message:
public Form1()
{
InitializeComponent();
StartServer();
Task.Delay(_threadJoinTimeout).Wait();
}
public void DisplayMessage()
{
this.notifyIcon1.BalloonTipIcon = ToolTipIcon.Info;
this.notifyIcon1.BalloonTipText = "Welcomd!";
this.notifyIcon1.BalloonTipTitle = "Title";
this.notifyIcon1.ShowBalloonTip(2000);
}
void StartServer()
{
Task.Factory.StartNew(() =>
{
var server = new NamedPipeServerStream("PipesOfPiece");
server.WaitForConnection();
StreamReader reader = new StreamReader(server);
while (true)
{
var line = reader.ReadLine();
DisplayMessage();
}
});
}
Then put the ConsoleClientApp into your Windows Service.
For details on the pipe please see Example of Named Pipes
For the System Tray application please see http://www.tutorialspanel.com/create-system-tray-icon-windows-forms-application-using-c-vb-net/#:~:text=Below%20is%20an%20example%20of%20how%20to%20create,Step%203.%20Add%20an%20icon%20to%20the%20NotifyIcon
Here are tips on using the TopShelf NuGet package which allows you to debug your Windows Service as a Console Application: https://www.codeproject.com/Articles/881511/SignalR-with-Self-hosted-Windows-Service

Open the Word Application from a button on a web page

I'm developing a proof of concept web application: A web page with a button that opens the Word Application installed on the user's PC.
I'm stuck with a C# project in Visual Studio 2008 Express (Windows XP client, LAMP server). I've followed the Writing an ActiveX Control in .NET tutorial and after some tuning it worked fine. Then I added my button for opening Word.
The problem is that I can reference the Microsoft.Office.Interop.Word from the project, but I'm not able to access it from the web page. The error says "That assembly does not allow partially trusted callers".
I've read a lot about security in .NET, but I'm totally lost now. Disclaimer: I'm into .NET since 4 days ago.
I've tried to work around this issue but I cannot see the light!!
I don't even know if it will ever be possible!
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Data;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Word = Microsoft.Office.Interop.Word;
using System.IO;
using System.Security.Permissions;
using System.Security;
[assembly: AllowPartiallyTrustedCallers]
namespace OfficeAutomation
{
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void openWord_Click(object sender, EventArgs e)
{
try
{
Word.Application Word_App = null;
Word_App = new Word.Application();
Word_App.Visible = true;
}
catch (Exception exc)
{
MessageBox.Show("Can't open Word application (" + exc.ToString() + ")");
}
}
}
}
Using .Net Framework 4 + XBAP makes this easy: You could use WPF XBAP instead of ActiveX.
And on Project settings window do:
Signing: unckeck all boxes. (this project does not need to be signed),
under Security tab, Just change it to Full Trust.
The user will be prompted one time if he wants to allow the application to Run.
The post How to provide extra trust for an Internet Explorer hosted assembly in the .NET Security Blog sheds light on the issue. It's dated 2003 so things could have changed now... I don't know.
But a commenter asked (2006)
Is it possible to execute the .net
assembly with all the trust permission
without changing anything on the
client side? We previously have been
using a signed ActiveX in a CAB that
was working fine, and try to port it
to C#.
And Shawnfa answered
No, it is not currently possible to
elevate your permissions on the client
side for a control. The closest
option is ClickOnce which will allow
you to prompt and elevate an
application -- although this
application will not be hosed in the
web page.

System.Net's Webclient in C# won't connect to server

Is there something I need to do to get System.Net working with Microsoft Visual C# 2008 Express Edition? I can't seem to get any web type controls or classes to work at all.. the below WebClient example always throws the exception "Unable to connect to the remote server".. and consequently I can't get the WebBrowser control to load a page either.
Here is the code (Edited):
using System;
using System.Text;
using System.Windows.Forms;
using System.IO;
using System.Net;
namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
using (WebClient client = new WebClient()) {
string s = client.DownloadString("http://www.google.com");
this.textBox1.Text = s;
}
}
}
}
This is in a simple form with only a textbox control (with multiline set to true) in it. The exception gets thrown on the DownloadString(...) line. I also tried using WebRequest.. same exception!
EDIT:
I am connected to a Linksys WRT54G Router that connects directly to my cable modem. I am not behind a proxy server, although I did run proxycfg -u and I got:
Updated proxy settings
Current WinHTTP proxy settings under:
HKEY_LOCAL_MACHINE\
SOFTWARE\Microsoft\Windows\CurrentVersion\Internet Settings\Connections\
WinHttpSettings :
Direct access (no proxy server).
I am using Windows XP and not running any kind of firewall. Only AVG at the moment. I'm pretty sure I shouldn't have to forward any ports or anything, but I did try forwarding port 80 to my workstation on my router. Didn't help.
(update - I meant proxycfg, not httpcfg; proxycfg -u will do the import)
First, there is nothing special about "express" here. Second, contoso is a dummy url.
What OS are you on? And do you go through a proxy server? If so, you might need to configure the OS's http stack - proxycfg will do the job on XP, and can be used to import the user's IE settings.
The sample is fine, although it doesn't correctly handle the multiple IDisposable objects - the following is much simpler:
using (WebClient client = new WebClient()) {
string s = client.DownloadString("http://www.google.com");
// do something with s
}
Do you have any firewall software on your PC that might be affecting it? Have you tried with any sites other than Google?

Categories