I have an application where I have to print a RDLC report without showing the printDialog and using the default specified printer defined in the application. Below is my test implementaion code.
Microsoft.Reporting.WinForms.ReportViewer reportViewerSales = new Microsoft.Reporting.WinForms.ReportViewer();
Microsoft.Reporting.WinForms.ReportDataSource reportDataSourceSales = new Microsoft.Reporting.WinForms.ReportDataSource();
reportViewerSales.Reset();
reportViewerSales.LocalReport.ReportPath = #"Sales.rdlc";
reportDataSourceSales.Name = "SalesTableDataSet";
int i = 1;
foreach (Product item in ProductSalesList)
{
dataset.CurrentSales.AddCurrentSalesRow(i, item.Name, item.Quantity.ToString(), item.Price.ToString(), item.Price.ToString());
i++;
}
reportDataSourceSales.Value = dataset.CurrentSales;
reportViewerSales.LocalReport.DataSources.Add(reportDataSourceSales);
dataset.EndInit();
reportViewerSales.RefreshReport();
reportViewerSales.RenderingComplete += new RenderingCompleteEventHandler(PrintSales);
And here is my Rendering Complete Method
public void PrintSales(object sender, RenderingCompleteEventArgs e)
{
try
{
reportViewerSales.PrintDialog();
reportViewerSales.Clear();
reportViewerSales.LocalReport.ReleaseSandboxAppDomain();
}
catch (Exception ex)
{
}
}
I just gave a quick look to a class I created to print directly and I think I took some ideas from this walkthrough:
Printing a Local Report without Preview
i have made an extension class to #tezzos answer. which might make it more easier.
use this Gist Here to get the extension class i wrote. include it to your project. don't for get namespace :D
LocalReport report = new LocalReport();
report.ReportEmbeddedResource = "Your.Reports.Path.rdlc";
report.DataSources.Add(new ReportDataSource("DataSet1", getYourDatasource()));
report.PrintToPrinter();
PrintToPrinter Method will be available on LocalReport. Might Help someone
Download C# full Project file
using Microsoft.Reporting.WinForms;
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;
namespace WindowsFormsApp
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
this.UiLabelUpTableAdapter.Fill(this.POSDataSet.UiLabelUp);
this.reportViewer1.RefreshReport();
}
private void buttonPrintReport_Click(object sender, EventArgs e)
{
ReportViewer InvoiceReport = new ReportViewer();
InvoiceReport.LocalReport.ReportPath = #"C:\Users\Chamod\source\repos\WindowsFormsApp\WindowsFormsApp\Report1.rdlc";
ReportDataSource DataSet1 = new ReportDataSource("DataSet1", UiLabelUpBindingSource);
InvoiceReport.LocalReport.DataSources.Add(DataSet1);
LocalReport lr = InvoiceReport.LocalReport;
lr.PrintToPrinter();
InvoiceReport.Clear();
}
}
}
using Microsoft.Reporting.WinForms;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using System.IO;
namespace WindowsFormsApp
{
public static class LocalReportExtensions
{
public static void PrintToPrinter(this LocalReport report)
{
PageSettings pageSettings = new PageSettings();
pageSettings.PaperSize = report.GetDefaultPageSettings().PaperSize;
pageSettings.Landscape = report.GetDefaultPageSettings().IsLandscape;
pageSettings.Margins = report.GetDefaultPageSettings().Margins;
Print(report, pageSettings);
}
public static void Print(this LocalReport report, PageSettings pageSettings)
{
string deviceInfo =
$#"<DeviceInfo>
<OutputFormat>EMF</OutputFormat>
<PageWidth>{pageSettings.PaperSize.Width * 100}in</PageWidth>
<PageHeight>{pageSettings.PaperSize.Height * 100}in</PageHeight>
<MarginTop>{pageSettings.Margins.Top * 100}in</MarginTop>
<MarginLeft>{pageSettings.Margins.Left * 100}in</MarginLeft>
<MarginRight>{pageSettings.Margins.Right * 100}in</MarginRight>
<MarginBottom>{pageSettings.Margins.Bottom * 100}in</MarginBottom>
</DeviceInfo>";
Warning[] warnings;
var streams = new List<Stream>();
var pageIndex = 0;
report.Render("Image", deviceInfo,
(name, fileNameExtension, encoding, mimeType, willSeek) =>
{
MemoryStream stream = new MemoryStream();
streams.Add(stream);
return stream;
}, out warnings);
foreach (Stream stream in streams)
stream.Position = 0;
if (streams == null || streams.Count == 0)
throw new Exception("No stream to print.");
using (PrintDocument printDocument = new PrintDocument())
{
printDocument.DefaultPageSettings = pageSettings;
if (!printDocument.PrinterSettings.IsValid)
throw new Exception("Can't find the default printer.");
else
{
printDocument.PrintPage += (sender, e) =>
{
Metafile pageImage = new Metafile(streams[pageIndex]);
Rectangle adjustedRect = new Rectangle(e.PageBounds.Left - (int)e.PageSettings.HardMarginX, e.PageBounds.Top - (int)e.PageSettings.HardMarginY, e.PageBounds.Width, e.PageBounds.Height);
e.Graphics.FillRectangle(Brushes.White, adjustedRect);
e.Graphics.DrawImage(pageImage, adjustedRect);
pageIndex++;
e.HasMorePages = (pageIndex < streams.Count);
e.Graphics.DrawRectangle(Pens.Red, adjustedRect);
};
printDocument.EndPrint += (Sender, e) =>
{
if (streams != null)
{
foreach (Stream stream in streams)
stream.Close();
streams = null;
}
};
printDocument.Print();
}
}
}
}
}
public void PrintSales(object sender, RenderingCompleteEventArgs e)
{
try
{
reportViewerSales.PageSetupDailog();
reportViewerSales.PrintDialog();
reportViewerSales.Clear();
reportViewerSales.LocalReport.ReleaseSandboxAppDomain();
}
catch (Exception ex)
{
}
}
Related
I'm using this code for printing to printer to print reportviewer without showing dialoge,
but I can't set the number of copies to print
I need a textbox or numericUpDown or anything to put the number of copies
using System;
using System.IO;
using System.Text;
using System.Globalization;
using System.Drawing;
using System.Drawing.Imaging;
using System.Drawing.Printing;
using Microsoft.Reporting.WinForms;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Diagnostics;
using System.ComponentModel;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace NewLabelPrinter
{
/// <summary>
/// The ReportPrintDocument will print all of the pages of a ServerReport or LocalReport.
/// The pages are rendered when the print document is constructed. Once constructed,
/// call Print() on this class to begin printing.
/// </summary>
class AutoPrintCls : PrintDocument
{
private PageSettings m_pageSettings;
private int m_currentPage;
private List<Stream> m_pages = new List<Stream>();
public AutoPrintCls(ServerReport serverReport)
: this((Report)serverReport)
{
RenderAllServerReportPages(serverReport);
}
public AutoPrintCls(LocalReport localReport)
: this((Report)localReport)
{
RenderAllLocalReportPages(localReport);
}
private AutoPrintCls(Report report)
{
// Set the page settings to the default defined in the report
ReportPageSettings reportPageSettings = report.GetDefaultPageSettings();
// The page settings object will use the default printer unless
// PageSettings.PrinterSettings is changed. This assumes there
// is a default printer.
m_pageSettings = new PageSettings();
m_pageSettings.PaperSize = reportPageSettings.PaperSize;
m_pageSettings.Margins = reportPageSettings.Margins;
}
protected override void Dispose(bool disposing)
{
base.Dispose(disposing);
if (disposing)
{
foreach (Stream s in m_pages)
{
s.Dispose();
}
m_pages.Clear();
}
}
protected override void OnBeginPrint(PrintEventArgs e)
{
base.OnBeginPrint(e);
m_currentPage = 0;
}
protected override void OnPrintPage(PrintPageEventArgs e)
{
base.OnPrintPage(e);
Stream pageToPrint = m_pages[m_currentPage];
pageToPrint.Position = 0;
// Load each page into a Metafile to draw it.
using (Metafile pageMetaFile = new Metafile(pageToPrint))
{
Rectangle adjustedRect = new Rectangle(
e.PageBounds.Left - (int)e.PageSettings.HardMarginX,
e.PageBounds.Top - (int)e.PageSettings.HardMarginY,
e.PageBounds.Width,
e.PageBounds.Height);
// Draw a white background for the report
e.Graphics.FillRectangle(Brushes.White, adjustedRect);
// Draw the report content
e.Graphics.DrawImage(pageMetaFile, adjustedRect);
// Prepare for next page. Make sure we haven't hit the end.
m_currentPage++;
e.HasMorePages = m_currentPage < m_pages.Count;
}
}
protected override void OnQueryPageSettings(QueryPageSettingsEventArgs e)
{
e.PageSettings = (PageSettings)m_pageSettings.Clone();
}
private void RenderAllServerReportPages(ServerReport serverReport)
{
try
{
string deviceInfo = CreateEMFDeviceInfo();
// Generating Image renderer pages one at a time can be expensive. In order
// to generate page 2, the server would need to recalculate page 1 and throw it
// away. Using PersistStreams causes the server to generate all the pages in
// the background but return as soon as page 1 is complete.
NameValueCollection firstPageParameters = new NameValueCollection();
firstPageParameters.Add("rs:PersistStreams", "True");
// GetNextStream returns the next page in the sequence from the background process
// started by PersistStreams.
NameValueCollection nonFirstPageParameters = new NameValueCollection();
nonFirstPageParameters.Add("rs:GetNextStream", "True");
string mimeType;
string fileExtension;
Stream pageStream = serverReport.Render("IMAGE", deviceInfo, firstPageParameters, out mimeType, out fileExtension);
// The server returns an empty stream when moving beyond the last page.
while (pageStream.Length > 0)
{
m_pages.Add(pageStream);
pageStream = serverReport.Render("IMAGE", deviceInfo, nonFirstPageParameters, out mimeType, out fileExtension);
}
}
catch (Exception e)
{
MessageBox.Show("possible missing information :: " + e);
}
}
private void RenderAllLocalReportPages(LocalReport localReport)
{
try
{
string deviceInfo = CreateEMFDeviceInfo();
Warning[] warnings;
localReport.Render("IMAGE", deviceInfo, LocalReportCreateStreamCallback, out warnings);
}
catch (Exception e)
{
MessageBox.Show("error :: " + e);
}
}
private Stream LocalReportCreateStreamCallback(
string name,
string extension,
Encoding encoding,
string mimeType,
bool willSeek)
{
MemoryStream stream = new MemoryStream();
m_pages.Add(stream);
return stream;
}
private string CreateEMFDeviceInfo()
{
PaperSize paperSize = m_pageSettings.PaperSize;
Margins margins = m_pageSettings.Margins;
// The device info string defines the page range to print as well as the size of the page.
// A start and end page of 0 means generate all pages.
return string.Format(
CultureInfo.InvariantCulture,
"<DeviceInfo><OutputFormat>emf</OutputFormat><StartPage>0</StartPage><EndPage>0</EndPage><MarginTop>{0}</MarginTop><MarginLeft>{1}</MarginLeft><MarginRight>{2}</MarginRight><MarginBottom>{3}</MarginBottom><PageHeight>{4}</PageHeight><PageWidth>{5}</PageWidth></DeviceInfo>",
ToInches(margins.Top),
ToInches(margins.Left),
ToInches(margins.Right),
ToInches(margins.Bottom),
ToInches(paperSize.Height),
ToInches(paperSize.Width));
}
private static string ToInches(int hundrethsOfInch)
{
double inches = hundrethsOfInch / 100.0;
return inches.ToString(CultureInfo.InvariantCulture) + "in";
}
}
}
this is the Print button
private void btnPrint_Click_1(object sender, EventArgs e)
{
AutoPrintCls autoprintme = new AutoPrintCls(reportViewer1.LocalReport);
autoprintme.Print();
}
Your btnPrint_Click_1 event can refer to the following code:
private void btnPrint_Click_1(object sender, EventArgs e)
{
AutoPrintCls autoprintme = new AutoPrintCls(reportViewer1.LocalReport);
autoprintme.PrinterSettings.Copies = Convert.ToInt16(numericUpDown1.Value);
autoprintme.Print();
}
I need to return all the peaks and valleys from the data in the csv file. I keep getting an exception when I run the program telling me the string isn't in correct format. I don't know what I'm writing incorrectly. I'm passing the values into testX and testY and then comparing them in my while loop. The while loop is where I'm getting the error when I convert testY to a double.
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;
namespace WindowsFormsApp6
{
public partial class Form1 : Form
{
double firstY = 0.0;
string testX;
string testY;
string[] xpoint = new string[5000];
string[] ypoint = new string[5000];
private void button2_Click(object sender, EventArgs e)
{
Application.Exit();
}
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
using (var reader = new StreamReader(#"D:\data.csv"))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
var values = line.Split(',');
testX = values[0];
testY = values[1];
while (Convert.ToDouble(testY) <= firstY)
{
firstY = Convert.ToDouble(testY);
if (firstY == Convert.ToDouble(testY))
{
break;
}
}
if (Convert.ToDouble(testY) > firstY)
{
listBox1.Items.Add(Convert.ToDouble(testX) + "," + firstY);
}
while (Convert.ToDouble(testY) >= firstY)
{
firstY = Convert.ToDouble(testY);
if (firstY == Convert.ToDouble(testY))
{
break;
}
}
if (Convert.ToDouble(testY) < firstY)
{
listBox2.Items.Add(Convert.ToDouble(testX) + "," + firstY);
}
Convert.ToString(testX);
Convert.ToString(testY);
}
}
}
}
}
i am currently working on a Windows Forms App in c# which will allow the user to add or delete records. when i hit the button to display all the records written to the file the files appear, but when i try to delete by transact number i get an exception saying that "The process cannot access the the because it is being used somewhere else". i have tried putting it in a try-catch block to make sure the reader/writer will close and still not working code will be attached any help is greatly appreciated. p.s im not looking for code to finish this project just help getting by this exception and make it work like it is suppose.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace MMFileIO
{
public partial class MMAssignment3 : Form
{
StreamWriter writer;
StreamReader reader;
string record = "";
public MMAssignment3()
{
InitializeComponent();
}
private void MMAssignment3_Load(object sender, EventArgs e)
{
txtFile.Text = #"c:\burnable\assignment3.txt";
if (!Directory.Exists(txtFile.Text.Substring
(0, txtFile.Text.LastIndexOf('\\'))))
MessageBox.Show("File path does not exist");
}
private void btnAdd_Click(object sender, EventArgs e)
{
try
{
if (radNew.Checked)
writer = new StreamWriter(txtFile.Text, append: false);
else
writer = new StreamWriter(txtFile.Text, append: true);
}
catch(Exception ex)
{
if (writer != null)
writer.Close();
MessageBox.Show($"exception adding new record: {ex.Message}");
return;
}
record = $"{txtTransact.Text}::{txtDate.Text}::{txtSerial.Text}::" +
$"{txtToolPurchased.Text}::${txtPrice.Text}::{txtQty.Text}::" +
$"${txtAmount.Text}";
try
{
writer.WriteLine(record);
lblMessage.Text = ($"Record added");
txtTransact.Text = txtDate.Text = txtSerial.Text =
txtToolPurchased.Text = txtPrice.Text = txtQty.Text =
txtAmount.Text = "";
}
catch(Exception ex)
{
MessageBox.Show($"exception adding a new record: {ex.Message}");
}
finally
{
writer.Close();
}
}
private void btnDelete_Click(object sender, EventArgs e)
{
reader = new StreamReader(txtFile.Text);
List<string> records = new List<string>();
while (! reader.EndOfStream)
{
record = reader.ReadLine();
records.Add(record);
}
if (records.Count == 0)
MessageBox.Show("No records left in file");
reader.Close();
writer = new StreamWriter(txtFile.Text, append: false);
foreach (string item in records)
{
}
}
private void btnCloseFile_Click(object sender, EventArgs e)
{
txtDataDisplay.Text = "";
reader.Close();
}
private void btnDisplay_Click(object sender, EventArgs e)
{
reader = new StreamReader(txtFile.Text);
txtDataDisplay.Text = $"{"#".PadRight(10)}\t" +
$"{"Purchase-Date".PadRight(10)}\t{"Serial #".PadRight(10)}\t" +
$"{"Manufacturing Tools".PadRight(10)}\t{"Price".PadRight(10)}\t" +
$"{"Qty".PadRight(10)}\t{"Amount".PadRight(10)}\n{"".PadRight(50)}\n";
while (!reader.EndOfStream)
{
record = reader.ReadLine();
string[] fields = record.Split(new string[] { "::" }, StringSplitOptions.None);
txtDataDisplay.Text += $"{fields[0].PadRight(10)}\t" +
$"{fields[1].PadRight(10)}\t{fields[2].PadRight(10)}\t" +
$"{fields[3].PadRight(30)}\t{fields[4].PadRight(10)}\t" +
$"{fields[5].PadRight(10)}\t{fields[6].PadRight(10)}\n";
}
reader.Close();
}
I'm looking to take a screenshot from a web page that is streaming from an IP camera and as such doesn't triggerWebBrowserReadyState.Complete.
The webpage in question is literally streaming a mjpeg and the browser is always loading/streaming.
I can generate images for other URLs but cannot guess this to give anything other than 'Navigation Cancelled'.
I have tried WebBrowser.Stop() but to no avail...
The webpage is simply an mJpeg:
<img class"shrink" src="192.168.1.124/Streaming/channels/1/httpPreview"; alt="192.168.1.124/Streaming/channels/1/httpPreview"; class="shrinkToFit" height="148" width="217"> </img>
using Telegram.Bot;
using System.Threading.Tasks;
using System.IO;
using Telegram.Bot.Types;
using System.Threading;
using System.Drawing;
using System.Windows.Forms;
using System.Drawing.Imaging;
namespace Telegram_Alerter
{
public static class BitmapExtensions
{
public static void SaveJPG100(this Bitmap bmp, string filename)
{
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
bmp.Save(filename, GetEncoder(ImageFormat.Jpeg), encoderParameters);
}
public static void SaveJPG100(this Bitmap bmp, Stream stream)
{
var encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
bmp.Save(stream, GetEncoder(ImageFormat.Jpeg), encoderParameters);
}
public static ImageCodecInfo GetEncoder(ImageFormat format)
{
var codecs = ImageCodecInfo.GetImageDecoders();
foreach (var codec in codecs)
{
if (codec.FormatID == format.Guid)
{
return codec;
}
}
// Return
return null;
}
}
class Program
{
static public void Main(string[] args)
{
TelegramMessageAsync().Wait();
}
static public async Task TelegramMessageAsync()
{
TelegramBotClient Bot = new TelegramBotClient("<mykey>");
WebsiteToImage websiteToImage = new WebsiteToImage("http://192.168.1.124/Streaming/channels/1/httpPreview", Application.StartupPath + "file.jpg");
websiteToImage.Generate();
using (FileStream fs = System.IO.File.OpenRead(Application.StartupPath + "file.jpg"))
{
FileToSend fts = new FileToSend();
fts.Content = fs;
fts.Filename = "file.jpg";
await Bot.SendPhotoAsync(<bot>, fts, "message here");
}
}
public class WebsiteToImage
{
private Bitmap m_Bitmap;
private string m_Url;
private string m_FileName = string.Empty;
public WebsiteToImage(string url)
{
// Without file
m_Url = url;
}
public WebsiteToImage(string url, string fileName)
{
// With file
m_Url = url;
m_FileName = fileName;
}
public Bitmap Generate()
{
// Thread
var m_thread = new Thread(_Generate);
m_thread.SetApartmentState(ApartmentState.STA);
m_thread.Start();
m_thread.Join();
return m_Bitmap;
}
private void _Generate()
{
var browser = new WebBrowser { ScrollBarsEnabled = false };
browser.Navigate(m_Url);
browser.DocumentCompleted += WebBrowser_DocumentCompleted;
while (browser.ReadyState != WebBrowserReadyState.Complete)
{
Application.DoEvents();
}
browser.Dispose();
}
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// Capture
var browser = (WebBrowser)sender;
browser.ClientSize = new Size(1024,768);
browser.ScrollBarsEnabled = false;
m_Bitmap = new Bitmap(1024,768);
browser.BringToFront();
browser.DrawToBitmap(m_Bitmap, browser.Bounds);
// Save as file?
if (m_FileName.Length > 0)
{
// Save
m_Bitmap.SaveJPG100(m_FileName);
}
}
}
}
}
Maybe that Page contains Iframes that never load.If yes:
private void WebBrowser_DocumentCompleted(object sender, WebBrowserDocumentCompletedEventArgs e)
{
// to check if it is not Iframe
if (e.Url.AbsolutePath != this.webBrowser.Url.AbsolutePath)
{
// Capture
var browser = (WebBrowser)sender;
browser.ClientSize = new Size(1024,768);
browser.ScrollBarsEnabled = false;
m_Bitmap = new Bitmap(1024,768);
browser.BringToFront();
browser.DrawToBitmap(m_Bitmap, browser.Bounds);
// Save as file?
if (m_FileName.Length > 0)
{
// Save
m_Bitmap.SaveJPG100(m_FileName);
}
}
}
Thanks for the efforts but I answered the question by using an FFMpeg .NET wrapper called N.Reco meaning I did not have to worry about parsing the MJPEG to obtain a single frame and then convert to a JPEG.
This was achieved in two lines of code but FFMPEG does add 20Mb to your application.
var ffmpeg = new NReco.VideoConverter.FFMpegConverter();
ffmpeg.GetVideoThumbnail(pathToVideoFile, Application.StartupPath + stamp);
I have two exceptions here. Not sure why they occur because I use Form.Invoke to run UI updates on the UI thread. So first,
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Xml;
using System.Windows.Forms;
namespace Toplr
{
using System.Collections.Specialized;
using System.Xml.XPath;
using System.Xml.Linq;
using System.Text;
using System.ServiceModel.Web;
using System.ServiceModel.Syndication;
using System.Net;
using System.Web;
using System.Xml.Schema;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
public partial class ToplrForm : Form
{
private readonly Uri SearchBase = new Uri(#"http://www.twine.com/feed/atom/entries/");
private readonly UriTemplate SearchTemplate = new UriTemplate(#"search?type={type}&author={author}");
public ToplrForm()
{
InitializeComponent();
Exiting = false;
TaskContext = new TaskManager();
Items = new AsyncBindingList<Twine>(this);
twineBindingSource.DataSource = Items;
}
private void ToplrForm_Load(object sender, EventArgs e)
{
}
private readonly TaskManager TaskContext;
private readonly AsyncBindingList<Twine> Items;
private bool Exiting;
private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Close()");
Close();
}
private void ToplrForm_FormClosing(object sender, FormClosingEventArgs e)
{
MessageBox.Show("Exiting = tru");
Exiting = true;
//TaskContext.Dispose();
}
private void saveToolStripMenuItem_Click(object sender, EventArgs e)
{
var sfd = new SaveFileDialog()
{
ValidateNames = true
};
if (sfd.ShowDialog() == DialogResult.OK)
{
using (var xtw = new XmlTextWriter(sfd.FileName, Encoding.UTF8))
{
var xw = XmlWriter.Create(xtw);
xw.WriteStartDocument();
xw.WriteStartElement("opml");
xw.WriteAttributeString("version", "1.1");
xw.WriteStartElement("head");
xw.WriteElementString("title", userNameComboBox.Text);
xw.WriteEndElement();
xw.WriteStartElement("body");
foreach (var row in twineDataGridView.SelectedRows)
{
var twine = (Twine)((DataGridViewRow)row).DataBoundItem;
if (twine != null)
{
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "link");
xw.WriteAttributeString("url", twine.HtmlAddress);
xw.WriteStartElement("outline");
xw.WriteAttributeString("text", twine.Title);
xw.WriteAttributeString("type", "atom");
xw.WriteAttributeString("url", twine.AtomAddress);
xw.WriteEndElement();
xw.WriteEndElement();
}
}
xw.WriteEndElement();
xw.WriteEndElement();
xw.WriteEndDocument();
xw.Close();
}
}
}
private void aboutToolStripMenuItem_Click(object sender, EventArgs e)
{
MessageBox.Show("Copyright (C) 2009 Bent Rasmussen");
}
private void accessButton_Click(object sender, EventArgs e)
{
var user = userNameComboBox.Text;
Task.Create(x => ProcessAccount(user));
}
public void ProcessAccount(string user)
{
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = false;
accessButton.Enabled = false;
toolStripStatusLabel1.Text = "Processing...";
}));
var param = new NameValueCollection();
param.Add("type", "Twine");
param.Add("author", user);
var source = SearchTemplate.BindByName(SearchBase, param);
var wc = new WebClient();
using (var feedStream = wc.OpenRead(source))
{
var reader = XmlReader.Create(feedStream);
var feed = SyndicationFeed.Load(reader);
int c = 0, i = 0;
foreach (var item in feed.Items)
{
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
if (item.Links.Count != 0)
{
//try
{
ProcessTwine(item);
i++;
}
//catch (Exception)
{
c++;
}
}
if (Exiting)
break;
}
}
this.Invoke((Action)(() =>
{
userNameComboBox.Enabled = true;
accessButton.Enabled = true;
}));
}
private Twine ProcessTwine(SyndicationItem item)
{
var result = new Twine();
result.Title = item.Title.Text;
result.HtmlAddress = item.Links[0].Uri.ToString();
result.AtomAddress = "";
var wc = new WebClient();
var data = wc.DownloadData(result.HtmlAddress);
var stream = new MemoryStream(data);
var readerSettings = new XmlReaderSettings()
{
ProhibitDtd = false,
ValidationType = ValidationType.None,
ValidationFlags = XmlSchemaValidationFlags.None,
};
var reader = XmlReader.Create(stream, readerSettings);
var doc = XDocument.Load(reader);
var htmlNs = (XNamespace)"http://www.w3.org/1999/xhtml";
var root = doc.Root;
var atom = from r in root.Descendants(htmlNs + "head").Descendants(htmlNs + "link")
where r.Attribute("rel").Value == "alternate" && r.Attribute("type").Value == "application/atom+xml"
select r.Attribute("href");
foreach (var e in atom)
{
if (e.Value != "")
{
result.AtomAddress = e.Value;
this.BeginInvoke((Action)(() =>
{
Items.Add(result);
toolStripProgressBar1.Increment(1);
}));
}
break;
}
return result;
}
}
}
This triggers the exception "Cannot access a disposed object" on this fragment
this.Invoke((Action)(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
}));
If this fragment is commented out, I run into the next problem - a TargetInvocationException on Program level.
The inner exception of this is an InvalidOperationException.
The code is quite simple, so it should not be hard to implement this, I just new a few hints to move on.
Visual Studio project files.
If the user hits the exit button, the Close() method is called, and the UI starts getting torn down. However, your worker code keeps running and attempts to update the UI, which it can no longer do.
If you centralise all those invoke calls:
public void UpdateUI(Action action) {
if(!Exiting) this.Invoke(action);
}
you can call:
UpdateUI(() =>
{
toolStripProgressBar1.Increment(1);
toolStripStatusLabel1.Text = "Processing...";
});
(etc - all the this.Invoke calls should use UpdateUI instead)
and it should work. Also, make Exiting volatile.