I remember being annoyed when Google canceled Reader, and at the time I was on a Windows 7 computer, so I fired up what I had in front of me (Visual Studio 2010), poked around on MSDN for a while and wrote my own reader program to use on my desktop. This is designed to fetch RSS feeds on the web, display their short descriptions in a webbrowser control, and then open the links in the system default browser if the user clicks any of the links. It includes Save/Open routines so the user can keep separate lists of RSS feeds.
This still works well enough on Windows 7 x64 with the .NET 4.6 framework, as I just tested it.
Imports System Imports System.IO Imports System.Net Imports System.Xml Imports System.Text.RegularExpressions Public Class frmRSS Dim rssDirPath As String = "C:\Users\" & Environment.UserName & "\Documents\" Dim rssFilePath As String = rssDirPath & "rssFeed.txt" Private Sub rssForm_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load ' Check for default text file on program start, quietly ignore if nonexistent Try Dim textIn As New StreamReader( New FileStream(rssFilePath, FileMode.Open, FileAccess.Read)) buildLinksListFromTxtFile(textIn) textIn.Close() Catch ex As FileNotFoundException Catch ex As DirectoryNotFoundException Catch ex As IOException End Try End Sub Private Sub buildLinksListFromTxtFile(ByVal file As StreamReader) ' Read contents of RSS links text file, check for valid format Dim rssLinks As New List(Of String) Dim lineNumber As Integer = 0 Do While file.Peek <> -1 lineNumber = lineNumber + 1 Dim row As String = file.ReadLine ' Hack to check if rssFeeds file is binary If row.Contains("\0\0") Or row.Contains("ΓΏ") Then MsgBox("This feeds list appears not to be a text file!", MsgBoxStyle.OkOnly) Exit Do ElseIf lineNumber = 1 And Not row.Contains("http") Then ' Hack to check that first line contains http; otherwise call it invalid text file MsgBox("This feeds list is invalid!", MsgBoxStyle.OkOnly) Exit Do Else rssLinks.Add(row) End If Loop ' Zero out cmbFeedList cmbFeedList.Items.Clear() For Each rssLink In rssLinks cmbFeedList.Items.Add(rssLink) Next file.Close() End Sub Private Sub btnFetch_Click(sender As System.Object, e As System.EventArgs) Handles btnFetch.Click ' Check for strings that are zero-length or without http protocol ' Set up some regular expressions to check for valid URLs Dim pattern As String = "^https?://[a-z0-9-]+(\.[a-z0-9-]+)+([/?].+)?$" Dim pattern2 As String = "^https?://www.[a-z0-9-]+(\.[a-z0-9-]+)+([/?].+)?$" Dim validURL As New Regex(pattern) Dim validURL2 As New Regex(pattern2) ' If URL contains www, it has to contain four parts: the protocol, www, ' the domain suffix, and some trailing characters, i.e., http://www.mysite.com/feed ' If URL doesn't contain www, it has to contain three parts: the protocol, domain ' suffix, and trailing characters, i.e., http://mysite.com/feed If ((cmbFeedList.Text.Contains("www") And validURL2.IsMatch(cmbFeedList.Text)) Or (Not cmbFeedList.Text.Contains("www") And validURL.IsMatch(cmbFeedList.Text))) Then ' Don't duplicate entries If Not cmbFeedList.Items.Contains(cmbFeedList.Text) Then cmbFeedList.Items.Add(cmbFeedList.Text) End If fetchRSS() Else MessageBox.Show("Please enter a valid RSS feed!", "Invalid RSS Feed", _ MessageBoxButtons.OK) End If End Sub Private Sub btnDelete_Click(sender As System.Object, e As System.EventArgs) _ Handles btnDelete.Click Dim deleteConfirm = MessageBox.Show("Are you sure you want to delete this feed?", _ "Confirm feed deletion", MessageBoxButtons.YesNo) If deleteConfirm = Windows.Forms.DialogResult.Yes Then cmbFeedList.Items.Remove(cmbFeedList.Text) End If End Sub Private Sub rssForm_FormClosing(sender As System.Object, e As _ System.Windows.Forms.FormClosingEventArgs) Handles MyBase.FormClosing ' Write rss list to text file Dim saveConfirm = MessageBox.Show("Do you want to save your current feed _ list? (If no, your existing rssFeeds.txt will be left untouched.)", "Save feed list", _ MessageBoxButtons.YesNoCancel) If saveConfirm = Windows.Forms.DialogResult.Yes Then writeRSSFile() ElseIf saveConfirm = Windows.Forms.DialogResult.Cancel Then e.Cancel = True End If End Sub Private Sub fetchRSS() Dim rssURL = cmbFeedList.Text Dim rssFeed As Stream = Nothing Dim errorMsg As String = Nothing ' Set up an HTTP request Dim request As HttpWebRequest = CType(WebRequest.Create(rssURL), HttpWebRequest) ' Try the download, check for HTTP OK status, grab feed if successful Try Dim response As HttpWebResponse = CType(request.GetResponse(), HttpWebResponse) If response.StatusCode = HttpStatusCode.OK Then rssFeed = response.GetResponseStream() showRSS(rssFeed) End If Catch e As WebException errorMsg = "Download failed. The response from the server was: " + CType(e.Response, HttpWebResponse).StatusDescription MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK) Catch e As Exception errorMsg = "This doesn't look like an RSS feed. The specific error is: " + e.Message 'errorMsg = "Hmm, there was a problem: " + e.Message MessageBox.Show(errorMsg, "Error", MessageBoxButtons.OK) End Try End Sub Private Overloads Sub writeRSSFile() ' Write rss list to text file - method with fixed path called on program close Dim textOut As New StreamWriter( New FileStream(rssFilePath, FileMode.Create, FileAccess.Write)) For Each rssLink In cmbFeedList.Items textOut.WriteLine(rssLink.ToString) Next textOut.Close() End Sub Private Overloads Sub writeRSSFile(ByVal file As Integer) ' Write rss list to text file - method called from File menu with user-determined path Dim saveFileDialog1 As New SaveFileDialog() saveFileDialog1.InitialDirectory = rssFilePath saveFileDialog1.Filter = "txt files (*.txt)|*.txt" If saveFileDialog1.ShowDialog() = DialogResult.OK Then Dim outputFile As StreamWriter = New StreamWriter(saveFileDialog1.OpenFile()) If (outputFile IsNot Nothing) Then For Each rssLink In cmbFeedList.Items outputFile.WriteLine(rssLink.ToString) Next outputFile.Close() End If End If End Sub Private Sub showRSS(ByVal rssStream As Stream) ' Process contents of RSS feed (XML) Dim rssFeed = XDocument.Load(rssStream) Dim output As String = Nothing ' Use XML literals to pull out the tags I want For Each post In From element In rssFeed...<item> output += "<h3>" + post.<title>.Value + "</h3>" ' Fix the date Dim correctDate = DateTime.Parse(post.<pubDate>.Value) output += "<strong>Posted on " + correctDate + "</strong>" '"<a href=""" + post.<link>.Value + " target=""_blank"">" output += post.<description>.Value Next ' Rewrite articles to open links in new window; replaced by navigating event override below ' Dim fixedOutput = output.Replace("<a rel=""nofollow""", "<a rel=""nofollow"" target=""_blank""") wbFeedList.DocumentText = "<html><body><font face=""sans-serif"">" + _ output.ToString() + "</font></body></html>" End Sub Private Sub HelpToolStripMenuItemHelp_Click(sender As System.Object, e As _ System.EventArgs) Handles HelpToolStripMenuItemHelp.Click rssHelpBox.Show() End Sub Private Sub AboutToolStripMenuItem_Click(sender As System.Object, e As _ System.EventArgs) Handles AboutToolStripMenuItem.Click rssAboutBox.Show() End Sub Private Sub QuitToolStripMenuItem_Click(sender As System.Object, e As _ System.EventArgs) Handles QuitToolStripMenuItem.Click writeRSSFile() Me.Close() End Sub Private Sub OpenFeedlistToolStripMenuItem_Click(sender As System.Object, e As _ System.EventArgs) Handles OpenFeedlistToolStripMenuItem.Click ' Open feeds file from file menu Dim openFileDialog1 As New OpenFileDialog() openFileDialog1.InitialDirectory = rssFilePath openFileDialog1.Filter = "txt files (*.txt)|*.txt" openFileDialog1.RestoreDirectory = True ' Offer to save existing feeds list first Dim saveOnClose = MsgBox("Would you like to save your existing feeds list ?", _ MsgBoxStyle.YesNoCancel) If saveOnClose = MsgBoxResult.Yes Then writeRSSFile(1) ElseIf saveOnClose = MsgBoxResult.Cancel Then Return End If ' Open open file dialog If openFileDialog1.ShowDialog() = System.Windows.Forms.DialogResult.OK Then Try Dim fileStream = New StreamReader(openFileDialog1.OpenFile) If (fileStream IsNot Nothing) Then ' Open dialog buildLinksListFromTxtFile(fileStream) End If Catch Ex As IOException MessageBox.Show("Cannot read file from disk. The error is: " & Ex.Message) End Try End If End Sub Private Sub SaveFeedlistToolStripMenuItem_Click(sender As System.Object, e As _ System.EventArgs) Handles SaveFeedlistToolStripMenuItem.Click ' Save current file as txt If cmbFeedList.Items.Count > 0 Then writeRSSFile(1) Else MessageBox.Show("Add some RSS feeds before you try to save them!", "Error", _ MessageBoxButtons.OK) End If End Sub Private Sub wbFeedList_Navigating(sender As Object, e As _ System.Windows.Forms.WebBrowserNavigatingEventArgs) Handles wbFeedList.Navigating ' Open links in default browser instead of webbrowser control If Not (e.Url.ToString().Equals("about:blank", StringComparison.InvariantCultureIgnoreCase)) Then e.Cancel = True Process.Start(e.Url.ToString()) End If End Sub End Class
Categories:
I participate in the Amazon Associates program. Making your Amazon purchases through my affiliate links supports this site at no additional cost to you: