I'm writing an IE extension using mshtml. Is there a way to get the text from the recent alert displayed to the user (via C# or javascript)?
Thanks in advance.
If you can hijack/inject/exec any JS in your websites, you could just overwrite the alert method with a custom one, which calls the original one inside :) Something like this:
// let's save the alert first
var _super_original_alert = window.alert;
// and now we overwrite it
window.alert = function(s){
// do something with the received string
// i will just log it, but you might want to send the string via
// ajax/jsonp to a remote server
console.log(s)
// call the original intended alert
_super_original_alert(s)
}
It's not nice, but could do the trick.
Related
I am coming back to work on a BOT that scraped data from a site once a day for my personal use.
However they have changed the code during COVID and now it seems they are loading in a lot of the content with Ajax/JavaScript.
I thought that if I did a WebRequest and obtained the response HTML from a URL, it should match the same content that I see in a browser (FF/Chrome) when I right click and "view source". I thought the actual DOM and generated source code would come later when those files were loaded as onload events fired, scripts lazily loaded and so on.
However the source HTML I obtain with my BOT is NOT the same as the HTML I see when viewing the source code. So my regular expressions that find certain links are not available to me.
Why am I seeing a difference between "view source" and a download of the HTML?
I can only think that when the page loads, SCRIPTS run that load other content into the page and that when I view source I am actually seeing a partial generated source rather than the original source code. Therefore is there a way I can call the page with my BOT, wait X seconds before obtaining the response to get this "onload" generated HTML?
Or even better a way for MY BOT (not using someone elses), to view generated source.
This BOT runs as a web service. I can find another site to scrape but it's just painful when I have all the regular expressions working on the source I see, except it's NOT the source my BOT obtains.
A bit confused at why my browser is showing me more content with a view source (not generated source), than my BOT gets when making a valid request.
Any help would be much appreciated this is almost an 8 year project that I have been doing on/off and this change has ruined one of the core parts of the system.
In response to OP's comment, here is the Java code for how to click at different parts on the screen to do this:
You could use Java's Robot class. I just learned about it a few days ago:
// Import
import java.awt.Robot;
// Code
void click(int x, int y, int btn) {
Robot robot = new Robot();
robot.mouseMove(x, y);
robot.mousePress(btn);
robot.mouseRelease(btn);
}
You would then run the click function with the x and y position to click, as well as the button (MouseEvent.BUTTON1, MouseEvent.BUTTON2, etc.)
After stringing together the right positions (this will vary depending on the screen) you could do just about anything.
To use shortcuts, just use the keyPress and keyRelease functions. Here is a good way to do this:
void key(int keyCode, boolean ctrl, boolean alt, boolean shift) {
if (ctrl)
robot.keyPress(KeyEvent.VK_CONTROL);
if (alt)
robot.keyPress(KeyEvent.VK_ALT);
if (shift)
robot.keyPress(KeyEvent.VK_SHIFT);
robot.keyPress(keyCode);
robot.keyRelease(keyCode);
if (ctrl)
robot.keyRelease(KeyEvent.VK_CONTROL);
if (alt)
robot.keyRelease(KeyEvent.VK_ALT);
if (shift)
robot.keyRelease(KeyEvent.VK_SHIFT);
}
Thus, something like Ctrl+Shift+I to open the inspect menu would look like this:
key(KeyEvent.VK_I, true, false, true);
Here are the steps to copy a website's code (from the inspector) with Google Chrome:
Ctrl + Shift + I
Right click the HTML tag
Select "Edit as HTML"
Ctrl + A
Ctrl + C
Then, you can use the technique from this StackOverflow to get the content from the clipboard:
Clipboard c = Toolkit.getDefaultToolkit().getSystemClipboard();
String text = (String) c.getData(DataFlavor.stringFlavor);
Using something like FileOutputStream to put the info into a file:
FileOutputStream output = new FileOutputStream(new File( PATH HERE ));
output.write(text.getBytes());
output.close();
I hope this helps!
I have seemed to have fixed it by just turning on the ability to store cookies in my custom HTTP (Bot/Scraper) class, that was being called from the class trying to obtain the data. Probably the site has a defense system to prevent visitors requesting pages and not the JS/CSS with a different session ID on each request.
However I would like to see some other examples because if it is just cookies then they could use JavaScript to test for JavaScript e.g an AJAX call to log if JS is actually on or some DOM manipulation to determine if you are really Human or not which would break it again.
Every site uses different methods to prevent scrapers, email harvesters, job rapists, link harvesters etc inc working out the standard time between requests for 100% verifiable humans and BOTS and then using those values to help determine spoofed user-agents etc. I wrote a whole system to stop BOTS at my last place of work and its a layered approach, just glad the cookies being enabled solved it on this site but it could easily be beefed up with other tricks to test for BOTS vs HUMANS.
I do know some Java, enough to work out what is going on anyway. My BOT is in C#.
I have the following line of code to open a web page modal dialog in C# (Silverlight):
var so = (ScriptObject)HtmlPage.Window.Invoke(
"showModalDialog",
modalWindowUrl,
dialogArgs,
"dialogWidth:600px;dialogHeight:600px;");
Now, code similar to the following is being called on the page I am displaying, and I need to make sure it gets the values I'm trying to pass in (this is a MSCRM web page I don't have control over):
dialogArgs.items <-- will be an array I pass in
dialogArgs.items[i].getAttribute("oid") <-- will return something
dialogArgs.items[i].getAttribute("otype") <-- will return something
dialogArgs.items[i].values <-- will return something
What I have tried to send in (from my C# code) is this:
dialogArgs = #"{items:[{oid:" + id + ",otype:" + type + "}]}";
which will result in a JSON string... but I'm guessing this just ends up as a string within the JavaScript and not a JSON object.
Any ideas how I get this to work?
A few side notes:
I can't get IE to debug the modal dialog that results from this call. I can get the debugging tools displaying, but it won't attach to the page because it cannot refresh it.
I don't have control over this modal dialog. It's a page that is displayed using MS Dynamics CRM. For that reason I cannot mess with the JavaScript or anything to test stuff.
Looks like I won the tumbleweed award for this one! Can't believe how uncommon this scenario seems to be. The solution ended up being quite simple, but not very documented so took me a while to track down. Thought I would share here.
Firstly, a quick search across the internet reveals that we can set this up using the following:
var dialogArgs = HtmlPage.Window.CreateInstance("Object");
Which gives you a ScriptObject back. For properties:
dialogArgs.SetProperty("items", items);
Some code for setting up an array and an item should look something like this (I have just created a new GUID for the purpose of this example):
var item = HtmlPage.Window.CreateInstance("Object");
item.SetProperty("oid", Guid.NewGuid());
item.SetProperty("otype", "account");
var items = HtmlPage.Window.CreateInstance("Object");
items.SetProperty(0, item);
And finally, just pass that object straight into your dialog window like this:
var so = (ScriptObject)HtmlPage.Window.Invoke("showModalDialog", lookUpWindow, dialogArgs, "dialogWidth:600px;dialogHeight:600px;");
I am trying to get user confirmation from c# code behind file, to confirm if user wants to overwrite the existing file on server of cancel the operation but so far no luck.
this is my code :
if (File.Exists(filePath))
{
string alertMsg = #"confirm('A File already exists with the same name. \n Would you like to overwrite the existing file ?');";
ScriptManager.RegisterStartupScript(this, this.GetType(), "Test", alertMsg, true);
}
else
{
fuPSD.SaveAs(filePath);
}
any help would be highly appreciated.
That code will pop up the message if the file exists and save it if it doesn't.
But you will need to take some action on the confirm dialog result on the client side and either trigger a postback or some other server call to perform the operation in the case of the override.
The problem is that your JavaScript registration will ask the user to confirm to overwrite the file after the next page loads. This then poses the issue of telling whether the user confirmed or denied from the server since you're confirm with be client side.
In the past I've used a hidden field to toggle true/false to show a popup from the server side. This gives me the ability to wire up the events to a delegate on the code behind(I.e make my own confirm box with my own buttons). You can still do this without it by I found that it leads to a lot of messy and hard to follow script like callin __doPostback manually.
something like this :
create
<asp:hiddenField id="hf" />* in the aspx file
also put on the JS location a Declaration :
var answer=null;
back to server :
string alertMsg = #"if (confirm('A File already exists with the same name. \n Would you like to overwrite the existing file ?')==true) answer='1'; else answer='0';";
now on the server side :
read :
hf.value
I am trying to keep track of prints that are made for a page. The page has Print this page link. And the code for it is like below: This is written in .cs file as there are many conditions for displaying this. And i am appending here using String Builder.
sbOutput.AppendFormat("<td align=\"right\" valign=\"bottom\"><div style =\"float:right;text-align:right; valign:bottom;width:200px\"class=\"print_button notPrinted\"><a class=\"notPrinted\" href=\"#\" onclick=\"window.print();\">PRINT THIS COUPON </a><img src=\"images/print-icon-34x34.gif\" class=\"notPrinted\" align=\"absmiddle\" /></div> </td></tr></table>", couponid, Userid, locationid);
Do i have to use onclientclick or something else??
Thanks so much in advance.
Good option would be to write a Javascript function to enable Ajax call, so that you can send a request to server to record the print coomand.
PRINT THIS COUPON
function RecordPrint()
{
// Make a AJAX Call to your server Page to record Print Command.
// printRecorded : success from server
If(printRecorded)
{
window.print();
}
return false;
}
Hope that helps.
since you seem to print on the client side only, you could do
PRINT THIS COUPON
On the server side, implement the counter.aspx page to just count the request and quit silently. Make sure, the window.print() will return true - otherwise the link is not executed.
We are developing an application which needs to interact with the active document in IE.
Context: The app is a C#, .Net 3.5 desktop app. The goal is to highlight specific text elements in the web page on user request. For this we need to retrieve and interpret web page elements (the need for the return value) then act on them through another JS call. The operations that must be made in the web page are not all done at the same time so we must get some kind of "snapshot" of the interesting text elements (we do this on the Mac version of our app by returning a string containing an XML representation of those elements).
In .Net we used IHTMLDocument2's execScript method successfully to run some JavaScript inside the active IE document, but we can't seem to find a way to get a return value from the call. Based on the doc execScript returns an execution success/failure constant which is not what we need.
In essence what we need to do is to load some JavaScript from a text file into a string, then send it to IE for execution. Then we need to get a string back from the called script.
Any hints on what objects to use? How to proceed to get this functionality?
Thanks in advance!
My colleague found the solution, based on what Alun Harford said:
string jsToRun = "function myTest() { return document.title; } myTest();";
mshtml.IHTMLDocument2 myIHTMLDocument2 = GetSelectedIEWindow();
IE ie = IE.AttachToIE(Find.ByUrl(myIHTMLDocument2.url));
string jsReturn = ie.Eval(jsToRun);
jsReturn then contains the string value returned from myTest() in JavaScript. Note that there is no return before the myTest() function call in the script!
Have a look at the WatiN codebase. In there, IE.Eval does exactly what you're looking for.
If you are providing the html and script yourself you can do the following:
execute the javascript function
let the js function place the result in an html element
wait till the function is done running
retrieve the html element using document.getElementById
and retrieve the value
I'm not sure if there's a easier way to do this.
Well it is nasty but it can be done.
Try this:
[Guid("626FC520-A41E-11CF-A731-00A0C9082637"), InterfaceType(ComInterfaceType.InterfaceIsDual)]
interface IHTMLDocument
{
void Script([Out, MarshalAs(UnmanagedType.Interface)] out object ppScript);
}
public object RunScript(InternetExplorer ie, string scriptText)
{
IHTMLDocument doc = (IHTMLDocument)ie.Document;
object scriptObj;
doc.Script(out scriptObj);
Type t = scriptObj.GetType();
return t.InvokeMember("eval", System.Reflection.BindingFlags.InvokeMethod, null, scriptObj, new object[] { scriptText });
}
That will return your value in the object (just cast to what ever type you expected). Of course .NET 4 makes this even easier ;)