I am developing a program which has an invisible web browser control that is used for loading data from certain web pages. However, I am having trouble blocking a certain type of popup.
This is the code I am currently using to block popups
private void webBrowser1_NewWindow( object sender,
System.ComponentModel.CancelEventArgs e)
{
e.Cancel = true;
}
I have tested it on http://www.popuptest.com/ and it fails to block the Come & Go test and the Modeless Window test. http://i75.servimg.com/u/f75/13/13/40/49/b11.png
Is there a way to block these popups?
This is the javascript which shows the popups
function modelesswin(url,mwidth,mheight){
if (document.all&&window.print) //if ie5
eval('window.showModelessDialog(url,"","help:0;resizable:1;dialogWidth:'+mwidth+'px;dialogHeight:'+mheight+'px")')
else
eval('window.open(url,"","width='+mwidth+'px,height='+mheight+'px,resizable=1,scrollbars=1")')
}
modelesswin("http://www.popuptest.com/popup1.html",600,600)
Try implementing WebBrowser Feature Control, particularly FEATURE_BLOCK_INPUT_PROMPTS and FEATURE_WEBOC_POPUPMANAGEMENT.
[EDITED] This code works for me with your test site, try it (tested with IE10). Make sure you set features before your WebBrowser gets created (before InitializeComponent below) and you do ScriptErrorsSuppressed = true to suppress script errors caused by blocked pop-ups.
using System;
using System.Runtime.InteropServices;
using System.Windows.Forms;
using System.Diagnostics;
using Microsoft.Win32;
namespace WinformsWB
{
public partial class Form1 : Form
{
public Form1()
{
SetBrowserFeatureControl();
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.webBrowser1.ScriptErrorsSuppressed = true;
this.webBrowser1.Navigate("http://www.popuptest.com/");
}
private void SetBrowserFeatureControlKey(string feature, string appName, uint value)
{
using (var key = Registry.CurrentUser.CreateSubKey(
String.Concat(#"Software\Microsoft\Internet Explorer\Main\FeatureControl\", feature),
RegistryKeyPermissionCheck.ReadWriteSubTree))
{
key.SetValue(appName, (UInt32)value, RegistryValueKind.DWord);
}
}
private void SetBrowserFeatureControl()
{
// http://msdn.microsoft.com/en-us/library/ee330720(v=vs.85).aspx
// FeatureControl settings are per-process
var fileName = System.IO.Path.GetFileName(Process.GetCurrentProcess().MainModule.FileName);
// make the control is not running inside Visual Studio Designer
if (String.Compare(fileName, "devenv.exe", true) == 0 || String.Compare(fileName, "XDesProc.exe", true) == 0)
return;
// TODO: FEATURE_BROWSER_MODE - what is it?
SetBrowserFeatureControlKey("FEATURE_BROWSER_EMULATION", fileName, 9000); // Webpages containing standards-based !DOCTYPE directives are displayed in IE10 Standards mode.
SetBrowserFeatureControlKey("FEATURE_DISABLE_NAVIGATION_SOUNDS", fileName, 1);
SetBrowserFeatureControlKey("FEATURE_WEBOC_POPUPMANAGEMENT", fileName, 1);
SetBrowserFeatureControlKey("FEATURE_BLOCK_INPUT_PROMPTS", fileName, 1);
}
}
}
Related
I am building a program in C# to be used in one of my course at a college to demonstrate how Asynchronous connections work using RS-232 and two computers connected together. My course is not about programming, but data networks, so the connectivity is what I am looking for.
picture 1 - sample layout of GUI using Visual Studio 2015
One of the features I want to implement in my program is to show how a Master-slave, simplex connection works (i.e. the program can choose between been a master to send input from the keyboard; or slave to only receive information and print it on a textbox).
What I have already is the capability of initializing the serial port with specific characteristics (baud rate, data bits, stop bits, etc). This features are selected using combo boxes from the GUI, and assigned to the port when the user clicks a button to "open the port".
What I don't know is how to create the "slave" part of the program. My idea of what I could do is, after you choose the program to be "slave", you open the port waiting for some sort of flag or event to trigger when the input buffer has data stored.
I've been reading several forums and I can't find anything similar to what I need. I have, however, tested multiple alternatives that I believed would bring me closer to what I need with little to no result. I come to ask for an idea of what I could be doing wrong, or suggestions on how to tackle this problem. The problematic lines are bolded (or 2 stars ( * ) ):
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.IO.Ports;
namespace SerialCommTester
{
public partial class frmSerialComm : Form
{
static SerialPort _PuertoSerial;
public frmSerialComm()
{
InitializeComponent();
getAvailablePorts();
}
//---------------------------------my functions--------------------------------------
void getAvailablePorts()
{
string[] ports = SerialPort.GetPortNames();
cmbPortList.Items.AddRange(ports);
}
void activatePort()
{
//Note that all the combo boxes are named somewhat accordingly to what the information they are meant to display.
if (cmbPortList.Text != "" && cmbBaudRate.Text != "" && cmbParity.Text != "" && cmbStopBits.Text != "")
{
_PuertoSerial.PortName = cmbPortList.Text;
_PuertoSerial.BaudRate = Convert.ToInt32(cmbBaudRate.Text);
_PuertoSerial.RtsEnable = true;
_PuertoSerial.DtrEnable = true;
_PuertoSerial.DataBits = Convert.ToInt32(cmbDataBits.Text);
if (cmbParity.Text == "Even") { _PuertoSerial.Parity = Parity.Even; }
else if (cmbParity.Text == "Odd") { _PuertoSerial.Parity = Parity.Odd; }
else if (cmbParity.Text == "Space") { _PuertoSerial.Parity = Parity.Space; }
else if (cmbParity.Text == "Mark") { _PuertoSerial.Parity = Parity.Mark; }
else { _PuertoSerial.Parity = Parity.None; }
if (cmbStopBits.Text =="2") { _PuertoSerial.StopBits = StopBits.Two; }
else if (cmbStopBits.Text == "1.5") { _PuertoSerial.StopBits = StopBits.OnePointFive; }
else { _PuertoSerial.StopBits = StopBits.One; }
if (cmbHandShake.Text == "Software Flow Control") { _PuertoSerial.Handshake = Handshake.XOnXOff; }
else if (cmbHandShake.Text == "Hardware Flow Control") { _PuertoSerial.Handshake = Handshake.RequestToSend; }
else { _PuertoSerial.Handshake = Handshake.None; }
_PuertoSerial.ReadTimeout = 500;
_PuertoSerial.WriteTimeout = 500;
_PuertoSerial.Open();
//in my understanding, this line of code is needed to handle data being received. Does it trigger a flag or something?
**_PuertoSerial.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);**
}
else
{
txtRecieve.Text = "Input selection missing 1 or more characteristics";
}
}
**
private static void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
SerialPort testing = (SerialPort)sender;
txtRecieve.AppendText(testing.ReadExisting()); //txtRecieve cannot be reached within this function. It indicates the following error: "An object reference is required for the non-static field, method, or property 'frmSerialComm.txtRecieve'
}
**
void enableDisableGUI(bool[] input)
{
grpConnection.Enabled = input[0];
grpCharacteristics.Enabled = input[1];
btnOpenPort.Enabled = input[2];
btnClosePort.Enabled = input[3];
txtSend.Enabled = ((cmbControlMasterSlave.Text == "Slave") ? false : true);
}
//----------------------------C# objects / functions--------------------------------------
private void btnOpenPort_Click(object sender, EventArgs e)
{
try
{
_PuertoSerial = new SerialPort();
activatePort();
}
catch(Exception ex)
{
MessageBox.Show(ex.Message, "Message ", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
bool[] format = { false, false, false, true};
enableDisableGUI(format);
}
private void btnClosePort_Click(object sender, EventArgs e)
{
_PuertoSerial.Close();
bool[] format = { true, true, true, false};
enableDisableGUI(format);
}
private void txtSend_KeyPress(object sender, KeyPressEventArgs e)
{
_PuertoSerial.Write(e.KeyChar.ToString()); //this is how I send data through the serial port.
}
private void btnClearTxts_Click(object sender, EventArgs e)
{
txtRecieve.Clear();
txtSend.Clear();
}
} //class closes
} //program closes
I am not an experienced programmer, I just want to create something useful for my students. Any constructive criticism will be highly appreciated.
I don't have any definitive answers for you. You code looks like it should provide what you need once you get past the two possible glitches.
I think you should attach your SerialDataReceivedEventHandler BEFORE
you call _PuertoSerial.Open().
It may have no effect since event handlers can normally be enabled/disabled dynamically, but I base the advice on the following comment taken from the .Net source code for SerialPort on MSDN.
// all the magic happens in the call to the instance's .Open() method.
// Internally, the SerialStream constructor opens the file handle, sets the device control block and associated Win32 structures, and begins the event-watching cycle.
The "object reference" error might be resolved by removing the
static modifier from your DataReceivedHandler. If not, or if that
static modifier is necessary for some reason, then perhaps the
txtRecieve control has a private modifier which needs to be changed
to internal or public. You should be able to use Visual Studio in
debug mode to step into the InitializeComponent() method and see
where txtRecieve is being instantiated.
Well, I believe that I needed to read more. This is how I solved the problem (if this is not the real solution, at least is working for now):
I moved the "SerialDataReceivedEventHandler" line before the _PuertoSerial.open();
I followed the suggestions from this article:
https://msdn.microsoft.com/query/dev14.query?appId=Dev14IDEF1&l=EN-US&k=k(EHInvalidOperation.WinForms.IllegalCrossThreadCall);k(TargetFrameworkMoniker-.NETFramework,Version%3Dv4.5.2);k(DevLang-csharp)&rd=true
So my funtions (one existings + a new one) look like this:
void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
printReceivedText(_PuertoSerial.ReadExisting());
}
private void printReceivedText(string text)
{
if (this.txtSend.InvokeRequired)
{
SetTextCallback d = new SetTextCallback(printReceivedText);
this.Invoke(d, new object[] { text });
}
else
{
this.txtRecieve.AppendText(text);
_PuertoSerial.DiscardInBuffer();
}
}
For now seems to be working fine. The final testing will come when I connect another terminal and see the program interacting with each other.
I have an requirement if the user open any office document from his/her hard drive it's should open an an exe(win form application) as a modal window to capture details about the document.
For that I have developed an console app which runs under the client machine, to monitor if any office document file is opening or not. Please find the below code
static void Main(string[] args)
{
var UIAEventHandler = new AutomationEventHandler(OnUIAEvent);
Automation.AddAutomationEventHandler(WindowPattern.WindowOpenedEvent,
AutomationElement.RootElement,
TreeScope.Children, UIAEventHandler);
Console.ReadLine();
Automation.RemoveAllEventHandlers();
}
public static void OnUIAEvent(object src, AutomationEventArgs args)
{
AutomationElement element;
try
{
element = src as AutomationElement;
}
catch
{
return;
}
string name = "";
if (element == null)
name = "null";
else
{
name = element.GetCurrentPropertyValue(
AutomationElement.NameProperty) as string;
}
if (name.Length == 0) name = "< NoName >";
string guid = Guid.NewGuid().ToString("N");
string str = string.Format("{0} : {1}", name, args.EventId.Id);
if ((element.Current.ClassName.Equals("XLMAIN", StringComparison.InvariantCultureIgnoreCase) == true && name.Contains(".xlsx")) || (element.Current.ClassName.Equals("OpusApp", StringComparison.InvariantCultureIgnoreCase) == true && name.Contains(".docx")))
{
Process.Start(#"E:\experiment\TestingWindowsService\UserInfomation\bin\Debug\UserInfomation.exe", element.Current.Name);
//Automation.AddAutomationEventHandler(
// WindowPattern.WindowClosedEvent,
// element, TreeScope.Element, (s, e) => UIAEventHandler1(s, e, guid, name));
Console.WriteLine(guid + " : " + name);
// Environment.Exit(1234);
}
}
if you see in the OnUIAEvent event handler I am using Process.Start to open an exe.It's working as expected. But I want the exe should open as modal to the opened document.The below code is the form load of the exe.
private void Form1_Load(object sender, EventArgs e)
{
this.TopMost = true;
this.CenterToScreen();
}
Is it possible to open the windows application to open as modal to the opened document?
Unless the external application has been coded taken into account your requirement, it will be difficult.
If you have access to the code (which you seem to have), you can include the Form in your console application (see here how to run a winform from console application?).
The easiest option is to start a windows forms project, then change
the output-type to Console Application. Alternatively, just add a
reference to System.Windows.Forms.dll, and start coding:
using System.Windows.Forms;
[STAThread] static void Main() {
Application.EnableVisualStyles();
Application.Run(new Form()); // or whatever
}
The important bit is the [STAThread] on your Main() method, required for full COM support.
You can override the Creator, and add parameters matching the document, or whatever you need to log/monitor.
I've searched up and down the internet throughout the day, and I'm just stumped.
What I want to do is play a youtube video inside of C# using the youtube API. Then I want a function on the form to be called when the video finishes playing. Unfortunately, I can't seem to find a way to get the events to fire.
(Using Visual C# 2010 Express, and have IE9. For reference.)
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
using System.Runtime.InteropServices;
public partial class Form1 : Form
{
// This nested class must be ComVisible for the JavaScript to be able to call it.
[ComVisible(true)]
public class ScriptManager
{
// Variable to store the form of type Form1.
private Form1 mForm;
// Constructor.
public ScriptManager(Form1 form)
{
// Save the form so it can be referenced later.
mForm = form;
}
// This method can be called from JavaScript.
public void MethodToCallFromScript()
{
// Call a method on the form.
mForm.GoToNext();
}
}
public Form1()
{
InitializeComponent();
}
public void GoToNext()
{
MessageBox.Show("Play the next song");
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.Navigate("http://localhost/index.html");
}
}
}
That is my Form1.cs code. Form1.cs [Design] consists of nothing more than a webBrowser control.
I've tried numerous things to get this to work, from installing an http server to run the html 'live' to running it from a file directly off my computer, to setting the document text with the code as a string. All has failed me thus far. In IE9 if I open the index.html file locally (as a file and not through my webserver) the events do not fire. If I run it live off my webserver the events do fire. However in C# webBrowser control, these events do not seem to fire at all, no matter where it's run from.
<!DOCTYPE html>
<html>
<body>
<div id="player"></div>
<script>
var tag = document.createElement('script');
tag.src = "http://www.youtube.com/player_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var player;
function onYouTubePlayerAPIReady() {
player = new YT.Player('player', {
height: '390',
width: '640',
playerVars: { 'autoplay': 1, 'controls': 1,'autohide':1,'wmode':'opaque' },
videoId: 'G4cRrOcDXXY',
events: {
'onReady': onPlayerReady,
'onStateChange': onPlayerStateChange
}
});
}
function onPlayerReady(event) {
event.target.mute();
}
function onPlayerStateChange(event) {
if(event.data === 0) {
alert('done');
window.external.MethodToCallFromScript();
}
}
</script>
</body>
</html>
I'm out of ideas, so any help would be greatly appreciated. I'd love to get events to fire in the C# WebBrowser control.
Wow. I was in the process of typing out my newest problem when I attempted something else with great success. The problem was that I'd navigate to my .html file on my webserver, and it'd begin playing a video, when the video finished, I'd have javascript tell C# to navigate to the same URL with a different youtube ID (to play another video). The second video would fail to fire the events.
I've overcome this by using different javascript, such as what was mentioned here.
I did start using Visual Studio 2013 Express, and IE11. That cleared up quite a few problems I was bumping into on it's own. I'll provide you guys with my current code, just in case anyone ever runs into the issues I've been dealing with.
My form:
using System;
using System.Windows.Forms;
using System.Data.SQLite;
namespace WindowsFormsApplication1
{
using System.Runtime.InteropServices;
public partial class Form1 : Form
{
// This nested class must be ComVisible for the JavaScript to be able to call it.
[ComVisible(true)]
public class ScriptManager
{
// Variable to store the form of type Form1.
private Form1 mForm;
// Constructor.
public ScriptManager(Form1 form)
{
// Save the form so it can be referenced later.
mForm = form;
}
public void AnotherMethod(string message)
{
mForm.GoToNext();
}
}
public Form1()
{
InitializeComponent();
}
public void GoToNext()
{
timer1.Interval = 2000;
timer1.Enabled = true;
}
public object MyInvokeScript(string name, params object[] args)
{
return webBrowser1.Document.InvokeScript(name, args);
}
public void SongCheck()
{
// Disable timer. Enable it later if there isn't a song to play.
if (timer1.Enabled)
timer1.Enabled = false;
// Connect to my SQLite db,
SQLiteConnection mySQLite = new SQLiteConnection("Data Source=ytsongrequest.s3db;Version=3;");
mySQLite.Open();
// The SQLite DB consists of three columns. id, youtubeid, requestor
// the 'id' auto increments when a row is added into the database.
string sqlCommand = "select * from songs order by id asc limit 1";
SQLiteCommand x = new SQLiteCommand(sqlCommand, mySQLite);
SQLiteDataReader reader = x.ExecuteReader();
if (reader.HasRows) {
while (reader.Read())
{
// Use our custom object to call a javascript function on our webpage.
object o = MyInvokeScript("createPlayerAndPlayVideo", reader["youtubeid"]);
label2.Text = reader["requestor"].ToString();
// Since we've played the song, we can now remove it.
x = new SQLiteCommand("delete from songs where id = " + reader["id"], mySQLite);
x.ExecuteNonQuery();
}
mySQLite.Close();
}
else
{
// Set a timer to check for a new song every 10 seconds.
timer1.Interval = 10000;
timer1.Enabled = true;
}
}
private void Form1_Load(object sender, EventArgs e)
{
webBrowser1.ObjectForScripting = new ScriptManager(this);
webBrowser1.Navigate("http://localhost/testing.html");
GoToNext();
}
private void timer1_Tick(object sender, EventArgs e)
{
SongCheck();
}
}
}
My HTML page that I have on my server:
<!DOCTYPE html>
<html>
<body>
<div id="player"></div>
<script>
var tag = document.createElement('script');
tag.src = "https://www.youtube.com/iframe_api";
var firstScriptTag = document.getElementsByTagName('script')[0];
firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);
var query = getQueryParams(document.location.search);
var player;
var playerAPIReady;
function onYouTubePlayerAPIReady() {
playerAPIReady = true;
}
function onPlayerReady() {
player.playVideo();
player.addEventListener('onStateChange', function(e) {
if (e.data === 0) {
window.external.AnotherMethod('Finished video');
}
});
}
function getQueryParams(qs) {
qs = qs.split("+").join(" ");
var params = {}, tokens,
re = /[?&]?([^=]+)=([^&]*)/g;
while (tokens = re.exec(qs)) {
params[decodeURIComponent(tokens[1])]
= decodeURIComponent(tokens[2]);
}
return params;
}
function createPlayerAndPlayVideo(id) {
if(! playerAPIReady) {
// player API file not loaded
return;
}
if (! player) {
player = new YT.Player('player', {
height: '390',
width: '640',
videoId: id,
events: {
'onReady': onPlayerReady
}
});
}
else {
player.loadVideoById(id);
}
}
</script>
</body>
</html>
I am attempting to access the HTML of a page after it has been modified by the JavaScripts on the page. This is what I have been currently attempting based on what I have found online.
using System;
using System.Windows.Forms;
using System.IO;
namespace WebBrowserDemo
{
class Program
{
public const string TestUrl = #"http://www.theverge.com/2012/7/2/3126604/android-jelly-bean-updates-htc-samsung-google-pdk";
[STAThread]
static void Main(string[] args)
{
WebBrowser wb = new WebBrowser();
wb.DocumentCompleted += new WebBrowserDocumentCompletedEventHandler(wb_DocumentCompleted);
wb.Navigate(TestUrl);
while (wb.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
Console.WriteLine("\nPress any key to continue...");
Console.ReadKey(true);
}
static void wb_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
WebBrowser wb = (WebBrowser)sender;
HtmlElement document = wb.Document.GetElementsByTagName("html")[0];
using (StreamWriter sw = new StreamWriter("OuterHTML.txt"))
{
sw.WriteLine(document.OuterHtml);
}
var abc = wb.Document.InvokeScript("eval", new object[] { "window.scrollTo(0, document.body.scrollHeight);" });
Console.WriteLine();
document = wb.Document.GetElementsByTagName("html")[0];
using (StreamWriter sw = new StreamWriter("OuterHTML2.txt"))
{
sw.WriteLine(document.OuterHtml);
}
}
}
}
The ultimate goal is to scroll to the bottom of the page activating any JS to load the comments on the article. Though currently the html I get back from before and after the script is ran is the same.
Any Suggestions?
Thanks
You should do it with a WebBrowser control.
This is basically a componentized version of IE. Load the page into the control. You probably do not even need to display the page. You can register an event handler that will be called when the page is fully loaded. There is no definite way to determine when the scripts have "completed" - scripts are open-ended and may run as long as they like. So you'd have to build in a heuristic "Wait period", then examine the HTML after that wait period passes.
Incidentally this is exactly what IECapt does.
Whenever I call folderbrowserdialog.showDialog() my application crashes.
I'm using the code that worked before for me, so it CAN NOT be the code.
try
{
FolderBrowserDialog fbd = new FolderBrowserDialog();
fbd.RootFolder = Environment.SpecialFolder.Desktop;
if (fbd.ShowDialog() == DialogResult.OK)
{
// this.Minecraft.Text = fbd.SelectedPath;
}
}
catch
{
}
It does not throw any error, no exception, there just pops up the little loading circle, then the app is gone, I noticed it with a different .NET app before too!
btw: will reinstalling .net 4 work?
Try adding this to your application (at the start of the Main() method, preferably). See if the exceptions.txt file has any exceptions logged into it when you reach your freezing point.
AppDomain.CurrentDomain.FirstChanceException += (sender, e) =>
{
if ((e == null) || (e.Exception == null))
{
return;
}
using (var sw = File.AppendText(#".\exceptions.txt"))
{
sw.WriteLine(e.ExceptionObject);
}
};
AppDomain.CurrentDomain.UnhandledException += (sender, e) =>
{
if ((e == null) || (e.ExceptionObject == null))
{
return;
}
using (var sw = File.AppendText(#".\exceptions.txt"))
{
sw.WriteLine(e.ExceptionObject);
}
};
I had just the same problem with FolderBrowserDialog and found the source of evilness. Comment / uncomment [STAThread] and see the difference:
using System;
using System.Windows.Forms;
namespace WindowsFormsApplication1
{
static class Program
{
//[STAThread]
static void Main()
{
new FolderBrowserDialog().ShowDialog();
}
}
}
Another thing that you should know about FolderBrowserDialog, SaveFileDialog, OpenFileDialog is that they don't work if you "Disable visual themes" on the compatibility tab from the executable file properties.
Hope this helps somebody - i actually had this problem, and turns out I had accidentally assigned a DialogResult to the button that was launching by FolderBrowserDialog! Therefore, whenever the code was finished executing, it was returning the DialogResult of 'Cancel' to the CLR and terminating my program. Check the 'DialogResult' property in Visual Studio for the button you have assigned to open the dialog - make sure it is set to None.