Educating the world

Our blog has over 10,000 readers a month

Unable to generate a temporary class

November 2nd, 2012

If you use serialisation then IIS dynamically compiles the extra classes it needs to perform the serialisation and it uses the Windows temporary folders to store the class files definition and class compilation artefacts. If IIS can’t write to the temporary folder you will get this error message:

Server Error in ‘/application’ Application.
Unable to generate a temporary class (result=1).
error CS2001: Source file ‘C:\Windows\TEMP\1kcmvhly.0.cs’ could not be found
error CS2008: No inputs specified

Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.

Exception Details: System.InvalidOperationException: Unable to generate a temporary class (result=1).
error CS2001: Source file ‘C:\Windows\TEMP\1kcmvhly.0.cs’ could not be found
error CS2008: No inputs specified

Source Error:
An unhandled exception was generated during the execution of the current web request. Information regarding the origin and location of the exception can be identified using the exception stack trace below.

Stack Trace:
[InvalidOperationException: Unable to generate a temporary class (result=1).
error CS2001: Source file ‘C:\Windows\TEMP\1kcmvhly.0.cs’ could not be found
error CS2008: No inputs specified

System.Xml.Serialization.Compiler.Compile(Assembly parent, String ns, XmlSerializerCompilerParameters xmlParameters, Evidence evidence) +1357
System.Xml.Serialization.TempAssembly.GenerateAssembly(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, Evidence evidence, XmlSerializerCompilerParameters parameters, Assembly assembly, Hashtable assemblies) +2809
System.Xml.Serialization.TempAssembly..ctor(XmlMapping[] xmlMappings, Type[] types, String defaultNamespace, String location, Evidence evidence) +366
System.Xml.Serialization.XmlSerializer..ctor(Type type, String defaultNamespace) +951
WebApplication1.LicenseManager.getLicenceRequestResult(String url) in D:\views\davidne_view\kernel\WIP\WebApplication1\WebApplication1\LicenseManager.cs:16
WebApplication1.LicenseManager.obtainLicenseKey(String version, String feature, String sessionid, String username) in D:\views\davidne_view\kernel\WIP\WebApplication1\WebApplication1\LicenseManager.cs:33
WebApplication1.LicensedSessionModule.OnPreRequestHandlerExecute(Object source, EventArgs e) in D:\views\davidne_view\kernel\WIP\WebApplication1\WebApplication1\LicensedSessionModule.cs:55
System.Web.SyncEventExecutionStep.System.Web.HttpApplication.IExecutionStep.Execute() +80
System.Web.HttpApplication.ExecuteStep(IExecutionStep step, Boolean& completedSynchronously) +270

Version Information: Microsoft .NET Framework Version:4.0.30319; ASP.NET Version:4.0.30319.272

If IIS can’t create files in that folder then the application will fail at runtime so, you must give IIS write access to C:\windows\temp.

  1. Right click on C:\windows\temp select Properties.
  2. Select the Security tab.
  3. Click Edit
  4. When the Permissions for Temp dialgue box opens click Add.
  5. In the Enter the object names to select(example) box enter iis_iusrs.
  6. Click Check Names and the system will change the name to HOST\IIS_IUSRS. Click OK.
  7. Highlight IIS_IUSRS (HOST\IIS_IUSRS) and in the Permissions for IIS_IUSRS box, check all the security boxes in the Allow column. You can’t check Special permissions so ignore that one.
  8. Then OK all the way out.

It moans about changing permissions on system folders so just click Yes to that. Now you should be able to reload the page without a problem.

There is a way to get around it by recompiling the classes needed for serialisation but I’ll save that one for another time.

Setting Google Chrome's Google Maps extension's location

October 28th, 2012

I downloaded the Google Maps extension from the Web Store and installed it into Google Chrome. Opened a new tab and clicked the Google Maps button, it got me straight to a zoomed out picture of the United States of America. I couldn’t find any options inside Chrome’s settings or extension settings to change my default location.

Had a bit of a Google and found quite a few forum threads of people with a location mismatch. The main suggestion was to install the English (UK) version of Chrome (instead of the English (US) version which is the default version on the download site). The next most popular suggestion was to change the language settings to add English (UK) and increase it’s priority. I tried all of the suggestions and none of it worked.

Today, when I clicked the Google Maps extension button it took me to the USA as usual but I noticed on the right information panel it said “United States Not your current location? Correct it". So I clicked the “Correct it” link. I entered my location and Google Maps took me there. I closed the tab and reopened a new one, clicked the Google Maps extension button and Hey Presto I’m taken straight to my real location.

It’s so simple to change the default location and the actual setting is just in the right place. If you are out and about you can easily change to any location at any zoom level. Perfect.

Open relay caused by Plesk 10.4.4 update

October 17th, 2012

Another great shout out to the boys at Plesk. Installing patch 10.4.4 turned my box into an open relay that allowed spammers to use my host to send junk email.

I started to see the following appear in the process list. We were also finding that emails that were legitimately being sent were taking ages to come through. Logged in and checked the process list and I was very surprised to see:

... xinetd -stayalive -pidfile /var/run/
... \_ /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/cmd5checkpw
... \_ /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/cmd5checkpw
... \_ /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/cmd5checkpw
... \_ /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/cmd5checkpw
... \_ /var/qmail/bin/qmail-smtpd /var/qmail/bin/smtp_auth /var/qmail/bin/cmd5checkpw
... qmail-send
...  \_ splogger qmail
...  \_ qmail-lspawn | /usr/bin/deliverquota ./Maildir
...  \_ qmail-rspawn
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  |   \_ /var/qmail/bin/qmail-remote.moved
...  \_ qmail-clean

Another symptom was that the secure log was registering loads of connects. You might get this on a busy server but ours isn’t.

tail -f /var/log/secure
Oct 15 13:04:14 s15427035 tcp-env[19544]: connect from (
Oct 15 13:04:14 s15427035 tcp-env[19545]: connect from (
Oct 15 13:04:14 s15427035 tcp-env[19546]: connect from (

To cut a really long boring story short, Plesks 10.4.4 update added extra services to the /etc/xinetd.d:

cd /etc/xinetd.d
ls -l smtp*
-rw-r–r– 1 root root 288 Oct 15 13:03 smtp_ok // switch off
-rw-r–r– 1 root root 397 Oct 15 10:50 smtp_psa
-rw-r–r– 1 root root 290 Oct 15 13:03 smtps_ok
-rw-r–r– 1 root root 398 Oct 15 10:50 smtps_psa // switch off

Edit smtp_ok and smtps_ok and update the disable line to “yes". If the line doesn’t exist then create it.
Edit smtp_psa and smtps_psa and update the disable line to “no". If the line doesn’t exist then create it.

When you have made the changes, restart xinetd:

/etc/init.d/xinetd restart

The first thing to do is stop qmail so it can’t send any more junk mail.

/etc/init.d/qmail stop

Now that we’ve sealed the hole left by the Plesk 10.4.4 patch, we’ll see how much mail we need to clean up.

messages in queue: 7589
messages in queue but not yet preprocessed: 0

I looked for ages tying to figure out how to delete mail from the qmail queue and there doesn’t seem to be a way in the standard qmail tool set! So on to the internet and I found Qmail-Remove. This tool deletes everything in the qmail queue. It has a couple of different options to only delete certain emails but I’ll leave that as an exercise for the reader.

I knew that everything in the queue was junk so I could do a blanket delete:

qmail-remove -d

Check it’s all gone, then restart qmail:

messages in queue: 0
messages in queue but not yet preprocessed: 0

/etc/init.d/qmail start

SQL for beginners

October 4th, 2012

There are plenty of articles on how to get going with SQL (or MySQL) for beginners. However, there aren’t many articles which take you back to basics describing the building blocks used and help you understand the concept of what a database actually is.

This document will hopefully introduce you to the kinds of things that SQL is capable of. Each example has the command and the results so hopefully you can just read and understand it. I’m aiming this document at people who may come across SQL as part of someone else’s job and feel like they should know a bit about it, but don’t really know where to begin.

So let’s get going…

Structured Query Language or SQL is a computer language used to get stuff out of a database. To understand this statement we need to know what a computer language is and what a database is. Simple again! A computer language is just a set of commands that will make the computer do stuff and a database is multiple groups of stuff.

Now that we have got that out of the way, let’s begin. For this lesson we’ll be using MySQL, partly because it’s free and partly because there are some instructions here to set up MySQL and PHP on a test system.

To understand SQL you have to understand a little bit more about the structure of a database. The groups of stuff I mentioned earlier are called tables. A table is a grid of rows and columns. A database is a collection of tables. Now you have, everything you need to know! So let’s do an example we can all relate to.

We’ll create a table to hold information on people. Table names tend to be plural names like people, parts, events, etc so in this case people and not person because the table holds lots of persons! We collect some relevant information together: first name, sex, age. Then we’ll try to do some thing useful with them.

Before we create the people table we must have a think about the best way of storing the information in the table. Each attribute, field or column needs to have a type. First name is text, sex is an enumeration of male or female and age is an integer. You could make all columns text but we would like to do sums with the age column so we’ll need to use a column type that allows this.

In the early days of programming the commands were separated by new lines but as the languages got more complex people wanted to spread the code over several lines and so a semi-colon was used to denote the end of a statement.

first_name VARCHAR(20)
,sex ENUM(’male’, ‘female’)
,age INT

The words in capitals are keywords, they are reserved for use by the computer language. i.e. you can’t have a table called table! Test columns need to have a maximum length so you need to specify it.

Now that we have a table let’s put some stuff in it:

INSERT INTO people(first_name, sex, age) VALUES
(’David’, ‘male’, ‘40′)
,(’Jon’, ‘male’, ‘30′)
,(’Tom’, ‘male’, ‘20′)
,(’Sophie’, ‘female’, ‘10′);

It’s only a small table so let’s list the contents.

SELECT first_name, sex, age FROM people;

Produces the output:

| first_name | sex    | age  |
| David      | male   |   40 |
| Jon        | male   |   30 |
| Tom        | male   |   20 |
| Sophie     | female |   10 |

Here you can definitely see the rows and columns structure I mentioned earlier. Each row is a complete set of information, that is there is an entry for every column. We didn’t put any restrictions on the table so we could have not supplied information for some of the columns if we wanted. In which case it might have looked something like this.

| first_name | sex    | age  |
| NULL       | male   |   40 |
| Jon        | NULL   |   30 |
| NULL       | NULL   | NULL |
| Sophie     | female |   10 |

Where NULL denotes the absence of data. In database terms NULL values are a bit of a bane. This special NULL symbol says the information is not provided and so we can’t assume anything about it. Most applications usually filter out the rows where there are gaps in the information.

Do you remember SETs from school? All of SQL is based on that idea. So lets look at our data and rephrase our question using SET-speak.

Show me all the information for a person where the person is over 21 is translated into

SELECT first_name, sex, age
FROM people
WHERE age > 21;

| first_name | sex  | age  |
| David      | male |   40 |
| Jon        | male |   30 |

Show me all the first names of all the females is translated into

SELECT first_name FROM people WHERE sex = ‘female’;

| first_name |
| Sophie     |

You may think that we are using the WHERE clause to filter the data to get results but what we are doing is far more subtle than that. We are creating new sets by dividing up existing sets. The sets may be added together in a union or subtracted from each other in an intersection. When we create our subset of data we can use it as the bases for another query. This can be shown in the following query:

SELECT first_name FROM people
WHERE age < 35
AND first_name IN (
SELECT first_name FROM people WHERE sex = ‘male’

The inner SELECT is the sub-query and produces a set of males names. That set of people is used with another set filter to reduce the set even further.

| first_name |
| Jon        |
| Tom        |

The previous query could have been written as the following but quite often you’ll find that the data is not conveniently placed in the same table! it’s in another table or is the result of a calculation.

SELECT first_name FROM people
WHERE age < 35 AND sex = ‘male’;

Now that we understand a little more about the concepts of sets and creating them let’s look at doing something (more) useful.

We will start simple and count the number of males and females in the data set. To the average MySQL’er this will seem like an odd choice to talk about first but it will hopefully be obvious (later) that it is the only starting point.

SELECT COUNT(first_name), sex
FROM people

Produces the output:

| COUNT(first_name) | sex    |
|                 3 | male   |
|                 1 | female |

The GROUP BY command is used all the time to collapse sets of information so that they can be aggregated. In this case we are collapsing around the sex column. To the SQL engine that gathers the rows the GROUP BY effectively makes the data look like this.

| first_name | sex    | age  |
| ?????      | male   |   40 |
| ???        | male   |   30 |
| ???        | male   |   20 |
| ??????     | female |   10 |

There aren’t many aggregate operations we can do on text columns like first_name, so the information is meaningless and unpredictable. The data is treated as a separate set of each unique entry in sex. Conceptually the data set has been split into two:

| first_name | sex    | age  |
| ?????      | male   |   40 |
| ???        | male   |   30 |
| ???        | male   |   20 |


| first_name | sex    | age  |
| ??????     | female |   10 |

The GROUP BY will allow you to create aggregate operations. For example:

SELECT COUNT(first_name), sex
FROM people

shows the number of rows counted in each of the two groups of data, giving the result:

| COUNT(1) | sex    |
|        3 | male   |
|        1 | female |

or the total age and average for those sets.

SELECT SUM(age), AVG(age), sex
FROM people


| SUM(age) | AVG(age) | sex    |
|       90 |  30.0000 | male   |
|       10 |  10.0000 | female |

When the GROUP BY is applied to the whole table the GROUP BY keywords may be omitted but it is there implicitly. For example:

SELECT SUM(age), AVG(age) FROM people;

| SUM(age) | AVG(age) |
|      100 |  25.0000 |

This document introduces the concepts of sets, creating subsets and then treating a set as an entire entity and doing something useful. A table is one big set and next time we’ll look at joining tables together to see what matches and what’s missing.

Installing VirtualBox, CentOS 5.4, Apache, PHP and MySQL

September 11th, 2012

I’ve recently done a project that uses load balancing. mod_proxy is a blog for another day but it was based on a LAMP stack. I install this all the time for lots of different projects. Some are development projects and some are just system administration projects.

My desktop of choice is Windows. I hate it slightly less than I hate MacOS, so I’m going to be installing my LAMP stack inside a virtual machine.

First up let’s get VirtualBox up running:

  1. Download VirtualBox for your operating system from
  2. Install it, selecting all the defaults.

Next we’ll set up a Virtual machine which will run our guest operating system:

  1. Download the latest copy of CentOS from their list of mirrors. At the time of writing this article was CentOS-5.4-i386-bin-DVD.
  2. Run VirtualBox.
  3. Click the New button to create a new virtual machine.
  4. Give the virtual machine a name. You can give it the name of the operating system or the project you will be working on.
  5. Select Linux as the operating system.
  6. CentOS wasn’t in the list so I just selected Other Linux, I don’t think this does anything.
  7. Click Next, to configure the Memory.
  8. There 6GB in my PC so I’ll give 1024MB to the virtual machine. You can change this later if you like.
  9. Click Next, to configure the Virtual Hard Disk.
  10. Accept the defaults to create new hard disk.
  11. Click Next, to start the virtual disk creation wizard.
  12. Select the VDI(Virtual Disk Image) and click Next.
  13. Select Dynamically allocated because it creates a smaller file which helps with housekeeping and backups at the cost of a small amount of speed each time the hard disk needs to grow. You’ll only really notice this at the beginning when your installing everything but once you’re done you’ll find that it hardly grows after that.
  14. You can leave the hard disk name the same as the operating system.
  15. CentOS should install in a couple of gigabytes so accept the default of 8GB. The file won’t be 8GB straight away.
  16. Select Next, then Create and then Create again.
  17. The virtual machine’s creation should be instant. We’ll tweak a few settings and install our guest operating system.
  18. Click the Settings button.
  19. Select the System tab.
  20. No one has a floppy disk drive anymore so switching it off will speed up your boot slightly. Uncheck Floppy and move it to the bottom of the list.
  21. We’ll connect our ISO file to the virtual machine’s CD-ROM drive. So select the Storage tab and highlight the Empty CD-ROM drive.
  22. Select the Network tab and change the Attached to Bridged Adaptor. This will allow you to pick up a real network address from the DHCP server which makes testing easier.
  23. The right hand panel will change so click the CD-ROM icon on the far right to open the file selector.
  24. Select Choose a virtual CD/DVD disk file and navigate to your ISO image and open it up.
  25. Click Ok to close the Settings panel.

Right, off we go. Click Start and read the popup boxes and click your way through them. VirtualBox will launch the Virtual Machine and will attempt to boot from the ISO image we gave it earlier. You will start to see the CentOS installation happening in a new window that’ll open up

  1. Press Return to install in graphical mode.
  2. Don’t bother checking the CD media because it’s really just a file and so won’t suffer from any corruption, hopefully! So select Skip.
  3. The virtual machine will think about it for a second and then launch the installation application in X-windows.
  4. Select your language, keyboard country. If you are English then select United Kingdom.
  5. Your virtual disk has not been partitioned or formatting and the installer notices. So click Yes and accept the defaults.
  6. Select the defaults for Network Devices.
  7. Select your location for the timezone.
  8. Enter your Root password. If the virtual machine is going to be on the internet then choose your password carefully. If it’s just a test system then just choose something simple and small!
  9. The next screen allows you to select an installation profile. I’m going to be just doing PHP development so don’t need to bother with all sorts of desktop applications like Open Office etc. I do want web servers and networking tools. Select Server - GUI.
  10. Select Customise now and then Next. We’re going speed up the installation by not installing a load of stuff.
  11. Under Applications unselect most of them except the editors.
  12. Under Development make sure you select the Development Libraries and Development Tools.
  13. Under Servers make sure you explicity check MySQL Database.
  14. Open the Web Server and explicitly set php-mysql.
  15. Under Base System -> System Tools, explicitly select tn (telnet is a handy connection tester) and Wireshark (for packet sniffing).
  16. Under Languages select your country support.
  17. Click Next and Next again to start the install.
  18. 4 minutes later you can click the Reboot button.
  19. When the the virtual PC reboots it puts you in the platform configuration screens. Click Forward.
  20. If your not on the internet make life simple and switch of the Firewall and the SELinux.
    You don’t need Kdump either.
  21. Create yourself a User.
  22. It’s nice to have a bit of sound so test that.
  23. Click Finish and reboot.

When the virtual machine reboots stop it so we can change the boot order. We don’t want to boot from CD every time.

  1. Click Settings -> System
  2. Move Hard Disk to above CD/DVD ROM.
  3. Then click OK.
  4. Next click the Start button, to boot the virtual machine.
  5. You will be booted to the X-Windows login prompt.
  6. Login as the root user.
  7. Open a terminal window; it’s under Application -> Terminal.
  8. We want Apache and MySQL to start when the virtual machine boots into multi-user mode (runlevel 3).

    cd /etc/rc3.d
    ln -s ../init.d/httpd S99http
    ln -s ../init.d/mysql S99mysql

  9. Now we’ll start the services

    /etc/init.d/httpd start
    /etc/init.d/mysqld start

We should be up and running so we’ll create a .php file to test that PHP and MySQL are working together.

  1. Change to the web server document root:

    cd /var/www/html

  2. Create a file called pdo.php and fill it with:


    $pdo = new PDO("mysql:host=localhost;dbname=mysql""root""");
    $sql "SELECT NOW()";
    $stmt $pdo->query$sql );
    $obj $stmt->fetch(PDO::FETCH_OBJ);
  3. Get the virtual machines IP address with /sbin/ifconfig.
  4. Open a browser and navigate to http://<ipaddress>/pdo.php
  5. You should see the following output in the web browser:

    object(stdClass)#3 (1) { ["NOW()"]=> string(19) “2012-06-11 00:37:14″ }

Congratulations that was easy.

Now that you have a fresh clean system it’s a good idea to create a clone. We can use this clone to create clean copies for other projects without having to go through all the hassle of installing the operating system. We’ll have to shutdown the virtual machine so from the command line type:

shutdown -h now

In VirtualBox:

  1. Right-click on the virtual machine and select Clone.
  2. Give it a name ending in “clean” so you know this one shouldn’t be touched.
  3. The first question VirtualBox asks is whether you want to reinitialise the MAC address on the network cards. The MAC address is the physical network address so if you want to run multiple clones at the same time then you’ll have to do this reinitialise step. Otherwise you could be in a world of IP address conflicts as both clones will appear to be the same machine. So do a Full Clone to keep it safe.

My installation was about 3GB so it took a few seconds to copy all the data to make the clone.