Friday, 24 December 2010

Resizing images with quality in ASP.Net (VB)

Recently I was asked to resize images in realtime during an ASP.Net page load.

I had the ashx page all set up and began using the GetThumbnailImage procedure which I ave used many times before.

Unknown to me was the fact the images were needed to be displayed at a fairly large size, just scaled down - which is where the thumbnail procedure falls apart!

Instead I had to get a bit more serious but also received more control.

The new plan was to redraw the image as a bitmap. To start with I needed to establish the new size which was being passed in the querystring so that was done as follows:

Dim intWidth As Int32 = 100 'Default width if a non numeric number has been supplied.
Int32.TryParse(context.Request.QueryString("Width"), intWidth)
If intWidth > 2000 Then intWidth = 2000 'Make sure no stupid high width has been supplied.

Dim ms As New MemoryStream(byteImage)
Dim img As System.Drawing.Image = FromStream(ms, True)

Dim dblScale As Double = intWidth / img.Width
Dim intNewWidth As Int32 = Convert.ToInt32(img.Width * dblScale)
Dim intNewHeight As Int32 = Convert.ToInt32(img.Height * dblScale)

This will calculate a new width and height based on the supplied width. 'byteImage' is the binary data for the original image and the difference in scale is worked out from that.

The next stage is to create a new bitmap and then begin drawing the image based on that:

Dim thumbnailBitmap = New Bitmap(intNewWidth, intNewHeight)

Dim thumbnailImage = Graphics.FromImage(thumbnailBitmap)
thumbnailImage.CompositingQuality = CompositingQuality.HighQuality
thumbnailImage.SmoothingMode = SmoothingMode.HighQuality
thumbnailImage.InterpolationMode = InterpolationMode.HighQualityBicubic

As you can see there are extra quality parameters here that give more control.

Once the new thumbnail image has been created, it can be returned to the original image:

Dim imgRectangle As New Rectangle(0, 0, intNewWidth, intNewHeight)

thumbnailImage.DrawImage(img, imgRectangle)

ms = New MemoryStream()
thumbnailBitmap.Save(ms, img.RawFormat)
byteImage = ms.ToArray

Finally we have a very large thumbnail.

If rotation is required then I suspected that the bitmap should be rotated before it is redrawn:

thumbnailBitmap.RotateFlip(Drawing.RotateFlipType.Rotate90FlipNone)

Although I haven't tested this yet.

Monday, 24 May 2010

SQL 2008 DTSWizard error

I have just fixed an annoying problem with regards SQL server 2008 Express. I installed the management tools and the DTS Wizard failed to work with the following message:

The SSIS Data Flow Task could not be created. Verify that DTSPipeline.dll is available and registered. The wizard cannot continue and it will terminate. (SQL Server Import and Export Wizard)

Cannot create a task with the name "STOCK:PipelineTask". Verify that the name is correct.

This PC has had SQL Express 2005 on it in the past but before installing 2008, the 2005 edition was fully uninstalled (using Add/Remove programs). The obvious answer was to follow the advice in the actual error message and register the appropriate dll but unfortunately that was answered with this:

The module "dtspipeline.dll" was loaded but the call to DllRegisterServer failed with error code 0x80070005

Now as I am on a Vista machine I established that it was a problem with permissions but running from an elevated command prompt (run as Administrator) still gave me the same message.

What cured it was typing the below into a command prompt to reset the permissions on Vista:

secedit /configure /cfg %windir%\inf\defltbase.inf /db defltbase.sdb /verbose

This was found on http://support.microsoft.com/kb/313222

Once I had run that AND then registered the dll, all seemed to work.

Monday, 5 April 2010

Enabling Google Docs paste functionality with Firefox 3

I was having trouble pasting content into Google Docs using Firefox, something that used to work for me.

There must have been a Firefox update that stopped it working because I certainly didn't change anything.

Anyway, I did the following to get it working again;

Tools menu
Options
Content tab
Enable Javascript (should be checked)
Advanced button on same line
Uncheck "Disable or replace context menus"

Tuesday, 30 March 2010

Visual Web Developer 2008 Express failed (.msp association)

I had an issue today when installing the Express version of Visual Web Developer 2008.

The required files download and the install starts. Then it seemed to want to open a file in a paint package installed on the computer and after it failed in doing so, the installer crashed!

I guessed straight away it might be the association of the .msp file and sure enough, on looking, the .msp extension was associated to a paint package installed on the PC.

Thankfully I had a PC that had the association as it needed to be so I copied that and tried to install the program again.

Not sure what .msp has to so with a paint package or why the installer needs it but once I'd 'corrected' it, all worked well.

Here is the registry key and data required;

HKEY_CLASSES_ROOT\.msg

data = 'Msi.Patch'

Friday, 26 March 2010

CSS floating images and lists

I had a piece of text with an image floated within it that looked exactly as required.

Upon adding unordered list HTML in-between two of the paragraphs, the text above and below the list still looked fine but the bullet points of the unordered list were on the edge of the actual image.


It seems that floating images don't work with <ol> and <ul> commands the same as they do with <p> commands but the fix was to give the unordered list a style of a left margin which matched the width of the image (plus any margin the image itself may have).

<ul style="margin-left:210px;">

Thursday, 25 March 2010

ASP.Net (VB) fix for RadioButton's using GroupName in a Repeater

I've just had the experience of learning that due to the way a repeater renders, in terms of giving names to the controls within, the GroupName attribute doesn't actually work.

This is the official Microsoft bug: http://support.microsoft.com/kb/316495/en-us

I can understand why it fails but it's a little frustrating that the only solution I could find was a javascript one.I originally found it on this website but I wanted to write the script in my code behind and in VB rather than C#.

Here is the code I converted it to.

To start off with in the Page Load event I had

Dim objSB As New StringBuilder

objSB.Append("" & Environment.NewLine)
ClientScript.RegisterClientScriptBlock(Me.GetType(), "UniqueRadio", objSB.ToString)

This just inserts the required javascript at the top of the page (and it should validate OK).

Then within the ItemDataBound event, amongst all the other code in there I put

If e.Item.ItemType = ListItemType.Item OrElse e.Item.ItemType = ListItemType.AlternatingItem Then
Dim rb As RadioButton = DirectCast(e.Item.FindControl("RADIOBUTTONID"), RadioButton)
rb.Attributes.Add("onclick", "setUniqueRadioButton('rptList.*GROUPNAME',this)")
End If

The text in capitals are what needs replacing. The RADIOBUTTONID should be the ID of the radio button and the GROUPNAME should be changed to the group name being used.

If you had multiple 'groups' on the same page you should only need to use the second piece of code twice. The javascript at the top can be referenced throughout the page.

Thursday, 18 March 2010

IE6 floating div margin bug

A very simple one this. I had 2 div elements on my web page. One floated left and one floated right. They had margins to their edges and it looked exactly as required in all proper browsers. That of course doesn't include Internet Explorer 6 which has been one of the bane's of my life for ages now.

Anyway, thankfully it turned out to be an easy fix and, when implemented, it didn't cause issues with Chrome, Firefox etc

All I did was put

display:inline;

on each of the floating elements.

Monday, 8 March 2010

VB.Net - Stopping a form from being moved

I have just managed to finish what I thought would be a 5 minute task that ended up taking me a lot longer than that.

I have a VB.Net application and a form that the client doesn't want the user to be able to move (it needs to hide data that the user validates).

I found various suggestions on-line. The most common being to remove the border of the form. This does work but looks awful so I carried on looking.

I eventually found several code samples written in C# and managed to convert the simplest looking one to VB.Net. I pasted it in the code page for the form and it worked. So here it is....

Protected Overloads Overrides Sub WndProc(ByRef m As Message)
Const WM_NCLBUTTONDOWN As Integer = 161
Const WM_SYSCOMMAND As Integer = 274
Const HTCAPTION As Integer = 2
Const SC_MOVE As Integer = 61456

If (m.Msg = WM_SYSCOMMAND) AndAlso (m.WParam.ToInt32() = SC_MOVE) Then
Exit Sub
End If

If (m.Msg = WM_NCLBUTTONDOWN) AndAlso (m.WParam.ToInt32() = HTCAPTION) Then
Exit Sub
End If

MyBase.WndProc(m)
End Sub

Saturday, 27 February 2010

Speeding up Vista boot

I started to notice the speed of my laptop on boot was degraded. Upon noticing this I spent hours browsing the web looking for possible suggestions to speed it up. Now as it's a laptop I wasn't expecting wonders as the power is nowhere near that of a desktop but it used to be usable upon log-on rather than having to wait a few minutes so I figured there must be something I could do.

Browsing the web come up with several suggestions about disabling software and other start up processes which I played around with to no avail. In fact the more I messed about the longer it seemed to take.

Within the Event Viewer underneath Applications & Services\Microsoft\Windows\Diagnostics-Performance\Operational I was finding boot up logs of warnings and errors, each time with various other (and sometimes none) messages.

I ended up trying a System Restore to a time before I remembered it being slow and that seemed to work initially but then after installing missing patches and software it started acting slow. So as a final resort I restored it to the initial state on purchase, after backing up all my wanted files of course,

This apparently formatted the c drive and I was expecting everything to be as it was when purchased. Sadly it didn't appear so, so either my memory was failing (likely) and the computer had never been that quick to boot up or something was still amiss.

After more research I then found the following pages:

http://smallvoid.com/article/winnt-xperf-xbootmgr.html

http://helpdeskgeek.com/how-to/speed-up-boot-time-in-windows-vista/

http://forum.thewindowsclub.com/windows-tips-tutorials-articles/30384-how-time-boot-perform-boot-trace-windows-microsoft-windows-7-sdk.html

and, in my opinion, the best one

http://alinconstantin.blogspot.com/2008/06/speeding-up-windows-vista-boot-and.html

They all pointed towards something called the Windows Performance Toolkit which Microsoft has information on at http://msdn.microsoft.com/en-us/performance/cc825801.aspx

I thought I had nothing to lose in trying this out so the first thing I tried upon finally installing the Windows Performance Toolkit, which was a challenge in itself. I had to install the Microsoft Windows SDK for Windows 7 and .NET Framework 3.5 SP1 first. I only installed the Win32 Development Tools from this as apparently the full install would have taken quite a long time. Once this had been installed I could find the correct WPT file in the C:\Program Files\Microsoft SDKs\Windows\v7.0\bin directory. In my case it was the wpt_x86.msi file as I had 32 bit Vista.

I ran the following in and elevated command prompt once this was installed

xbootmgr -trace boot -traceFlags BASE+CSWITCH+DRIVERS+POWER -resultPath C:\

The system then rebooted and left me with log files in my root directory (thus the C: above) that I could examine. These files gave me the knowledge that the disk activity was running at almost 100% during boot, giving me the impression this could be the main problem.

This looked a similar status to that mentioned by Alin Constantin in his blog so I followed his instructions and tried defragging.

Defragging was tried first using Vista's built in tool, despite Vista stating it wasn't necessary. This took forever and I actually got fed up of waiting for it before downloading another tool which did it far quicker. I wasn't convinced however and I noticed no significant improvement upon reboot after this. The improvement I did get came after I actually left the Vista defragging utility to run overnight and it actually finished. I was still getting errors in the above mentioned event log but they were warnings rather than critical.

The laptop was becoming quite usable again but I decided I had nothing to lose in running the command Alin mentioned that apparently forces "existing internal operating system optimization mechanisms to update their state based on the current configuration of the system".

xbootmgr.exe -trace boot -prepSystem

This was the command I ran and after about 6 re-boots I am left with a PC that now seems to be as it was when I got it. Although I am still getting the odd warning message in the event log.

Tonight I am going to let it defrag in full again just for luck!

Friday, 26 February 2010

Vista WMI Event 10

On a clean install of Windows Vista I was receiving the below error in the Application Event log.

Event filter with query "SELECT * FROM __InstanceModificationEvent WITHIN 60 WHERE TargetInstance ISA "Win32_Processor" AND TargetInstance.LoadPercentage > 99" could not be reactivated in namespace "//./root/CIMV2" because of error 0x80041003. Events cannot be delivered through this filter until the problem is corrected.

I'm not quite sure why it was appearing but a quick scout around the web gave me the impression that it wasn't causing any real problems. The Windows Management Instrumentation seems to be some kind of system used by Microsoft to manage drivers and interact with Windows.

Removing the error was fairly straightforward and after doing so I found nothing noticeable wrong with the computer.

Here's what I did:

I opened up my Windows services and stopped the "Windows Management Instrumentation" Service. Doing this also stopped two dependent services, "Security Center", & "IP Helper".

Once these were stopped I then ran the Command Prompt (within Start Menu/Accessories) as an administrator (right click on the Command Prompt option).

Within that I typed the following to move the 'faulty' files to a new directory. (Don't type the bits in brackets!)

cd \     (to get to the root of the c drive)
md backupwbem     (to create a directory to move the files to)
cd windows\system32\wbem\repository     (to go to the path containing the files)
move * c:\backupwbem    (to move all files from this directory into the one created above)
exit     (to quit command prompt)

Once I had done this I then restarted the 3 services above ("Windows Management Instrumentation" , then "Security Center", and finally "IP Helper") and all was well.

Friday, 19 February 2010

SEO Musings

A few weeks ago I attended a meeting with a client about the search engine optimisation (SEO) for their website.

I knew some of what they said but there were a few aspects I hadn't contemplated for.

I know that URL Rewriting is a good thing although I'm yet to establish exactly what the best format of a URL actually is. I need to research this for another client soon so hopefully I will come up with a plan. I did find out that hyphens should separate words rather than having them all together (i.e. this-page.aspx rather than thispage.aspx)

Having links inter-linking between the site is also a good thing. So text on the home page could have links within it to pages within the site - then users can navigate without having to only use the menu bar.

Breadcrumbs - I'm not sure if this is good for SEO but it is probably very good for site users to have an idea of where they are currently navigated.

In terms of CSS I had tended to put the odd one or two styles within the actual HTML page but this should all be put in external style sheets - that way robots crawling the site have less text to actually crawl to find the good content.

Error pages should also be more user friendly to the user.

I know some of the above are pretty obvious now they are written down but they are just some things I had never contemplated previously.

I also know the above doesn't even begin to cover SEO in full but I'm hoping by posting this, it will remind me to improve my site building.

Tuesday, 26 January 2010

XHTML & ASP.Net - forcing HTML tags to lower case

One of our clients has set up a central database containing all their product information and has asked us to link to this data to display it on their web site.

All well and good but I can be a bit of a perfectionist sometimes and I like my HTML tags to be in lowercase so that it becomes XHTML compliant. Typically, the feed of data contains tags that are all in uppercase. Even by solving this issue, I'm not really onto a winner with this feed as the tags aren't closed off in most cases but I figure making the tags lower case is a start!

Anyway, I did start off by doing a list of replaces after the string:

strOriginalString.Replace("<UL>", "<ul>").Replace("</UL>", "</ul>").Replace("<LI>", "<li>") etc etc

I realised this could get very long and they may also start using tags that I hadn't covered so I decided a regular expression was probably the way to go. Not being a genius (or anything remotely close) with these, it took a bit of Googling and I eventually came up with a solution.I'm not sure it is the best way but it does seem to work.....First I created a function on the ASP.Net code behind as this:

Private Function ToLowerCase(ByVal m As Match) As String
        Dim objSB As New StringBuilder
        For intLoop = 0 To m.Captures(0).Value.Count - 1
            objSB.Append(m.Captures(0).Value(intLoop).ToString.ToLower)
        Next
        Return objSB.ToString
End Function

This should receive a full tag and go through each character (including < and >) and set them to lowercase before returning the full tag now in lowercase.

Finally I had to set up the RegEx on the string in question:

litText.Text = Regex.Replace(strOriginalString, "<(.|\n)+?>", New MatchEvaluator(AddressOf ToLowerCase))

This seemed to solve the issue for me. Maybe in the future I will find a quicker/cleaner way....      

Monday, 25 January 2010

Google maps embedding - who moved the marker?

All I wanted to do was have a little map next to each address for outlets on a web site. I figured this would be a nice quick job - especially as Google nicely provide an embed link when you use their Mapping site.

I knew I would have to modify the links at runtime to accept the postcode from the database I was using to list the outlets but I figured I could do this quite easily.

So let's get a single outlet done and working before I start trying to be clever.

Postcode = WA15 8ES

Go to Google maps, enter it and get the following.....



Perfect so far!

so now I get the embed link kindly provided by Google for this particular location

http://maps.google.co.uk/maps?f=q&source=s_q&hl=en&geocode=&q=Altrincham,+Cheshire+WA15+8ES,+UK&sll=53.800651,-4.064941&sspn=15.686479,36.254883&ie=UTF8&hq=&hnear=Altrincham,+Cheshire+WA15+8ES,+United+Kingdom&z=16&ll=53.388896,-2.34556&output=embed

Place this on my site and voila......



Easy! Erm.... actually...... who moved the marker! I've changed nothing, just done as Google suggested and embedding has moved the location of the outlet to a main road that is actually a bit of a drive away - not very useful for customers really!

Incidentally, the link they provide for this

http://maps.google.co.uk/maps?f=q&source=s_q&hl=en&geocode=&q=Altrincham,+Cheshire+WA15+8ES,+UK&sll=53.800651,-4.064941&sspn=15.686479,36.254883&ie=UTF8&hq=&hnear=Altrincham,+Cheshire+WA15+8ES,+United+Kingdom&ll=53.389471,-2.344573&spn=0.007716,0.017703&z=16

is fine so why the embedding is so far out is something only the Google developers could perhaps answer.

I did mess about with trying to change the values in the embed link's querystring - including the latitude and longitude values but got nowhere. In the end, I resorted to use the Google Maps API and all seems well (although I did have to use the longitude and latitude locations for this to work, rather than the postcode).

A colleague suggested that the embed link only takes into consideration the first part of the postcode. If this is true then I'm not sure why Google would have made it like this unless they are trying to force developers down the API route.

Friday, 22 January 2010

ASP Email - character positioning

Here's an interesting problem I was given.

A web site dealing with villas is written in classic ASP. When an enquiry for a property is submitted by a customer an e-mail is generated containing all the details of the enquiry.

 All has been working well until today when it crashed with a mail error. The error was as follows:

CDO.Message.1 error '8004011b'

From searching about, this seems to look like an error regarding the mail server being unavailable - or can't be connected to.

However, I knew this couldn't be the case because the same server had other sites sending mail OK using similar code.

To narrow down the issue I started stripping out the HTML from the body text of the email that was being sent. Part of the information was the arrival date and time and departure date and time from the property that had been requested. This was where I started to find a difference between it working and not working.

If I removed the departure information it worked OK, if I swapped departure for arrival information and basically replicated the arrival code (for testing purposes), it failed! What became more strange was that taking the colon our of the middle of the departure time caused the email to send, despite the fact the arrival date had it in!. Placing a colon at the end of the time also caused it to work.

So "1000" and "10:00:" both worked but "10:00" didn't. This was turning out to be quite a bizarre problem!

Upon trying random things in the code I solved the issue. There must be a character limit on the commands sent to a mail server, or at least an IIS SMTP server, and the colon was appearing at the end of a line being sent which must have given the server a problem.

The solution was to place new lines (vbNewLine) in the code above so that the HTML wasn't one big string and the mail server didn't have any issues.

I knew that dots could cause issues but colon's was something new for me.

Thursday, 21 January 2010

Vista/IE opening with no connection

For a while now I have had issues opening Internet Explorer on my work computer. The program would be opened, fail to get a connection and I would shut it down and repeat until it did connect. The home page was aimed towards a local Intranet address but this wasn't the issue - whatever the home page was set as, the same problem occurred.

Now this may have started once Microsoft ISA Server became the network's way out to the Internet as I am sure it didn't happen before. However I can't pinpoint it for definite.

As I mainly use Firefox for development of web sites at the moment I haven't really been too bothered about it. It was just an annoyance that I had to try starting IE several times before I had a successful connection.

At random intervals I did try and look into it through our trusty friend Google but to no avail.

Recently however, I found out it was happening on other computers on the network also and users were just putting up with it rather than informing me.

Anyway, I had another Google session on this last week and found this post about tabs not connecting. Now I didn't do everything mentioned on this page but simply decided to try the following in the command prompt;

regsvr32.exe /n /i ieframe.dll

Once I had done this, my IE then seemed to connect every time I started it the first time so I am hoping I have solved it.

I passed the same info onto some colleagues and one says it is now better but not perfect. I'm yet to follow it up to see if it is the same problem.

As far as I am concerned though, so far so good!


Monday, 18 January 2010

Excel file failure

A friend sent me a file that was allegedly an Excel file that she couldn't open.

Sure enough, Excel opened up when the file was double clicked and then showed nothing. To tabs, no option to do anything and no data.

I attempted to open it up in repair mode and got the same.

Strangely it opened successfully in OpenOffice so I was at least able to retrieve the data from it and re-save it in Excel format.

I have no idea what may have happened to the original file - I can only guess it was corrupted in some way.

I did find it amusing that OpenOffice opened up an Excel file that MS Excel couldn't though! I appreciate it will access the data in a different way but I would have expected Excel to get closer than it did!