home · blog · groups · about us · contact us
DevelopmentNow Blog
 Tuesday, July 18, 2006
 
 

Instead of using Notepad all the time for viewing random text files, why not check out one of the many replacements mentioned on Rick Strahl's post on Notepad replacements. FWIW I use TextPad, although their menu hotkeys take a little getting used to (F5 for Find??).

July 18, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Thursday, July 13, 2006
 
 

Up to base 36, anyhow. This is a port from old C. I think it works (did it on paper).

// return decimal version of any number up to base 36
// e.g. strtonum("110", 16) returns 272 (which is 110 in base 16)
int strtonum(orig, base)
{
    string digits = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
    int retval = 0;

    for (int i = 0; i < orig.length; i++)
    {
        string character = orig[i];

        for (j = 0; j < digits.length; j++)
        {
            if (character == digits[j])
            {
                retval = retval * base + j;
                break;
            }
        }
    }

    return retval;
}

July 13, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Thursday, July 06, 2006
 
 

FYI, I'll be speaking at Portland Code Camp 2.0 this year, talking about incorporating AJAX functionality into ASP.NET applications. July 22nd & 23rd at WSU's Vancouver campus. It's free for everyone, so go ahead and get registered. Code Camp is a very informal, code-centric (as opposed to yak-centric) conference put on by developers, for developers.

I was tempted to also speak about O/R Mappers & code generators, but I think one presentation is enough this time around. :)

Edit: Code Camp is down to one day, July 22nd. Registration is free & starts at 8am.

July 6, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Wednesday, June 28, 2006
 
 

Overview

The DevelopmentNow Google Calendar Monitor is a simple desktop application that synchronizes with your Google Calendar and pops up hard-to-miss, snoozable reminders for your events. You can also add events to your calendar without having to open a browser.

Installation

To install, just download the zip file, extract it, and run the EXE. Note that you must have the .NET 1.1 runtime installed (you can get it at Windows Update). The software has been tested on Windows XP Pro, SP2, but it should work on any computer that supports .NET 1.1. Note that firewalls will probably block the program. You will need to allow the program to access the internet in order to display your calendar.

General Use

To use, just start it up and go to the Settings panel. Enter your Google Calendar username and password, click Save Settings, and you're off. When you hide the main form, you'll see an icon in your taskbar. You can right-click it for menu options, single-click it for a quick view at today's apopintments, or double-click it to bring the main window back up.

Screenshots

Snoozable reminders pop up above your taskbar as well as in the middle of your screen, making it hard to miss your appointments.


Enter your settings for your Google Calendar


Add events to your Google Calendar


It automatically synchronizes with your online calendar
google calendar

Privacy

Your settings are saved on your local computer and are not sent over the internet except to log into Google Calendar. None of your settings or calendar information are shared with anyone in any way. It's just as safe as if you went to http://calendar.google.com and logged in yourself.

Price / Licensing

The DevelopmentNow Google Calendar Monitor is free. Use it any way you want as long as you don't in any way alter, distribute, or sell it without DevelopmentNow's prior written approval.

Download

Get the Google Calendar Monitor here
June 28, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Tuesday, June 27, 2006
 
 

Ok, so this is funny. A few days ago I blogged about trying in vain to find software that would automatically back up my important files, ignore the ones that havem't changed, and send them to an FTP server. And so I just find out that WinZip 10 Pro will do that, and compress your files, too. And it's $50. Hmmm...

Some teaser screenshots:

Maybe I'll be checking out WinZip after all, and have it just watch my project directories, zip everything up, and upload it to a cheap web host.

June 27, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [1]



 
 

Since I've started using an offsite backup service, I've been feeling better about my disaster recovery ability. However, I wanted to ensure that my files stayed small so that a) they would transfer faster to the offsite backup, and b) so they'd take up less space, which saves me money on storage.

So here's an updated SQL Command Line Backup script (see my previous post for details and the SQL script I used):

@echo off 
REM get today's date and time as one big string
for /f "tokens=2-4 delims=/ " %%i in ( 'date /t') do set theday=%%k%%i%%j
for /f "tokens=1-2 delims=: " %%i in ( 'time /t') do set thetime=%%i%%j
set now=%theday%%thetime%

REM create backup files
C:
cd "\Program Files\Microsoft SQL Server\MSSQL.1\MSSQL\Binn"
sqlcmd -S localhost -U sa -P somepassword -i c:\sqlbackup\backup.sql -o c:\sqlbackup\log.txt

REM compress backup files
gzip -f C:\sqlbackup\*.bak

REM copy backup files to backup device
xcopy "C:\sqlbackup\*.*" \\10.1.10.50\ben_backup\sqlbackup\%now%\ /E /H /R 

The main difference is I'm now using a command line compression utility called gzip to compress the database backups (down to 10-13% of their original size). Gzip is open source, fast, and small. Obviously, you could use other utilities like WinZip's command line utility, or even Windows Services for Unix (with its ironic 230+mb download). But I figured free was good enough for me. You can download a Win32 version of gzip here.

FYI, the 10.1.10.50\ben_backup\ folder is on a local file server with RAID1, so it's relatively stable. But I now also have Mozy watching that folder, too, so everything that gets dumped there gets backed up over the internet.

Hopefully the above has given you some ideas on how to protect your code. By make regular database & source code repository dumps, and backing them up, you'll be in a better position to recover if your computer goes down, or worse.

June 27, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Monday, June 26, 2006
 
 

Just ran across a tool to more easily read log4net files. There's a free single-user version apparently.

log4net Dashboard / Viewer

June 26, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 
 

So you have an ASP.NET application and want to do some custom logging other than by using Response.AppendToLog(). Or maybe you have a console app that you want to log what it's doing. Good! Let's get you set up using log4net (a very popular logging library) in a few minutes so you can start keeping track of things. Much of this is based on Haacked's Quick and Dirty Guide to log4net, which is based on VS2003 but still a good read. I also got some tips for Visual Studio 2005 from Akash's blog. Now let's get started.

Download log4net

Download and extract the latest stable release of log4net here.

Add a reference

In your Visual Studio project, add a reference (Project->Add Reference) to log4net.dll (in the bin\net\<dotnet version>\release directory where you extracted the log4net zip file).

Add a log4net config file

Even though you can add log4net configuration settings to your app's main .config file, we're going to give log4net it's own config file for two reasons: 1) cleanliness, and 2) you can log4net change the config settings on the fly without having to restart the app. :)

So, create a new .config file in the root directory of your application ad name it log4net.config. If you're building a client app, set the "Copy to Output Directory" property to "Copy Always". Remove everything in the log4net.config file, and paste the below XML into it.  It contains sample configurations to log many types of events (info, warning, error, fatal) to a rolling set of log files in a "log4net" subdirectory in your application's root directory. It will also send emails for any error or fatal events. You'll at least want to change the Smtp settings to a valid host & email account.

<?xml version="1.0"?>
<log4net>
    <appender name="SmtpAppender" type="log4net.Appender.SmtpAppender">
        <to value="support@yourcompany.com" />
        <from value="support@yourcompany.com" />
        <subject value="ERROR on site" />
        <smtpHost value="your.smtp.host" />
        <bufferSize value="256" />
        <lossy value="true" />
        <evaluator type="log4net.spi.LevelEvaluator">
            <threshold value="ERROR" />
        </evaluator>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-5p %d [ThreadId: %t] Class:%c{1} Method:%M %nMESSAGE:%n%m%n%n" />
        </layout>
    </appender>
    <appender name="RollingLogFileAppender" type="log4net.Appender.RollingFileAppender">
        <file value="log4net\\logfile.txt" />
        <appendToFile value="true" />
        <datePattern value="yyyyMMdd" />
        <rollingStyle value="Date" />
        <filter type="log4net.Filter.LevelRangeFilter">
            <acceptOnMatch value="true" />
            <levelMin value="INFO" />
            <levelMax value="FATAL" />
        </filter>
        <layout type="log4net.Layout.PatternLayout">
            <conversionPattern value="%-5p %d %5rms %-22.22c{1} %-18.18M - %m%n" />
        </layout>
    </appender>
    <root>
        <level value="DEBUG" />
        <appender-ref ref="SmtpAppender" />
        <appender-ref ref="RollingLogFileAppender" />
    </root>
</log4net>

Initialize the configuration

If you're using a web application, add the following line to your Application_Start method in global.asax.

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo(Server.MapPath("log4net.config")));

If you're using a client application (e.g. a console app), add the following line to your app's initialization routine:

log4net.Config.XmlConfigurator.ConfigureAndWatch(new System.IO.FileInfo("log4net.config"));

These lines tell log4net to load configuration information from the local log4net.config file and watch it for any configuration changes while the app is running.

Start logging

Now wherever you want to log some information in a particular class, add a member variable like this

private log4net.ILog logger = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);

This creates a logger variable, and causes log messages to be prefixed with the class name containing the logger variable. That makes it easier to sift through logs, since you'll be able to see which messages came from which classes.

Then when you want to do some logging you can just use statements like this

logger.Info("some info");
logger.Warn("a stern warning!")
logger.Error("An error occurred!");

Reading the logs

The sample config (above) creates a log file named logfile.txt in a log4net subdirectory inside your application's root directory. Note that for client applications, that'll be your bin/debug or bin/release folders (or wherever the EXE lives). Since we used a RollingLogAppender, older logs will be archived with the date apprended to the file name. That means that "logfile.txt" only contains messages for the current day.

Deploying your app

When you deploy your application, make sure to deploy the log4net.dll, log4net.xml, and log4net.config files. Also make sure that your application's account (e.g. the ASPNET account for web apps, or the user for client apps) can create and write to the "log4net" subdirectory. For web applications you may want to go ahead and create the "log4net" subdirectory up front and assign ASPNET full control rights to that.

Tweaking the configuration

You can tweak the settings in your log4net.config at any time, even while the app is running. You may wish to change the location of the log file, or add different appenders, or change what type of messages get logged. I suggest reading the log4net documentation for more information.

 

 

 

June 26, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Sunday, June 25, 2006
 
 

In order to work on the largest user base possible (who often are behind routers and firewalls), Skype will listen on port 80 and prevent IIS (and other services) from using it. That may cause some minutes of frustration as your IIS stops working, Visual Studio won't bind to the local web server, and you repeatedly click "Start" in IIS Manager to no effect.

To put Skype in its place and make it stay away from port 80 for good, open up Skype and go to Tools->Options, General, click "Set connection parameters and proxies", and uncheck "Use port 80 & 443 as alternatives for incoming connections." Then restart Skype. That should allow IIS to use port 80 as it needs to.

However, if Skype then stops working for you, you may need to open up a port in your router. You'll find the port that Skype's using on the same options page where you unchecked "use port 80...".

June 25, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Friday, June 23, 2006
 
 

Google recently released an API for Google Calendar. Even though the Google Calendar UI is already pretty slick, developers can now write applications to extend the functionality further. C# and Java versions of the API are available.

For example, you can query your upcoming events in C# like so:

  1. First download & install the libraries. You may need to build them first.
  2. Make a new project and reference GData.dll, GDataExtensions.dll, and CalendarService.dll
  3. Use code kinda like the below :)


using System;
using System.IO;
using System.Xml;
using System.Net;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Calendar;

namespace ConsoleApplication1
{
    class Class1
    {
        [STAThread]
        static void Main(string[] args)
        {
            string calendarURL = "http://www.google.com/calendar/feeds/default/private/full";
            string appName = "MyCompany-MyApp-v1.0";
            string userName = "you@someisp.com";    // google calendar login
            string password = "somepassword"; // google calendar password

            // create a query object
            // get 10 entries that start between now & the next 10 days
            EventQuery query = new EventQuery();
            query.Uri = new Uri(calendarURL);
            query.NumberToRetrieve = 10;
            query.StartTime = System.DateTime.Now;
            query.EndTime = System.DateTime.Today.AddDays(10);

            // connect to the calendar service
            CalendarService service = new CalendarService(appName);
            service.setUserCredentials(userName, password);

            // execute the query & get the results back
            EventFeed calFeed = service.Query(query);

            // iterate through the results
            foreach (EventEntry feedEntry in calFeed.Entries)
            {
                string eventStartDesc = "n/a";
                string eventWhereDesc = "n/a";
                
                if (feedEntry.Times.Count > 0)
                {
                    When eventStart = feedEntry.Times[0];
                    if (eventStart.AllDay)
                        eventStartDesc = "All day";
                    else if (eventStart.StartTime.Date == System.DateTime.Today.Date)
                        eventStartDesc = "Today at " + eventStart.StartTime.ToShortTimeString();
                    else
                        eventStartDesc = eventStart.StartTime.ToString();
                }

                if (feedEntry.Locations.Count > 0)
                {
                    Where where = feedEntry.Locations[0];
                    if (where.ValueString != null || where.Label != null)
                        eventWhereDesc = where.Rel + " " + where.Label + " " + where.ValueString;
                }

                Console.WriteLine("Event:");
                Console.WriteLine("\tTitle: " + feedEntry.Title.Text);
                Console.WriteLine("\tWhen: " + eventStartDesc);
                Console.WriteLine("\tWhere: " + eventWhereDesc);

            }
        }
    }
}


As you can see, it's pretty easy. Note that you should change the username & password information at the top, and make sure you have some upcoming events in your calendar.

You can also download a sample .NET 1.1 project here.

June 23, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Thursday, June 22, 2006
 
 

Saw this SQL Login Killer Script on SQL Server Central (yes I know it's old, but it's still good) ...

Handy when you need to kill everyone off in order to perform a restore. I even use it on my dev workstation, since IIS, ColdFusion, & a million other things like to hang on.

Although, I wonder if SQL Server 2005 has an easier way to boot everyone off. Hmm.

June 22, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [0]



 Monday, June 19, 2006
 
 

So I spent several hours last week doing some research on remote backups. Even though I have a file server here for local backups, something could always happen -- fire, flood, crazy electrical storm, theft, etc -- that could cause me to lose files or data from every machine in the building.

What I wanted was something simple: make it automatically back up certain files and folders on my computer, start up when Windows starts, run in the background (when idle or on a schedule), and back up changed files only. I did not want to manually click some "Backup" button all the day -- I needed "set & forget" behavior. And I was even willing to pay!

I started by reading reviews of storage providers on PC World and TechCrunch. After some more research, I signed up for a small GoDaddy Online File Folder since that got some kudos. Verdict: bleh! Would have been nice to learn about it before shelling out my $10, but oh well. Their web interface is slow. The backup software can only automatically back up one folder on your PC. One? If you want to back up multiple folders, you instead have to find a third party app and over it over FTP or WebDAV. WebDAV is slow, and their FTP service was giving me weird errors. I spent a few hours trying out third party software and eventually gave up.

I then looked at Box.net, a Web 2.0 darling. However, it didn't have any backup software -- I'd have to log into their site & drag files onto it every time I wanted to back something up. Forget that, guys. I started seeing a trend with other online storage services, too -- it was like they didn't really focus on backing up files, and instead made cool-looking web sites that made it easy to share your MP3 collection with your friends. Like we don't know how file sharing companies eventually turn out. Granted, I can see how sharing might fit in, since people will want to back up their photos, and why not share them with friends and let them print copies etc. But anyhow.

Finally I tried out Mozy, which thankfully fit the bill. Easy to install, 2gb storage for free, with a little app that rests on your computer and automatically backs up what you want when you want. They even encrypt your files before uploading, which is neat. You can upgrade to 30gb of storage for about $5/month. Two additional things I'd like to see out of Mozy, though: 1) offer a business-grade plan for 100+gb storage; and 2) compress the files (or at least compressible ones like BMP/TXT/.CS) before uploading so we can store more stuff and use less bandwidth.

So for now I'm trying out Mozy...we'll see how that goes. If anyone knows of third-party software that does automatic, differential backups over FTP, please let me know! I was tempted to write my own, but you know how that goes. 

June 19, 2006    Bookmark to Digg or other social bookmarking
#    Disclaimer  |  Comments [2]