Tag Archives: Development - Page 2

SQLScripter

I’ve been wanting to creating something like this for myself for a while. A simple tool to quickly create a backup copy of a SQL Server database ‘structure’ (or schema if you will). It is really a simple command line tool that simply takes a few parameters like server\instance name, database, output directory and a prefix name for the output files.

It creates separate files for Tables, Views and Stored procedures (which includes UDFs)

Example usage:

SQLScripter.exe <-s:server> <-d:database> [-od:outputDirectory] [-p:prefixFileName]

Grab it here (plain exe in a zip file). It make use of the .Net 4.0 client framework.

Event Scavenger 5

A quick heads up about a new version of my Event Scavenger tool/system that is coming. There are a whole lot of changes that build up on the existing functionality as far as the gathering service(s) and Administration are concerned. The Viewer part has (so far) being left unchanged so that a previous version Viewer tool can still access the new version database and Vice Versa.

Why things have changed?

The reasons for the update is simple to cater for some limitations I experienced myself with the tool/system. These include the following:

– Newly added Event Logs required a service restart so the gathering service (Event Scavenger service) could become aware of them.

– The original (Event Scavenger) service kept ‘open’ threads for each machine/log that needed to be ‘polled’. Most of the time each thread was left in a ‘sleeping’ state doing no work at all and just taking up resources.

– Only one instance of the collecting (Event Scavenger) service could run on a single machine – thus limiting it to only one database it can store logs into, one service that could be managed etc.

– Logs polled/imported into another database were set up ‘sort of’ separately from actual (machine)logs already in the current database. This made them (sort of) hard to managed.

– Setting up permissions for users was mostly a manual process.

Changes

To solve these issues the following changes have been made:

– The gathering service now spawn threads only for enabled machine/logs each time it ‘runs’ based on a master frequency. This is set to 60 seconds by default (but as always can be changed and now managed from the Admin tool itself). This solves both the 1st and 2nd points mentioned. A side effect is that the performance counters for each Machine/Log now have disappeared (may be a bad thing…). This also means the whole concept of Thread recycling have gone the way of the Dodo…

– The service is now ‘Multi instance’ aware so that multiple copies of the same service (each with its own physical copy of the exe and config file) can run separately ‘servicing’ different Event Logs/databases etc on the same machine. Each instance can thus operate totally independent doing totally its own thing. Multi-machine instances are still possible as before. To set up  a new ‘instance’ you simple make a copy of the service exe & config file (plus editing) and then use the “-install ‘<serviceName>’ ‘<displayName>’ ‘<Description>’ ” parameters on the service exe. The result is a separate entry in Service Manager which you can start/stop on its own.

– A Machine/Log entry now has another (sorta) state other than just be enabled/disabled. The 3rd ‘state’ is the option to have it being imported from another EventScavenger database. Using the Admin tool now makes it a lot easier to manage this.

– The Admin tool now has a simplistic view/editor to manage users in the database.

– The Admin tool also now provides a way to ‘manage’ the collectors (services). A simplistic way to stop/start/pause/continue services is built right into the tool.

– To set up the database is now a bit easier. I included a new (command-line) tool that simply runs the various sql scripts for you. Some editing of the scripts might still be required if you don’t like the default settings). You can always still do it manually.

[Update]

– Something new, the admin tool now has a simplistic way to manage ‘Reaper’ services so you can start/stop/pause services, manage a view of what physical services service what Collector name etc. At the moment the actual registration of a service is still a manual process but the admin tool shows you a help screen with instructions on how to set it up (or even unregister it).

New name

Because the ‘main’ service for collecting Event Logs changed I decided to give it a new name as well – Event Reaper (being a fan of the Mass Effect games must be obvious by now… 😉 ).  The name ‘Event Scavenger’ is now just a global name for the whole project/tool set. With the new multi instance support this means you can have multiple reapers (on the same box).

Source code

So far I’ve kept the changed source code ‘offline’ as it is now a totally new ‘branch’ of the original source code. The global version number has now being changed to 5 (and in fact – the default database name has now being changed to EventScavenger5) as it is not compatible with the previous version (with the exception of the viewer tool that works on both versions – for now…). Thus, previous version collector services and the Admin tool will not work anymore with the new database version – per design.

Release

I’m still in testing so no actual ‘Release’ has been made yet. I’ll post an update here when here is something that others can start playing with.

Update: A preview (Beta) can be found here. It is (should be) fully functional with all the above mentioned features already working.

VS2012 Express for Desktop

I’ve been waiting for this for a while so I was glad when they finally released this. Now for some initial feedback.

First off, the download was reasonable – size and speed wise. The installation was, lets just say ok – as I had to reboot since it had to update some libraries that were is ‘use’ at the time. Registration was also not too bad – since I have an old existing Hotmail/Live account where more of the details were already populated. Running it for the first time is where the shock comes in… it is as ugly as hell (reminds me death, all grey and boring). Unfortunately the same would apply to any of the other Express and even full versions of VS2012.

VS2012 Express For Desktop development

Functionality wise it provides just the very basics – not that you can expect anything more. Since I haven’t installed the ‘full’ express version I cannot comment on any other functionality that version might have. Anyway, The only templates worth mentioning is the Windows Forms, WPF and Console ones. Again, one cannot expect anything more of this release. Interestingly enough, when creating a new project the framework version cannot be changed on the ‘create project’ dialog screen. You can only change this ‘after’ the project has already been created.

One nice thing is that you can still create custom toolbars with ‘external’ commands – I use it to run a source backup tool I created some time ago. Another thing to remember is that this tool can be installed in Windows 7, unlike the full Express version that can ONLY be installed on Windows 8. The Web express version can also be installed on 7 (plus the TFS Express version).

If you excuse the way it looks (wearing shades to protect your eyes) then this tool is not that bad… Just wish they allowed old fashioned ‘themes’ to change the look and feel of the entire editor. Ah well, it is an ‘Express’ product… Fortunately you can import your VS 2010 color and font settings to get all your customizations back (even though it does moan about a whole bunch of settings that are not applicable to this edition which you can ignore)

In order to try it out you can follow this link.

Update:
If you like to change the overall theme and don’t like the built-in Light or Dark there are some more options if you look at this blog entry.

Windows Command Centre

A few years ago I created a quick utility to simply bring together all the various configuration tools that are included inside Windows itself. The problem is that there are actually all these built-in tools and utilities but finding them sometimes require you to search or discover them by accident. The tool I created simply provides an easy way to get to a lot of them. Even in Windows 7 not everything is located in one place – especially the more ‘advanced’, older or legacy tools – e.g. ODBC settings. Additionally I added something simple to simply ‘list’ the installed .Net versions as well.

A quick summary of what it contains:

System

Control panel
Manage computer
System config
Registry editor
Performance monitor
Scheduled tasks
Locale

Regional settings
Date and time

.Net

List versions
Disable Explorer GAC view

Hardware

Device manager
Install hardware
Remove hardware
Power options
Disk management
Removable storage
Settings

Keyboard
Mouse
Display
Sound
Printer

Software

Add & remove programs
Default programs
Windows components

Services

Services
IISAdmin
Component services
ODBC

Security

Security centre
Firewall settings
User accounts
Policy
Local security settings

Connections

Network connections
Create share
Shared folders
Map network drive
Disconnect network drive
Internet options

Looks

Taskbar properties
Fonts
Folder options
Display themes

I’ve now simple recompiled the utility and created a very simple installer for it (one for x86 and one for x64)

x86 – https://dl.dropbox.com/u/20983/WindowsCommandCentreSetup.msi

x64 – https://dl.dropbox.com/u/20983/WindowsCommandCentreSetupx64.msi

I’ve tested it on Windows 7 and it use to work on Vista/XP as well. Unfortunately I cannot guarantee that it will work properly on Windows 8 if at all. All it requires is the base .Net 2.0 framework to work.

How to run application after VS MSI installer finish

Sometimes you need to do something that is not provided ‘out-of-the-box’ – as provided by the default tools you use. Take Visual Studio’s built in ‘Set-up’ and installation projects as an example.

I wanted to simply add the option to launch the executable that was installed during the install process once the installer ends. Sounds simple and there are ways of doing this with and without Visual Studio using custom installer classes plus ‘Custom Actions’ is possible but it has its drawbacks – like it suspend the installer or you have to write extra code inside your app just to cater for that.

Interestingly enough, MSI installers actually supports this functionality ‘natively’ i.e. it is a built-in feature of MSI technology to have the option for ‘Run my app after the installer ends’. The problem is just that Visual Studio doesn’t expose this functionality itself. The only way to ‘enable’ this feature is to modify the MSI package afterwards – through a ‘Post build action’ or manually (or you can use msbuild or any other build process tool).

To do this you can use a JavaScript script that simply makes the required changes to the MSI package (its internal database). See Aaron Stebner’s blog for more details. The example script to do this is located here.

I initially had trouble getting the working paths correct for my specific project but it turned out the normal ‘build’ command in VS does not always rebuild the solution. Instead you have to explicitly use the ‘Rebuild’ command on the Set-up project to make sure it recreate the MSI using the post build action script.

To summarize how to do it:

  1. First download a copy of the ‘EnableLaunchApplication.js’ script to the set-up projects directory – the directory where the .vdproj file is located.
  2. Then edit the js file to specify the actual exe name of your application you want to ‘launch’ after the MSI finish. You can of course customize it further.
  3. In the Visual Studio set up project’s project properties specify the following ‘PostBuildEvent’: cscript.exe “$(ProjectDir)EnableLaunchApplication.js” “$(BuiltOuputPath)”
  4. Take not that the spelling mistake (BuiltOuputPath) is deliberate since that is how the VS team implemented it (was probably a typo which they never fixed)
  5. Now you can use the ‘Rebuild’ command for the (set-up) project.

and thats how it works. Have fun!

HTMLWriter 1.7

Just a quick refresh on my HTMLWriter utility library. Some minor changes/additions:

1. Added support for the NOBR tag

2. Improved the special character functions including ignoring the ‘&’ sign when needed.

Latest version here.

Rumours of desktop development death greatly exaggerated

Ok, Microsoft has restored some faith from my side in them – after announcing that the new Visual Studio 11 (now called VS 2012) would NOT support any desktop development anymore.

They eventually changed their minds due to a lot of pressure and decided to release a desktop specific version as well – see this.

A quote from the article:

With this new Express edition, developers will be able to use C++, C#, or Visual Basic to create Windows desktop and console applications. Developers will also get access to new advances available across the Express family in Visual Studio 2012, such as the latest compilers and programming language tools, integrated unit testing, and the ability for small development teams to collaborate via Team Explorer and TFS Express.

Now, we just need to get MS to drop Metro and BioWare to fix Mass Effect 3’s ending… and the world could be a happy place again… hehe

Provide “Export to CSV” functionality on an ASP.Net page

I don’t do (or particularly like) ASP.Net development often but recently had to quickly add some ‘Export to CSV’ functionality of a displayed table to a page. Personally I would have just used ‘copy and paste’ to do it (the export) but since the user isn’t in the habit of thinking for themselves I had to create new functionality which turn out to be very nice – and even opens the door for some future more advanced functionality.

Anyway, to achieve this is really easy if you use the HttpContext.Current.Response class and add an attachment ‘header’ to your page. The header must be named ‘content-disposition‘ and ContentType ‘text/csv‘. See the following methods I created to simply take a DataSet and convert it to ‘CSV file’:

public class CSVExportUtils
{
    public void ExportDataSetToCSV(string title, DataSet ds, string columnNamesCSV = "")
    {
        string attachment = "attachment; filename=" + title.Replace(",", "").Replace(".", "") + ".csv";
        HttpContext.Current.Response.Clear();
        HttpContext.Current.Response.ClearHeaders();
        HttpContext.Current.Response.ClearContent();
        HttpContext.Current.Response.AddHeader("content-disposition", attachment);
        HttpContext.Current.Response.ContentType = "text/csv";
        HttpContext.Current.Response.AddHeader("Pragma", "public");
        if (columnNamesCSV.Length == 0)
        {
            WriteColumnName(ds);
            foreach (DataRow r in ds.Tables[0].Rows)
            {
                if (ds.Tables[0].Columns.Count > 0)
                {
                    string value = r[0].ToString();
                    if (value.Contains(","))
                        value = "\"" + value + "\"";
                    HttpContext.Current.Response.Write(value);
                    for (int i = 1; i < ds.Tables[0].Columns.Count; i++)
                    {
                        value = r[i].ToString();
                        if (value.Contains(","))
                            value = "\"" + value + "\"";
                        HttpContext.Current.Response.Write("," + value);
                    }
                }
                HttpContext.Current.Response.Write(Environment.NewLine);
            }
        }
        else
        {
            HttpContext.Current.Response.Write(columnNamesCSV);
            HttpContext.Current.Response.Write(Environment.NewLine);
            string[] columns = columnNamesCSV.Split(',');
            foreach (DataRow r in ds.Tables[0].Rows)
            {
                string value = r[columns[0]].ToString();
                if (value.Contains(","))
                    value = "\"" + value + "\"";
                HttpContext.Current.Response.Write(value);
                for (int i = 1; i < columns.Length; i++)
                {
                    value = r[columns[i]].ToString();
                    if (value.Contains(","))
                        value = "\"" + value + "\"";
                    HttpContext.Current.Response.Write("," + value);
                }
                HttpContext.Current.Response.Write(Environment.NewLine);
            }
        }

        HttpContext.Current.Response.End();
    }
    private static void WriteColumnName(DataSet ds)
    {
        StringBuilder sb = new StringBuilder();
        if (ds.Tables[0].Columns.Count > 0)
        {
            string value = ds.Tables[0].Columns[0].Caption;
            if (value.Contains(","))
                value = "\"" + value + "\"";
            HttpContext.Current.Response.Write(value);
            for (int i = 1; i < ds.Tables[0].Columns.Count; i++)
            {
                value = ds.Tables[0].Columns[i].Caption;
                if (value.Contains(","))
                    value = "\"" + value + "\"";
                HttpContext.Current.Response.Write("," + value);
            }
        }
        HttpContext.Current.Response.Write(Environment.NewLine);
    }
}

This method also allows you to specify the fields you want to export – or alternatively it just use the ones in the DataSet. For example, you can use it like this:

if (Request.QueryString["csvexport"] != null)
{
    CSVExportUtils csvExportUtils = new CSVExportUtils();
    csvExportUtils.ExportDataSetToCSV(fileName, dataSet, "Field1,Field2,...");
}

The calling page can then simply have a hyperlink like this:

SomePage.aspx?csvexport=Yes

Death to desktop development

Well, perhaps that is what Microsoft is trying to achieve with its latest move to remove all desktop development functionality from its Express versions of Visual Studio. Yes, you can still create desktop apps in the ‘pro’ version but at something like $500 it isn’t cheap for hobbyist op someone that is still learning.  Lately they have been making all kind of wild and ridiculous decisions trying to push their new ‘Retro’, eh I mean ‘Metro’ interface down our throats. I for one don’t like this new interface ‘on the desktop’ at all and I’m definitely not the only one!

Just looking at the comments in articles like these you can get the impression that more and more people (developers) are really not liking this new direction that ‘they’ are taking. It is one thing to create something new and exciting but another to actively alienate/irritate your existing followers just to try and push them into a new direction (which might or might not suit them). Is this rush to try and play ‘catch-up’ with ‘the fruit company’ so important that they actually are shooting themselves in the foot? Yes, that is right, they are actively playing the catch-up game but is loosing it with every move they are trying. Not a good move if you want to survive in the end. As big as they are (once) ‘they’ are now in the ‘failing’ game – as Adam Savage would say – Failure is always an option. Microsoft is now ‘living’ that lotto!

Was good knowing ya: RIP Microsoft 1975-2012

Passing a ‘Method’ as parameter in C#

This is actually nothing new but sometimes you might still need a quick reference for to remember how to do this quickly… Say you have a generic class that does something like generating a report and display it somehow (or save or whatever the class do) and want all the ‘calling classes’ to just pass the ‘Method’ that it must ‘run’ in order to generate the report. Yes there are probably nice and fancy tools these days that could also do it if you have the mulla for it…

A solution is to use Anonymous methods that has been with C# (.Net) since version 3 of something.

Reporter r = new Reporter();
r.Report = delegate
{
string stuff = "example report yada yada yada";
return stuff;
}
r.Show();

The generic class that provides the ‘generic’ functionality can then look something like this using a defined delegate so it knows what output it will receive when ‘running’ the method.

public delegate string RefreshActionDelegate();
class Reporter
{
    public RefreshActionDelegate Report { get; set; }

    public Show()
    {
       if (Report != null)
       {
          string theContent = Report();
          DoSomethingWithContent(theContent);
       }
    }
}

This is just a quick example but it shows how you can use the main ‘generic’ class from multiple places each time just passing a different ‘Method’ with its own functionality.