# Thursday, 28 October 2010

ASP.NET applications run under an account with limited privileges that doesn’t have the right to connect to a network printer.  The normal answer for this is to give rights to the user running your application or impersonate a user during execution that does have the rights.

We found another way that doesn’t require changing the user or privileges of the existing account that ASP.NET apps run under.

I can hear someone asking “Why would you want to do this anyway?  Can’t the end user choose a printer?”  There might be situations where this isn’t sufficient enough.  We had to control the printer line by line in order to print on the form that is being used and a particular printer had to be used.  

We added the network printer as a printer on the server where our app was running.  When we setup the printer we chose local not networked but then on the options to use a printer port we didn’t use LPT1.  Instead we created a new port with the IP address of the device.  In our code we then call the printer by the name we gave it on our server.

port

printer 

The PrintDocument class in the .NET Framework allows for control of a printer.

VB Version:

Public Class SpecialReportPrintJob 
  Inherits Printing.PrintDocument 
 
Protected Overrides Sub OnBeginPrint(ByVal ev as Printing.PrintEventArgs) 
  MyBase.OnBeginPrint(ev) 
 
  Me.PrinterSettings.PrinterName = "SCLaser2" 
 
  'setup rest of stuff.... 
End Sub   
End Class 
'And we then call it like so 
Dim printSpecialReport as new SpecialReportPrintJob() 
printSpecialReport.Print()
C# Version:
public class SpecialReportPrintJob : Printing.PrintDocument
{

    protected override void OnBeginPrint(Printing.PrintEventArgs ev)
    {
        base.OnBeginPrint(ev);

        this.PrinterSettings.PrinterName = "SCLaser2";

        //setup rest of stuff.... 
    }
}
//And we then call it like so
SpecialReportPrintJob printSpecialReport = new SpecialReportPrintJob();
printSpecialReport.Print();

PrintDocument is pretty powerful.  It can control just about anything for your printer.  We passed in a text file of our data to print and our code setup the x, y coordinates of each item as it related to where on the form it needed to be.

All this without having to muck around with permissions.  Always a good thing!

Happy Coding!

Posted 10.28.2010  #    Comments [0]  | 
# Thursday, 22 April 2010

I recently needed to make a change to some code that had a routine for getting the week currently in.  I needed to add the ability to get the previous / last week relative to this week.  No problem, I would just work off of the existing routine.

Private Sub SetDatesToThisWeek()

  Dim dateStart As String
  Dim dateEnd As String

  Dim dateNow As Date
  dateNow = Now

  dateStart = (Weekday(dateNow, Microsoft.VisualBasic.FirstDayOfWeek.Sunday) - 1).ToString
  dateStart = DateAdd(DateInterval.Day, -CType(dateStart, Double), dateNow).ToString
  dateStart = Format(System.Convert.ToDateTime(dateStart), "MM/dd/yyyy")

  dateEnd = DateAdd(DateInterval.Day, 6, System.Convert.ToDateTime(dateStart)).ToString
  dateEnd = Format(System.Convert.ToDateTime(dateEnd), "MM/dd/yyyy")
 
  Me.StartDate.Text = dateStart
  Me.EndDate.Text = dateEnd
End Sub

It took me a little bit of time to digest the routine and realized I needed to simplify the routine and even though the code is in VB I wanted to remove the dependence on the Microsoft.VisualBasic library as well.  This means getting rid of Weekday, DateAdd, etc and replace with the framework standard.  I love not reinventing the wheel and happened to find a nice pointer on stack overflow.

Private Sub SetDatesToThisWeek()

  Dim thisSunday As Date = DateTime.Now.AddDays(-(DateTime.Now.DayOfWeek - DayOfWeek.Sunday))
  Me.StartDate.Text = Format(thisSunday, "MM/dd/yyyy")
  Me.EndDate.Text = Format(thisSunday.AddDays(6), "MM/dd/yyyy")

End Sub

11 lines of code and three variables down to three lines and one variable with the added benefit of being easier to read, understand and the reliance on Microsoft.VisualBasic gone (at least for this code). Since I needed to create another routine that returns last week I decided as suggested in one of the stack overflow answers to create an extension on the date type.

Imports System.Runtime.CompilerServices

Module DateExtensions

  <Extension()> _
  Public Function StartOfWeek(ByVal aDate As Date, ByVal dayToStartWeek As DayOfWeek) As Date
    Return aDate.AddDays(-(aDate.DayOfWeek - dayToStartWeek))
  End Function
End Module

Now I can use the extension like so:

Private Sub SetDatesToLastWeek()

  Dim lastSunday As Date = DateTime.Now.StartOfWeek(DayOfWeek.Sunday).AddDays(-7)
  Me.StartDate.Text = Format(lastSunday, "MM/dd/yyyy")
  Me.EndDate.Text = Format(lastSunday.AddDays(6), "MM/dd/yyyy")
End Sub

Private Sub SetDatesToThisWeek()

  Dim thisSunday As Date = DateTime.Now.StartOfWeek(DayOfWeek.Sunday)
  Me.StartDate.Text = Format(thisSunday, "MM/dd/yyyy")
  Me.EndDate.Text = Format(thisSunday.AddDays(6), "MM/dd/yyyy")
End Sub
The C# version of the extension is a little different than VB:
namespace Extensions
{
    public static class DateExtension
    {
        public static Date StartOfWeek(this Date aDate, DayOfWeek dayToStartWeek)
        {
            return aDate.AddDays(-(aDate.DayOfWeek - dayToStartWeek));
        }
    }   
}

Leaving code better off than when you started is always a great feeling.

Happy Coding!

P.S. – I also replaced the date formatting strings with a constant. :-)

C# | Programming | VB
Posted 04.22.2010  #    Comments [0]  | 
# Saturday, 27 March 2010

I need to take a CSV file of logins with their emails and verify if these logins exist in our Active Directory.  This can be done several different ways including with powershell but for one reason or another I want/need to do it with .Net.

I will be using an open source library called FileHelpers to make the parsing of the CSV file a snap.  I’m going to skip over the code that uses FileHelpers and focus on the AD lookup.  Check out my previous post on FileHelpers to see how easy FileHelpers makes parsing.

I’m going to use the System.DirectoryServices namespace to lookup AD information.

Let’s look at the AD Lookup class I created to compare the login in the CSV file to AD.

using System;
using System.Collections.Generic;
using System.DirectoryServices;

namespace VerifyUsers
{
    public class ADLookup
    {
        private DirectorySearcher _directoryToSearch;

        public ADLookup()
        {
            DirectoryEntry root = new DirectoryEntry("LDAP://rootDSE");
            string rootName = "LDAP://" + root.Properties["defaultNamingContext"].Value.ToString();
            DirectoryEntry searchRoot = new DirectoryEntry(rootName);
            _directoryToSearch = new DirectorySearcher(searchRoot);
            _directoryToSearch.PageSize = 100;
            _directoryToSearch.SearchScope = SearchScope.Subtree;
            _directoryToSearch.PropertiesToLoad.Add("displayName");
        }

        public bool IsUserInAD(string login)
        {
            _directoryToSearch.Filter = string.Format("(&(sAMAccountName={0})(objectClass=Person))", login);
            SearchResultCollection personFound = _directoryToSearch.FindAll();

            return personFound.Count > 0;
        }
    }
}

I’m using the DirectorySearcher class to look in AD for user information.  In the class constructor I setup the connection information to the LDAP store and set some of the basic properties.

The SearchScope property is important to set to what you need.  I set it to Subtree (which is the default) to have search include the base and it’s children.  If for example, your AD environment has subfolders then you want this set in order to search the subfolders.

In the IsUserInAD method call I setup the query to look for the login name better known as the sAMAccountName in LDAP and I only want it to search Person objects.

Note – If you are creating your own project you will need to add a reference to System.DirectoryServices.

Now let’s get the code running in a console:

using System;
using System.Collections.Generic;

namespace VerifyUsers
{
    class Program
    {
        static void Main(string[] args)
        {
            Parser userParser = new Parser("Users.csv");
            DisplayUsersNotInAD(userParser.Parse());

            Console.ReadLine();
        }

        static void DisplayUsersNotInAD(User[] list)
        {
            ADLookup lookup = new ADLookup();
            foreach (User u in list)
                if (lookup.IsUserInAD(u.login) == false)
                    Console.WriteLine("{0} was not found in AD.", u.login);
        }
    }
}

First, we parse the CSV file using the FileHelpers library.  Then we iterate over the list and display the entries not found in our directory.

The CSV file I am using has three entries and the first two are bogus accounts that don’t exist in AD.  The third entry does.  If the code works correctly we should only have the first two entries reported as not found.

When you run the code you should see:

image

The last entry, kdog, was found in AD.  We can do whatever we need to with the two entries that aren’t in AD.

Download the C# source or VB Source.

Read my previous post on using the open source FileHelpers library to parse CSV files.

Happy Coding!

Posted 03.27.2010  #    Comments [0]  | 
# Saturday, 20 March 2010

Need to parse a text file or perhaps a stream?  Tired of writing parsing code to do this?  Well, for only $19.95….  Ha, ha,  just kidding.  I ran across FileHelpers earlier this week and was impressed.

FileHelpers are a free and easy to use .NET library to import/export data from fixed length or delimited records in files, strings or streams.
The idea is pretty simple:

You can strong type your flat file (fixed or delimited) simply describing a class that maps to each record and later read/write your file as an strong typed .NET array

The Library also has support for import/export data from differents storages like Excel, Access, SqlServer, etc. – Home page of FileHelpers.com

Setting it up and getting started is very easy.  I’ll walk you through a sample.

I have a CSV file with usernames and email addresses in it.  I need to parse that file and I need to verify the information in the CSV against another data store.  I won’t go into verifying to the other data store for this example.

For the purpose of the exercise, create a new C# console project named FileHelpersSample.

Download version 2.0 and reference the FileHelpers library in your project.

Here’s how our CSV looks:

joeuser,joeuser@email.com
awinter,awinter@summer.com
jdoe,jdoe@welcome.org

HINT - If you are following along and creating this project from scratch be sure to create a file named Users.csv with the above entries in it and put it in your debug/release bin folders.

In your project create a new class called User.  This class will be used to map the CSV file.

using System;
using FileHelpers;

namespace FileHelpersSample
{
    [DelimitedRecord(",")]
    public class User
    {
        public string username;
        public string email;
    }
}

Now create a new class and call it Parser.  This class will invoke the FileHelpers engine to parse the file.  It should look like this:

using System;
using System.Collections.Generic;
using FileHelpers;

namespace FileHelpersSample
{
    public class Parser
    {
        private string _filePath;
        public Parser(string filePath)
        {
            _filePath = filePath;
        }

        public User[] Parse()
        {
            FileHelperEngine engine = new FileHelperEngine();
            return engine.ReadFile(_filePath);
        }
    }
}

The FileHelperEngine uses generics to accept the mapping class.  When the ReadFile method is called on the object it uses the mapping to return an array of User objects.

It’s that easy to parse a CSV file.

Now, let’s complete the sample.  Open the Program.cs file and copy the code below:

using System;
using System.Collections.Generic;

namespace FileHelpersSample
{
    class Program
    {
        static void Main(string[] args)
        {
            Parser userParser = new Parser("Users.csv");
            DisplayUsers(userParser.Parse());

            Console.ReadLine(); 
        }

        static void DisplayUsers(User[] list)
        {
            foreach (User u in list)
                Console.WriteLine("{0} {1}", u.username, u.email);   
        }
    }
}

Run the project and you should see:

image 

That was easy! 

The library can do a lot more than this simple example shows.  Be sure to read their quick starts and samples.  The library can ignore the first and last X number of lines as well as empty lines.  It can ignore/process records based on conditions you set along with many other options.  It even has a tool to create your mapping class.

Download this sample in C# or VB.

Happy Coding!

C# | Open Source | Parsing | Programming | VB
Posted 03.20.2010  #    Comments [0]  |