I've been following this great tutorial:
http://buildmobile.com/twitter-in-a-windows-phone-7-app/#fbid=o0eLp-OipGa
But it seems that the pin extraction method used in doesn't work for me or is out of date. I'm not an expert on html scrapping and was wondering if someone could help me find a solution to extracting the pin. The method used by the tutorial is:
private void BrowserNavigated(object sender, NavigationEventArgs e){
if (AuthenticationBrowser.Visibility == Visibility.Collapsed) {
AuthenticationBrowser.Visibility = Visibility.Visible;
}
if (e.Uri.AbsoluteUri.ToLower().Replace("https://", "http://") == AuthorizeUrl) {
var htmlString = AuthenticationBrowser.SaveToString();
var pinFinder = new Regex(#"<DIV id=oauth_pin>(?<pin>[A-Za-z0-9_]+)</DIV>", RegexOptions.IgnoreCase);
var match = pinFinder.Match(htmlString);
if (match.Length > 0) {
var group = match.Groups["pin"];
if (group.Length > 0) {
pin = group.Captures[0].Value;
if (!string.IsNullOrEmpty(pin)) {
RetrieveAccessToken();
}
}
}
if (string.IsNullOrEmpty(pin)){
Dispatcher.BeginInvoke(() => MessageBox.Show("Authorization denied by user"));
}
// Make sure pin is reset to null
pin = null;
AuthenticationBrowser.Visibility = Visibility.Collapsed;
}
}
When running through that code, "match" always ends up null and the pin is never found. Everything else in the tutorial works, but I have no idea how to manipulate this code to extract the pin due to the new structure of the page.
I really appreciate the time,
Mike
I have found that Twitter has 2 different PIN pages, and I think they determine which page to redirect you to depending on your browser.
Something as simple as string parsing will work for you. The first PIN page I came across has the PIN code wrapped in a <.code> tag, so simply look for <.code> and parse it out:
if (innerHtml.Contains("<code>"))
{
pin = innerHtml.Substring(innerHtml.IndexOf("<code>") + 6, 7);
}
The other page I came across (which looks like the one in the tutorial you are using) is wrapped using an id="oauth_pin" if I recall correctly. So, just parse that as well:
else if(innerHtml.Contains("oauth_pin"))
{
pin = innerHtml.Substring(innerHtml.IndexOf("oauth_pin") + 10, 7);
}
innerHtml is a string that contains the body of the page. Which seems to be var htmlString = AuthenticationBrowser.SaveToString(); from your code.
I use both of these in my C# program and they work great, full snippet:
private void WebBrowser1DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
var innerHtml = webBrowser1.Document.Body.InnerHtml.ToLower();
var code = string.Empty;
if (innerHtml.Contains("<code>"))
{
code = innerHtml.Substring(innerHtml.IndexOf("<code>") + 6, 7);
}
else if(innerHtml.Contains("oauth_pin"))
{
code = innerHtml.Substring(innerHtml.IndexOf("oauth_pin") + 10, 7);
}
textBox1.Text = code;
}
Let me know if you have any question and I hope this helps!!
I need to change the code suggested from Toma A with this one:
var innerHtml = webBrowser1.SaveToString();
var code = string.Empty;
if (innerHtml.Contains("<code>"))
{
code = innerHtml.Substring(innerHtml.IndexOf("<code>") + 6, 7);
}
else if (innerHtml.Contains("oauth_pin"))
{
code = innerHtml.Substring(innerHtml.IndexOf("oauth_pin") + 10, 7);
}
because this one doesn't works for windows phone
var innerHtml = webBrowser1.Document.Body.InnerHtml.ToLower();
Related
I am really new to coding, never studied it or something similar, just learning it myself, never done it before, but I am trying to create my first real application right new.
However, I have some problems for 2 days which I just can't figure out, so I hope you can help me out.
Alright, so before the youtubedlCurrentWorker_Process() is created, I did define 'public string CurrentYouTubeDLVersion'.
How ever, when a button in my application executes the youtubedlCompareVersion_Process(), the CurrentYouTubeDLVersion string is empty, when it comes at the compare point.
Below is just a little part of my code.
Why is the string CurrentYouTubeDLVersion empty in the CompareVersion while the GetCurrentVersion ran before it?
Even if I double click "CurrentYouTubeDLVersion" in Visual Studio, it won't show a link to the one in the GetCurrentVersion_Process.
namespace MediaDownloader
{
public partial class updates : UserControl
{
public string LatestYoutubeDLVersion;
public string CurrentYouTubeDLVersion;
public void youtubedlGetCurrentVersion_Process()
{
if (File.Exists(YouTubeDLPath))
{
//Here I get the current version of youtube-dl.exe, to get the version number, we have to run youtube-dl.exe --version
Process youtubedl = new Process();
youtubedl.StartInfo.CreateNoWindow = true;
youtubedl.StartInfo.UseShellExecute = false;
youtubedl.StartInfo.RedirectStandardOutput = true;
youtubedl.StartInfo.RedirectStandardError = true;
youtubedl.StartInfo.FileName = YouTubeDLPath;
youtubedl.StartInfo.Arguments = " --version";
youtubedl.Start();
string CurrentYouTubeDLVersion = youtubedl.StandardOutput.ReadToEnd();
this.Dispatcher.Invoke((Action)(() =>
{
CurrentYouTubeDLVersionText.Text = "Current youtube-dl.exe version: " + CurrentYouTubeDLVersion;
YouTubeDLVersionStatusText.Text = null;
UpdateYouTubeDL.IsEnabled = false;
}));
}
public void youtubedlCompareVersion_Process()
{
youtubedlGetCurrentVersion_Process();
string LatestYoutubeDLVersion = WebClient.DownloadString("https://yt-dl.org/latest/version");
MessageBox.Show("Latest:" + LatestYoutubeDLVersion + "Current " + CurrentYouTubeDLVersion);
int YouTubeDLUptodate = CurrentYouTubeDLVersion.CompareTo(LatestYoutubeDLVersion);
if (YouTubeDLUptodate < 1)
{
YouTubeDLVersionStatusText.Text = "Your youtube-dl.exe is out of date, please click the button below to update.";
UpdateYouTubeDL.IsEnabled = true;
}
else
{
YouTubeDLVersionStatusText.Text = "youtube-dl.exe is up to date!";
UpdateYouTubeDL.IsEnabled = false;
}
}
}
Inside the youtubedlGetCurrentVersion_Process method, you're creating a new CurrentYouTubeDLVersion string, and it's completely separate from the public CurrentYouTubeDLVersion you added to the top of the class.
string CurrentYouTubeDLVersion = youtubedl.StandardOutput.ReadToEnd();
Assign to the class-level variable you made, instead of creating a new string:
CurrentYouTubeDLVersion = youtubedl.StandardOutput.ReadToEnd();
Then the value will be available to you in youtubedlCompareVersion_Process.
Take out the 'string' in front of CurrentYouTubeDLVersion and it should work
public youtubedlGetCurrentVersion_Process()
{
/* removed code to make easier to read */
//string CurrentYouTubeDLVersion = youtubedl.StandardOutput.ReadToEnd();
CurrentYouTubeDLVersion = youtubedl.StandardOutput.ReadToEnd();
/* removed code to make easier to read */
}
I've got a few web pages that have static data in HTML mark-up tables. By this, I mean, manually maintained text:
<table border="1" >
<tr><th>Number</th><th>Date</th><th>BW</th><th>WW</th><th>%</th><th>Type</th><th>CED</th><th>BW</th><th>WW</th><th>YW</th><th>Mlk</th><th>Me</th></tr>
<tr><td>313</td><td>9/16/2013</td><td>74</td><td>512</td><td>100</td><td>861U</td><td>3</td><td>-1.1</td><td>54</td><td>85</td><td>16</td><td></td></tr>
<tr><td>315</td><td>10/6/2013</td><td>-</td><td>-</td><td>-</td><td>W179</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td><td>-</td></tr>
<tr><td>316</td><td>10/102013</td><td>72</td><td>595</td><td>94.2</td><td>W179</td><td>7</td><td>-2.3</td><td>53</td><td>80</td><td>21</td><td>-3</td></tr>
<tr><td>350</td><td>10/11/2013</td><td>71</td><td>703</td><td>100</td><td>W179</td><td>7</td><td>-2.3</td><td>46</td><td>72</td><td>20</td><td>-5</td></tr>
<tr><td>392</td><td>3/8/2013</td><td>61</td><td>651</td><td>100</td><td>RANGER</td><td>7</td><td>-2.3</td><td>52</td><td>82</td><td>20</td><td>-2</td></tr>
<tr><td>303</td><td>7/3/2013</td><td>63</td><td>-</td><td>97.1</td><td>W179</td><td>8</td><td>-3.2</td><td>N/A</td><td>82</td><td>21</td><td>-8</td></tr>
<tr><td>304</td><td>7/8/2013</td><td>62</td><td>-</td><td>97.1</td><td>W179</td><td>7</td><td>-3.9</td><td>N/A</td><td>69</td><td>20</td><td>-4</td></tr>
<tr><td>397</td><td>3/18/2013</td><td>78</td><td>621</td><td>100</td><td>STATEMENT</td><td>6</td><td>-2.7</td><td>55</td><td>84</td><td>19</td><td>5</td></tr>
<tr><td>395</td><td>3/17/2013</td><td>63</td><td>716</td><td>94.2</td><td>STATEMENT</td><td>5</td><td>-2.7</td><td>54</td><td>85</td><td>19</td><td>5</td></tr>
<tr><td>390</td><td>3/6/2013</td><td>66</td><td>583</td><td>94.2</td><td>ENVY</td><td>2</td><td>-0.6</td><td>55</td><td>80</td><td>23</td><td>2</td></tr>
<tr><td>388</td><td>3/4/2013</td><td>53</td><td>621</td><td>100</td><td>STATEMENT</td><td>10</td><td>-5.1</td><td>49</td><td>82</td><td>20</td><td>2</td></tr>
<tr><td>300</td><td>3/22/2013</td><td>61</td><td>633</td><td>100</td><td>RANGER</td><td>8</td><td>-2.8</td><td>49</td><td>81</td><td>19</td><td>-2</td></tr>
<tr><td>379</td><td>2/1/2013</td><td>55</td><td>518</td><td>100</td><td>STATEMENT</td><td>8</td><td>-4.1</td><td>61</td><td>98</td><td>18</td><td>1</td></tr>
<tr><td>398</td><td>3/20/2013</td><td>62</td><td>664</td><td>100</td><td>RANGER</td><td>6</td><td>-2.3</td><td>53</td><td>83</td><td>20</td><td>0</td></tr>
<tr><td>384</td><td>2/10/2013</td><td>61</td><td>650</td><td>100</td><td>ENVY</td><td>3</td><td>-1</td><td>50</td><td>70</td><td>19</td><td>4</td></tr>
<tr><td>369</td><td>1/30/2013</td><td>76</td><td>651</td><td>100</td><td>STATEMENT</td><td>5</td><td>-2.4</td><td>60</td><td>99</td><td>20</td><td>8</td></tr>
<tr><td>373</td><td>1/21/2013</td><td>71</td><td>433</td><td>100</td><td>STATEMENT</td><td>4</td><td>-1.6</td><td>55</td><td>89</td><td>17</td><td>3</td></tr>
<tr><td>393</td><td>3/10/2013</td><td>63</td><td>717</td><td>100</td><td>STATEMENT</td><td>3</td><td>-4.6</td><td>51</td><td>91</td><td>20</td><td>5</td></tr>
<tr><td>389</td><td>3/8/2013</td><td>72</td><td>723</td><td>88.3</td><td>ENVY</td><td>4</td><td>-0.6</td><td>54</td><td>76</td><td>24</td><td>2</td></tr>
<tr><td>364</td><td>10/1/2012</td><td>60</td><td>574</td><td>100</td><td>RANGER</td><td>1</td><td>0.4</td><td>56</td><td>84</td><td>21</td><td>2</td></tr>
</table>
Currently, I am contemplating using a WebClient.DownloadString to pull all of the text in, and try to create an XML file out of it by parsing each row <tr>.
That sounds tedious, and I would rather not reinvent the wheel. Besides, a few good solutions would give me something to look at for ideas on how to best approach writing my version.
Has anyone come across some code that can do this?
I've started, to give you an idea of what I'm working on:
private const string XML_DATA = "App_Data/page_data.xml";
private const string TABLE_START = "<table>";
private const string TABLE_STOP = "</table>";
private string[] TABLE_ROW = { "<tr>", "</tr>" };
private string[] TABLE_HEAD = { "<th>", "</th>" };
private string[] TABLE_DET = { "<td>", "</td>" };
private void load_data() {
if (!File.Exists(XML_DATA)) {
string HtmlText;
using (var client = new WebClient()) {
HtmlText = client.DownloadString(Server.MapPath("/Sales.aspx"));
}
if (!String.IsNullOrEmpty(HtmlText)) {
var lcTxt = HtmlText.ToLower();
int len0 = TABLE_START.Length;
int tStart = lcTxt.IndexOf(TABLE_START) + len0;
int tStop = lcTxt.IndexOf(TABLE_STOP);
if ((len0 < tStart) && (tStart < tStop)) {
var tableString = HtmlText.Substring(tStart, tStop - tStart);
var tableRows = tableString.Split(TABLE_ROW, StringSplitOptions.RemoveEmptyEntries);
foreach (var row in tableRows) {
if (-1 < row.IndexOf(TABLE_HEAD[0])) {
//
} else {
//
}
}
}
}
}
}
Of course, you can see that is already going to fail, because the Markup using <table border="1">.
Yes, easy to fix, but I'd rather have a working guide that has already been through a lot of debugging steps.
UPDATE: I tried using XmlDocument's LoadXml method, but it can't seem to read basic HTML:
You definitely shouldn't be trying to parse that manually. Other people have already solved that problem.
If your markup is valid XML (and from what you've shown us, it looks like it is), then you can just parse it as XML:
XmlDocument doc = new XmlDocument();
doc.LoadXml(HtmlString);
doc.Save("myfile.xml");
But for that matter, if it's already valid XML markup, and all you need to do is save it as a file, then you don't need to parse it. Just save it:
File.WriteAllText("myfile.xml", HtmlString);
Backstory,
So I am working on a personal assistant program and all my voice commands are translated into strings for parsing.
I have set up the ability to search Google and display the results in a text block as hyperlinks.
Now I want to be able to set up the ability to open these links with speech(string commands). So far I have the following.
This bit allows me to search using the Google Custom Search API with a custom "GoogleSearch" class.
public void search_google(string query) //Google Searching
{
#region link strings
string result_1 = "";
string result_2 = "";
string result_3 = "";
string result_4 = "";
string result_5 = "";
string result_6 = "";
string result_7 = "";
string result_8 = "";
string result_9 = "";
string result_10 = "";
#endregion
GoogleSearch search = new GoogleSearch()
{
Key = "{apikey}",
CX = "{cxkey}"
};
search.SearchCompleted += (a, b) =>
{
tab_control.SelectedIndex = 2;
int p = 1;
search_results.Text = String.Empty;
foreach (Item i in b.Response.Items)
{
Hyperlink hyperLink = new Hyperlink()
{
NavigateUri = new Uri(i.Link)
};
hyperLink.Inlines.Add(i.Title);
hyperLink.RequestNavigate += Hyperlink_RequestNavigate;
hyperLink.Name = "result_" + p;
//search_results.Inlines.Add(hyperLink.Name);
search_results.Inlines.Add(Environment.NewLine);
search_results.Inlines.Add(hyperLink);
search_results.Inlines.Add(Environment.NewLine);
search_results.Inlines.Add(i.Snippet);
search_results.Inlines.Add(Environment.NewLine);
search_results.Inlines.Add(Environment.NewLine);
p++;
};
};
search.Search(query);
}
It outputs my results in a series of hyperlinks and text snippets into a text block that I set up on the main window. The search process is triggered by my input parser which looks for the keywords "search" or "Google".
The next step would be the input parser checking for keyword "result" to look for the hyperlink to open. Here is the unfinished code for that.
if ((Input.Contains("result") || Input.Contains("Result")) && tab_control.TabIndex == 2)
{
int result_number = 0;
switch(result_number)
{
case 1:
if (Input.Contains("first") || Input.Contains("1st"))
{
// open hyperlink with name property result_1
}
break;
case 2:
// additional cases added up to 10 with similar syntax for parsing.
}
}
You can open a hyperlink in the default browser using:
Process.Start(myHyperlink);
EDIT
Based on your comments, it seems you are having trouble accessing result_1 (etc.).
You define result_1 as a variable local to the method search_google()
public void search_google(string query) //Google Searching
{
#region link strings
string result_1 = "";
That means result_1 is only visible within that method.
Your if and switch statements do not appear to be part of search_google(), so they can never see result_1. If those statements are in a different method, you can work around that issue by moving result_1 to the class level (outside of search_google()).
ON a site note, rather than defining ten individual result strings, you probably want to use an array of strings or a list of strings.
I'm having following code which runs perfectly on dev server but gives error on live server.
It gives me following error
System.UriFormatException: Invalid URI: The format of the URI could not be determined.
Please guide me how to resolve this issue.
<-----------------Code Started--------------------->
private void InsertThrAPI(clsProductProp objProductProp)
{
xmldata data = new xmldata();
data.Items = new xmldataProducts[1];
data.Items[0] = new xmldataProducts();
objProduct.stockstatus = Convert.ToString(objProductProp.stockstatus);
objProduct.price = Convert.ToString(objProductProp.price);
objProduct.productname = Convert.ToString(objProductProp.productname);
objProduct.productshortname = Convert.ToString(objProductProp.productshortname);
objProduct.productcode = Convert.ToString(objProductProp.productcode);
objProduct.description = Convert.ToString(objProductProp.description);
objProduct.technicalspecs = Convert.ToString(objProductProp.technicalspecs);
objProduct.shippingcost = Convert.ToString(objProductProp.shippingcost);
objProduct.productweight = Convert.ToString(objProductProp.productweight);
objProduct.vendorprice = Convert.ToString(objProductProp.vendorprice);
if (objProductProp.shipping == true || objProductProp.shipping == Convert.ToBoolean(1))
{
objProduct.shipping = "Y";
}
else
{
objProduct.shipping = "N";
}
//Populate the product fields here
data.Items[0].StockStatus = objProduct.stockstatus;
data.Items[0].ProductPrice = objProduct.price;
data.Items[0].ProductName = objProduct.productname;
data.Items[0].ProductNameShort = objProduct.productshortname;
data.Items[0].ProductCode = objProduct.productcode;
data.Items[0].ProductDescription = objProduct.description;
data.Items[0].TechSpecs = objProduct.technicalspecs;
data.Items[0].FreeShippingItem = objProduct.shipping;
data.Items[0].Fixed_ShippingCost = objProduct.shippingcost;
data.Items[0].ProductWeight = objProduct.productweight;
data.Items[0].Vendor_Price = objProduct.vendorprice;
string productXML = Utils.GetProductXML(data);
string APIURL = Utils.GetAPIPostURL(ImportMode.Insert);
XMLPostManager manager = new XMLPostManager();
string response = manager.SendXMLToURL(APIURL, productXML);
//Response.Write(response);
}
We would need to see the URL to tell you what's wrong with it, but you can check to make sure that the URL is valid like this:
if (Uri.IsWellFormedUriString(APIURL, UriKind.RelativeOrAbsolute))
{
//url is valid
}
Please guide me how to resolve this issue.
I guess you main problem is that this only happens in live and not in your dev system, so debugging is hard?
A couple of suggestion:
Look in to adding logging code - there's a lot of info out there, but
something like Log4Net would be a good start. Add logging code
to this method and you should hopefully see the data that is causing
issues.
See if you can add more realistic data to your unit tests or
other internal tests and see if you can spot this.
How can I show the PI Tag search dialog, and secondarily, how can I get the selected tag name from it?
Hopefully this can be of some use to you:
private void Button1_Click(object sender, EventArgs e) {
TagSearch dialog = new TagSearch();
PointList results = dialog.showTagSearch(
new string[] { }, SearchOptions.SingleSelect);
if (results.Count > 0) {
object index = 1;
string serverTag =
string.Format(
CultureInfo.InvariantCulture,
#"\\{0}\{1}",
results.get_Item(ref index).Server.Name,
results.get_Item(ref index).Name);
}
}
Please download the PI ProcessBook user manual from the OSIsoft Technical Support website, and see section: PI Tag Search (pg.57):
http://techsupport.osisoft.com/Techsupport/NonTemplates/Download%20Center/DownloadCenter.aspx?download_file=26B66920-EF5F-4ECE-866B-44CD446EED49
FYI for anyone else looking for similar.
I came here looking for a steer on this, and this code (the accepted answer) was great in pointing me in the right direction. The syntax has changed slightly in newer versions of the SDK. Here is my (basic) updated code:
public PIPoint SearchForPoint()
{
TagSearch searchDialog = new TagSearch();
PointList result = searchDialog.Show(null, TagSearchOptions.tsoptSingleSelect);
if (result.Count > 0)
{
return result[1];
}
return null;
}
This also requires a reference to the PISDKdlg library (mine is version 16.8.0.0).