Author |
Message |
|
Newbie
Bandwidth Hog
Joined: 23 Jan 2004 Posts: 2247
|
Posted: 10 May 2008 03:19:04 pm Post subject: |
|
|
Does anyone know how I might use Visual Basic or C#.Net to automate the process of filling out a form on a website and then submitting it? |
|
Back to top |
|
|
Weregoose Authentic INTJ
Super Elite (Last Title)
Joined: 25 Nov 2004 Posts: 3976
|
Posted: 10 May 2008 03:49:24 pm Post subject: |
|
|
The Autofill Forms extension for Firefox will allow you to customize what fields to fill out automatically, along with a surplus of other options (see screenshot). About submitting automatically, I dunno. A keyboard/mouse macro would do the work just fine – I used one to upload hundreds of files to the TI|BD.
Last edited by Guest on 10 May 2008 03:51:29 pm; edited 1 time in total |
|
Back to top |
|
|
magicdanw pcGuru()
Calc Guru
Joined: 14 Feb 2007 Posts: 1110
|
Posted: 10 May 2008 04:05:05 pm Post subject: |
|
|
Take a look at this page for information about using the VB SendKeys function to send keypresses to another application. |
|
Back to top |
|
|
benryves
Active Member
Joined: 23 Feb 2006 Posts: 564
|
Posted: 10 May 2008 07:18:24 pm Post subject: |
|
|
A rather less Heath Robinson approach would be to use the WebRequest class.
Here's a quick-and-dirty demo that sends a POST request to rot13.com.
Code: using System.IO;
using System.Net;
using System.Text;
namespace PostWebRequestDemo {
class Program {
static void Main(string[] args) {
// Create a WebRequest instance to perform the query.
var Request = WebRequest.Create("http://www.rot13.com/");
Request.Method = "POST";
Request.ContentType = "application/x-www-form-urlencoded";
// Here's the parameter (just the one).
var RequestParams = "text=P+funec+naq+.ARG+ner+pbby,+ab?";
Request.ContentLength = RequestParams.Length;
// Write our request.
using (var RequestStreamWriter = new StreamWriter(Request.GetRequestStream(), Encoding.Default)) {
RequestStreamWriter.Write(RequestParams);
}
// Execute/Read the response.
string Response = "";
using (var ResponseReader = new StreamReader(Request.GetResponse().GetResponseStream())) {
Response = ResponseReader.ReadToEnd();
}
}
}
} Another option might be to use the DOM methods exposed by the WebBrowser control.
Last edited by Guest on 10 May 2008 07:19:46 pm; edited 1 time in total |
|
Back to top |
|
|
Newbie
Bandwidth Hog
Joined: 23 Jan 2004 Posts: 2247
|
Posted: 10 May 2008 07:35:29 pm Post subject: |
|
|
Thanks a lot for your help. I'm going to try benryves solution first and see what happens. I'll get back to you on how it went.
Edit:
benryves, your solution worked great, well after adding
Console.WriteLine(Response);
Console.ReadLine();
so I could read the results. LOL
Your solution uses one field. How do I go about a form that has multiple fields, by knowing which field to write to?
Sorry, I'm not real familiar with the console part of C#, I normally deal with a form.
Last edited by Guest on 10 May 2008 07:59:10 pm; edited 1 time in total |
|
Back to top |
|
|
calc84maniac
Elite
Joined: 22 Jan 2007 Posts: 770
|
Posted: 10 May 2008 08:11:07 pm Post subject: |
|
|
Here's an idea that sounds really neat (and has been suggested before): A program that will automatically log in on each TI site you choose and post the same topic (or post in the same topic) in each of them, thus making it way easier to post updates on projects that are on multiple forums, and aren't run-on sentences fun? |
|
Back to top |
|
|
benryves
Active Member
Joined: 23 Feb 2006 Posts: 564
|
Posted: 10 May 2008 08:17:56 pm Post subject: |
|
|
Newbie wrote: ...so I could read the results. LOL Heh, I usually set a breakpoint on the closing brace of the Main method so I can hover the variables to see their state. Either way, glad you got it working!
Quote: Your solution uses one field. How do I go about a form that has multiple fields, by knowing which field to write to? Oops, I probably should have mentioned that. You might have noticed the "application/x-www-form-urlencoded" content-type; this means you pass the field variables like this:
Code: field1=value1&field2=value2&field3=value3&field4=value4
(And so on and so forth). You need to make sure that the values you are passing are suitably encoded for passing via an URL (in my above example, the spaces were replaced with the + sign). Fortunately .NET provides a method to do this for us, but you will need to add a reference to System.Web to your project settings. Then you can do this:
Code: using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
using System.Web;
namespace PostWebRequestDemo {
class Program {
static void Main(string[] args) {
// Here are the fields to submit.
var Fields = new Dictionary<string, string>();
Fields.Add("text", "P funec naq .ARG ner pbby, ab?" + Environment.NewLine + "Abgr ubj guvf vf pbeerpgyl HEY-rapbqrq.");
Fields.Add("other", "There is no other field, but let's pretend!");
// Create a WebRequest instance to perform the query.
var Request = WebRequest.Create("http://www.rot13.com/");
Request.Method = "POST";
Request.ContentType = "application/x-www-form-urlencoded";
// Turn fields into a query string.
var RequestParams = CreateQueryString(Fields);
Request.ContentLength = RequestParams.Length;
// Write our request.
using (var RequestStreamWriter = new StreamWriter(Request.GetRequestStream(), Encoding.Default)) {
RequestStreamWriter.Write(RequestParams);
}
// Execute/Read the response.
string Response = "";
using (var ResponseReader = new StreamReader(Request.GetResponse().GetResponseStream())) {
Response = ResponseReader.ReadToEnd();
}
}
private static string CreateQueryString(IEnumerable<KeyValuePair<string, string>> fields) {
var EncodedFields = new List<string>();
foreach (var Field in fields) {
EncodedFields.Add(HttpUtility.UrlEncode(Field.Key) + "=" + HttpUtility.UrlEncode(Field.Value));
}
return string.Join("&", EncodedFields.ToArray());
}
}
}
Last edited by Guest on 10 May 2008 08:22:08 pm; edited 1 time in total |
|
Back to top |
|
|
Newbie
Bandwidth Hog
Joined: 23 Jan 2004 Posts: 2247
|
Posted: 10 May 2008 08:24:58 pm Post subject: |
|
|
So from what I'm seeing you don't really need to know the field names that the website uses, it's done in chronological order? For instance the first field.add would write to the first field on the form and the second to the second and so forth?
Edit: One last question. Do you know how to deal with an option on a form that would be a drop down list of items?
I really appreciate your help.
Last edited by Guest on 10 May 2008 08:31:33 pm; edited 1 time in total |
|
Back to top |
|
|
benryves
Active Member
Joined: 23 Feb 2006 Posts: 564
|
Posted: 10 May 2008 08:48:30 pm Post subject: |
|
|
Newbie wrote: So from what I'm seeing you don't really need to know the field names that the website uses, it's done in chronological order? No, you must explicitly pass the name of the form fields. You can get these by viewing the page source. Depending on how the way the page is written, you might not need to pass all of them, and you can probably pass extra ones, but you do need to use the name in the HTML source (including the case!) If you view the source for the rot13.com page, you'll see a <textarea> named "text".
Quote: Edit: One last question. Do you know how to deal with an option on a form that would be a drop down list of items? Find the corresponding <select> element, and it will contain a number of <option> elements. For example:
Code: <select name="boris">
<option value="1">Spaghetti</option>
<option value="2">Glass</option>
<option value="3">Piano</option>
</select>
To pass "Glass" I would need to do this:
Code: Fields.Add("boris", "2");
Checkboxes are more interesting; to submit a checkbox that is checked, pass its name and its value. If it is unchecked, do not pass it at all.
If you need to work out these details at runtime, you would need to parse the original HTML form somehow. This is a non-trivial operation if you wish to do it properly, though it is made easier via the WebBrowser.Document's DOM methods. |
|
Back to top |
|
|
Newbie
Bandwidth Hog
Joined: 23 Jan 2004 Posts: 2247
|
Posted: 10 May 2008 08:53:51 pm Post subject: |
|
|
Oh, I see how it works now. I thought the text meant the type of information you were trying to pass. Thanks a lot for your help, you cleared a lot of things up for me.
Edit:
I get an error: The name 'HttpUtility' does not exist in the current context.
Yeah um, I have the System.Web reference at the top and yet for some reason I get a compile error because of HttpUtility. Weird.
Also on this line: var Fields = new Dictionary<string, string>(); How is the select element added to that? I'm assuming that it would affect the CreateQueryString method too?
Last edited by Guest on 10 May 2008 09:30:12 pm; edited 1 time in total |
|
Back to top |
|
|
benryves
Active Member
Joined: 23 Feb 2006 Posts: 564
|
Posted: 11 May 2008 06:38:10 am Post subject: |
|
|
Newbie wrote: I get an error: The name 'HttpUtility' does not exist in the current context. As I mentioned, you need to add System.Web as a reference to your project. Go Project->Add Reference, select System.Web from the .NET tab, and that should resolve your compile errors.
Quote: Also on this line: var Fields = new Dictionary<string, string>(); How is the select element added to that? I'm assuming that it would affect the CreateQueryString method too? "Fields" is a dictionary mapping strings->strings. The CreateQueryString method takes an IEnumerable<KeyValuePair<string, string>> - ie, anything that can be enumerated over to retrieve string->string key->value pairs (which Dictionary<string, string> supports). It could as easily be a KeyValuePair<string, string>[] or a List<KeyValuePair<string, string>>, as these also implement IEnumerable<string, string>.
In any case, you'd just keep adding fields like this:
Code: Fields.Add("text", "P funec naq .ARG ner pbby, ab?" + Environment.NewLine + "Abgr ubj guvf vf pbeerpgyl HEY-rapbqrq.");
Fields.Add("other", "There is no other field, but let's pretend!");
Fields.Add("boris", "2");
Fields.Add("checkbox1", "ON");
Fields.Add("username", "a.n.other");
// ... and so on. :) Note that this would throw an exception:
Fields.Add("other", "uh-oh");
// ... as the key "other" already exists in the dictionary!
|
|
Back to top |
|
|
Newbie
Bandwidth Hog
Joined: 23 Jan 2004 Posts: 2247
|
Posted: 11 May 2008 06:39:01 pm Post subject: |
|
|
Thanks a lot for your help benryves. |
|
Back to top |
|
|
|