Massoud Mazar's Blog

Sharing The Knowledge

About the author

Massoud Mazar has been doing .net development since 2002. He is founder and president of Evolynx, Inc.
E-mail me Send mail

Recent comments

Don't show

Authors

Disclaimer

The opinions expressed herein are my own personal opinions and do not represent my employer's view in anyway.

© Copyright 2008

Preconfigured slim PC With Subversion as an Appliance

I've been using Subversion at work for some time and found it an awesome version control tool, so I decided to use it at home for my personal projects. Being a Microsoft oriented developer, I did not want to install Linux on my home PC. I tested some different hardware and software configurations to build a Linux based Subversion machine. I ended up with a small form factor (Mini-ITX) machine which only consumes 24 watts of power when turned on but is pretty powerful. Here is the configuration:

CPU: Intel Atom 1.6 GHz (Hyper-threaded)

RAM: 512 MB DDR2-667 MHz

Disk: 160 GB 2.5 inch SATA Hard Drive

CD Drive: Teac slim 24X CD-ROM drive

OS: Ubuntu Server 8.04

This has worked out really well for me and I'm willing to build similar boxes for anyone else who is interested.

 

 

 

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Subversion
Posted by Mazar on Sunday, June 22, 2008 3:05 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Outlook add-in to select "From Account"

If you have setup more than one email account in your Outlook (Work and Home) you may have realized a need for some type of pop-up dialog which will ask you which account you want to use when creating a new email. Outlook lets you define a default account, but obviously that's not good enough. I decided to write a small and simple add-in which will ask me to select the sending account every time I compose a new email. (Even if Outlook already has such a tool, I couldn't find it! and I wanted to gain some Office programming knowledge anyways.)

I used Visual Studio 2008 and created a new Office project of type Outlook Add-in. This will give you the basics you need. Just fill the methods with your code and you are done.

    public partial class ThisAddIn
    {
        private Outlook.Inspectors Inspectors;

        private void ThisAddIn_Startup(object sender, System.EventArgs e)
        {
            Inspectors = this.Application.Inspectors;
            Inspectors.NewInspector += new Microsoft.Office.Interop.Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);

            foreach (Outlook.Inspector inspector in Inspectors)
            {
                Inspectors_NewInspector(inspector);
            }
        }

        void Inspectors_NewInspector(Microsoft.Office.Interop.Outlook.Inspector Inspector)
        {
            if (Inspector.CurrentItem is Outlook.MailItem)
            {
                Outlook.MailItem item = (Outlook.MailItem)Inspector.CurrentItem;
                if (string.IsNullOrEmpty(item.Body) && string.IsNullOrEmpty(item.Subject) && string.IsNullOrEmpty(item.To))
                {
                    Outlook.MailItem ThisItem = (Outlook.MailItem)Inspector.CurrentItem;
                    Accounts accForm = new Accounts();
                    System.Windows.Forms.ComboBox cboAccounts = (System.Windows.Forms.ComboBox)accForm.Controls["cboAccounts"];
                    foreach (Outlook.Account account in this.Application.Session.Accounts)
                    {
                        cboAccounts.Items.Add(account.DisplayName);
                    }
                    cboAccounts.SelectedIndex = 0;
                    accForm.ShowDialog();
                    ThisItem.SendUsingAccount = this.Application.Session.Accounts[cboAccounts.SelectedIndex + 1];
                }
            }
        }

        private void ThisAddIn_Shutdown(object sender, System.EventArgs e)
        {
            Inspectors.NewInspector -= new Outlook.InspectorsEvents_NewInspectorEventHandler(Inspectors_NewInspector);
            Inspectors = null;
        }

        #region VSTO generated code

        /// <summary>
        /// Required method for Designer support - do not modify
        /// the contents of this method with the code editor.
        /// </summary>
        private void InternalStartup()
        {
            this.Startup += new System.EventHandler(ThisAddIn_Startup);
            this.Shutdown += new System.EventHandler(ThisAddIn_Shutdown);
        }
       
        #endregion
    }

 

Accounts() is a Windows Form which only contains a dropdown and a button:

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: Outlook add-in
Posted by Mazar on Monday, June 16, 2008 8:56 AM
Permalink | Comments (0) | Post RSSRSS comment feed

Code sample for using iTextSharp PDF library

iTextSharp is a rich code library to create PDF and RTF output. Recently I decided to use it for a client and realized there are not much good code examples available on the internet. Even some of the code samples from its online tutorial wont run.

By doing a lot of try and error and with some help from other posts, I could get the desired output. It took me too much time to gather all this information and thought it may come handy to others. So I put together a sample web application which creates a PDF document and renders it to the client browser. Here is the code behind for the page:

 

    public partial class _Default : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {
            SendOutPDF(new CustomReports().CreatePDF("Title: Sample 1"));
        }

        /// <summary>
        /// Sends a Stream of bytes to Client as a PDF file
        /// </summary>
        /// <param name="PDFData">Stream containing bytes</param>
        protected void SendOutPDF(System.IO.MemoryStream PDFData)
        {
            // Clear response content & headers
            Response.Clear();
            Response.ClearContent();
            Response.ClearHeaders();
            Response.ContentType = "application/pdf";
            Response.Charset = string.Empty;
            Response.Cache.SetCacheability(System.Web.HttpCacheability.Public);
            Response.AddHeader("Content-Disposition",
                "attachment; filename=" + Title.Replace(" ", "").Replace(":", "-") + ".pdf");

            Response.OutputStream.Write(PDFData.GetBuffer(), 0, PDFData.GetBuffer().Length);
            Response.OutputStream.Flush();
            Response.OutputStream.Close();
            Response.End();
        }

    }

 

The MemoryStream is generated by calling the CreatePDF() method in my CustomReports class. It's a very simple report of 30 lines of text, divided into 2 groups. A bookmark is created for each group to simplify navigation in large reports. It has custom multiline header and custom footer displaying "Page X of Y".

 

using System;
using System.IO;
using System.Data;
using System.Collections.Generic;
using System.Text;

using iTextSharp.text;
using iTextSharp.text.html.simpleparser;
using iTextSharp.text.pdf;

namespace PDF_Tests
{
    public class CustomReports
    {

        public MemoryStream CreatePDF(string Title)
        {
            MemoryStream PDFData = new MemoryStream();
            Document document = new Document(PageSize.LETTER, 50, 50, 80, 50);
            PdfWriter PDFWriter = PdfWriter.GetInstance(document, PDFData);
            PDFWriter.ViewerPreferences = PdfWriter.PageModeUseOutlines;

            // Our custom Header and Footer is done using Event Handler
            TwoColumnHeaderFooter PageEventHandler = new TwoColumnHeaderFooter();
            PDFWriter.PageEvent = PageEventHandler;

            // Define the page header
            PageEventHandler.Title = Title;
            PageEventHandler.HeaderFont = FontFactory.GetFont(BaseFont.COURIER_BOLD, 10, Font.BOLD);
            PageEventHandler.HeaderLeft = "Group";
            PageEventHandler.HeaderRight = "1";

            document.Open();

            for (int i = 1; i <= 2; i++)
            {
                // Define the page header
                PageEventHandler.HeaderRight = i.ToString();

                if (i != 1)
                {
                    document.NewPage();
                }

                // New outline must be created after the page is added
                AddOutline(PDFWriter, "Group " + i.ToString(), document.PageSize.Height);

                for (int j = 1; j <= 30; j++)
                {
                    Table ItemTable = new Table(2);
                    ItemTable.TableFitsPage = true;
                    ItemTable.Width = 95;
                    ItemTable.Offset = 0;
                    ItemTable.Border = 0;
                    ItemTable.DefaultCellBorder = 0;
                    ItemTable.AddCell(new Cell(string.Format("blah blah {0} - {1} ...", i, j)));
                    document.Add(ItemTable);
                    document.Add(new Paragraph("\r\n"));
                }

            }

            document.Close();

            return PDFData;
        }

        public void AddOutline(PdfWriter writer, string Title, float Position)
        {
            PdfDestination destination = new PdfDestination(PdfDestination.FITH, Position);
            PdfOutline outline = new PdfOutline(writer.DirectContent.RootOutline, destination, Title);
            writer.DirectContent.AddOutline(outline, "Name = " + Title);
        }
    }
}

 

Header and footer are created using a PageEventHandler class:

 

using System;
using System.Collections.Generic;
using System.Text;

using iTextSharp.text.pdf;
using iTextSharp.text;

namespace PDF_Tests
{
    public class TwoColumnHeaderFooter :PdfPageEventHelper
    {
        // This is the contentbyte object of the writer
        PdfContentByte cb;

        // we will put the final number of pages in a template
        PdfTemplate template;

        // this is the BaseFont we are going to use for the header / footer
        BaseFont bf = null;

        // This keeps track of the creation time
        DateTime PrintTime = DateTime.Now;

        #region Properties
        private string _Title;
        public string Title
        {
            get { return _Title; }
            set { _Title = value; }
        }
       
        private string _HeaderLeft;
        public string HeaderLeft
        {
            get { return _HeaderLeft; }
            set { _HeaderLeft = value; }
        }

        private string _HeaderRight;
        public string HeaderRight
        {
            get { return _HeaderRight; }
            set { _HeaderRight = value; }
        }

        private Font _HeaderFont;
        public Font HeaderFont
        {
            get { return _HeaderFont; }
            set { _HeaderFont = value; }
        }

        private Font _FooterFont;
        public Font FooterFont
        {
            get { return _FooterFont; }
            set { _FooterFont = value; }
        }
        #endregion

        // we override the onOpenDocument method
        public override void OnOpenDocument(PdfWriter writer, Document document)
        {
            try
            {
                PrintTime = DateTime.Now;
                bf = BaseFont.CreateFont(BaseFont.HELVETICA, BaseFont.CP1252, BaseFont.NOT_EMBEDDED);
                cb = writer.DirectContent;
                template = cb.CreateTemplate(50, 50);
            }
            catch (DocumentException de)
            {
            }
            catch (System.IO.IOException ioe)
            {
            }
        }
       
        public override void OnStartPage(PdfWriter writer, Document document)
        {
            base.OnStartPage(writer, document);

            Rectangle pageSize = document.PageSize;

            if (Title != string.Empty)
            {
                cb.BeginText();
                cb.SetFontAndSize(bf, 15);
                cb.SetRGBColorFill(50, 50, 200);
                cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetTop(40));
                cb.ShowText(Title);
                cb.EndText();
            }

            if (HeaderLeft + HeaderRight != string.Empty)
            {
                PdfPTable HeaderTable = new PdfPTable(2);
                HeaderTable.DefaultCell.VerticalAlignment = Element.ALIGN_MIDDLE;
                HeaderTable.TotalWidth = pageSize.Width - 80;
                HeaderTable.SetWidthPercentage(new float[] { 45, 45 }, pageSize);
               
                PdfPCell HeaderLeftCell = new PdfPCell(new Phrase(8, HeaderLeft, HeaderFont));
                HeaderLeftCell.Padding = 5;
                HeaderLeftCell.PaddingBottom = 8;
                HeaderLeftCell.BorderWidthRight = 0;
                HeaderTable.AddCell(HeaderLeftCell);

                PdfPCell HeaderRightCell = new PdfPCell(new Phrase(8, HeaderRight, HeaderFont));
                HeaderRightCell.HorizontalAlignment = PdfPCell.ALIGN_RIGHT;
                HeaderRightCell.Padding = 5;
                HeaderRightCell.PaddingBottom = 8;
                HeaderRightCell.BorderWidthLeft = 0;
                HeaderTable.AddCell(HeaderRightCell);

                cb.SetRGBColorFill(0, 0, 0);
                HeaderTable.WriteSelectedRows(0, -1, pageSize.GetLeft(40), pageSize.GetTop(50), cb);
            }
        }

        public override void OnEndPage(PdfWriter writer, Document document)
        {
            base.OnEndPage(writer, document);

            int pageN = writer.PageNumber;
            String text = "Page " + pageN + " of ";
            float len = bf.GetWidthPoint(text, 8);

            Rectangle pageSize = document.PageSize;

            cb.SetRGBColorFill(100, 100, 100);

            cb.BeginText();
            cb.SetFontAndSize(bf, 8);
            cb.SetTextMatrix(pageSize.GetLeft(40), pageSize.GetBottom(30));
            cb.ShowText(text);
            cb.EndText();

            cb.AddTemplate(template, pageSize.GetLeft(40) + len, pageSize.GetBottom(30));
           
            cb.BeginText();
            cb.SetFontAndSize(bf, 8);
            cb.ShowTextAligned(PdfContentByte.ALIGN_RIGHT,
                "Printed On " + PrintTime.ToString(),
                pageSize.GetRight(40),
                pageSize.GetBottom(30), 0);
            cb.EndText();
        }

        public override void OnCloseDocument(PdfWriter writer, Document document)
        {
            base.OnCloseDocument(writer, document);

            template.BeginText();
            template.SetFontAndSize(bf, 8);
            template.SetTextMatrix(0, 0);
            template.ShowText("" + (writer.PageNumber - 1));
            template.EndText();
        }

    }
}

 

Currently rated 3.7 by 3 people

  • Currently 3.666667/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: PDF | iTextSharp
Posted by Mazar on Wednesday, April 30, 2008 12:24 PM
Permalink | Comments (0) | Post RSSRSS comment feed

formatting C# code in your BlogEngine.net blogs

I thought this may save someone a little time:

If using BlogEngine.net as your blogging tool, you can format your code using one of the extensions which comes with the tool.

some of the things to remember:

1- first create an opening and closing [code] tag surrounding some zzz characters. Simply type the characters in the editor, all lower case, and make sure to press "ENTER" after each line:

[ code:c#]

zzz

[ /code]

(ignore the space I added after the opening brackets)

2- Do not copy your code directly from Visual Studio. Copy it first to Notepad, then copy from Notepad to replace "zzz". Make sure it only replaces the 3 z characters, not the linefeed after them.

And that's it. BlogEngine.net extension formats your code beautifully.

 

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: blogging
Posted by Mazar on Saturday, April 26, 2008 1:51 PM
Permalink | Comments (0) | Post RSSRSS comment feed

serviceInstaller component and its default EventLogInstaller

While working on a Windows Service project in .net (Visual Studio 2008), a minor problem related to defining custom event logs kept bugging me.

As you already know, to debug your Windows Service you should use InstallUtil tool to install the service in your Windows. For InstallUtil to be able to install your Service, you add an Installer to your project which contains a ServiceProcessInstaller and a ServiceInstaller. So far everything is cool. You set the properties on these components and BAM! you can now easily install your Service. If you look closely at the IinstallUtil messages on your screen you will see that it creates an EventLog source with the same name you specify for the Service Name property of the ServiceInstaller component and assigns that source to a standard Windows event log called Application.

According to MSDN, "Applications and services should write to the Application log or a custom log. Device drivers should write to the System log.". I wanted to create a separate log for my Windows Service and not use the Windows Application log. There may be multiple ways to do this but the suggested approach is to create the Event Source and related Log during the installation of your application. In case of a Windows Service, ServiceInstaller is designed to do this for you by creating an event source for your Windows Service and assigning it to the Application log.

But what if you want to use a log other than Application log? that's easy too. You can check for the event source each time your Service is instantiated and if it does not exist, create the source and the log, similar to what is suggested here, or use EventLogInstaller class to create the log and the source at the time your service is being installed. The second approach seems to be more appropriate because it creates the log at installation time and removes it when you uninstall the service.

So I went ahead and used the EventLogInstaller class:

 

namespace MyService
{
    [RunInstaller(true)]
    public partial class CustomEventLogInstaller : Installer
    {
        private EventLogInstaller customEventLogInstaller;

        public CustomEventLogInstaller()
        {
            InitializeComponent();

            customEventLogInstaller = new EventLogInstaller();
            customEventLogInstaller.Source = "My Service";
            customEventLogInstaller.Log = "My Service Events";
            Installers.Add(customEventLogInstaller);
        }

        public static void Main()
        {
        }

    }
}

 

Interestingly, ServiceInstaller was still creating its default source and assigning it to the Application log before my EventLogInstaller creates the source and installation would fail because the Event Source already existed. I could just use a different name for my event source and let ServiceInstaller create its own source, but the idea kept bugging me. So I decided to prevent the ServiceInstaller from creating its default source.

After spending a good deal of time, I finally got it working the way i wanted it. The trick is to find the unwanted instance of the EventLogInstaller in the Installers property of the ServiceInstaller and remove it. This must be done in the constructor method of the ProjectInstaller:

 

namespace MyService
{
    [RunInstaller(true)]
    public partial class ProjectInstaller : Installer
    {
        public ProjectInstaller()
        {
            InitializeComponent();

            // Remove the default Event Log Installer
            EventLogInstaller DefaultInstaller = null;
            foreach (Installer installer in serviceInstaller1.Installers)
            {
                if (installer is EventLogInstaller)
                {
                    DefaultInstaller = (EventLogInstaller)installer;
                    break;
                }
            }
            if (DefaultInstaller != null)
            {
                serviceInstaller1.Installers.Remove(DefaultInstaller);
            }

        }
    }
}

 

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Posted by Mazar on Friday, April 25, 2008 1:22 PM
Permalink | Comments (0) | Post RSSRSS comment feed

Welcome to my new blog

I know it's way past due, but i finally decided to spend the time and get this blog software setup on my site.


When I started the MazSoft.com web site (early 1999), my idea was to have a web site to share my ideas and knowledge. At that time the concept of blogging was not as popular as it is now, and obviously there was no pre-existing software for it, so I started with some simple static HTML files. After I got more involved with creating web application using classic ASP, I converted my site to an ASP web site so I re-use parts of the UI, and that was it. So, MasSoft.com is still a Classic ASP site for now, until I find the time to move all my previous articles to this new blog.

But before I move old contents to this new system, I may start with some new articles.

Stay tuned...

Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5

Categories: General
Posted by Mazar on Friday, April 25, 2008 1:02 PM
Permalink | Comments (0) | Post RSSRSS comment feed