# Friday, May 29, 2009
I've got my Dell Studio XPS 16 laptop up and running the Windows 7 RC.

Stats:

XPS 1640, Intel Core 2 Duo P8700(2.53GHz/1066Mhz FSB/3M L2 Cache)
Obsidian Black High Gloss Finish with Leather XPS 1640
4GB, DDR3, 1067 MHz 2 Dimm forXPS 1640
16.0 inch Wide Screen 16:9 1080p FullHD RGBLED LCD W/2.0 MP, XPS 1640
ATI Mobility RADEON HD 3670 - 512MB
320GB 7200 RPM SATA Hard Drive
Microsoft Windows Vista with SP1 Home Premium Edition 64-bit Edition English
8X DVD+/-RW Slot Load Drive for XPS1640
Integrated High Definition Audio 2.0
Intel WiFi Link 5300 802.11AGN Half Mini Card
56 WHr 6-cell Lithium Ion P Primary Battery, for XPS 1640
Warranty Support,1 Year Extended
Dell Wireless 370 Bluetooth Internal (2.0+Enhanced Data Rate)
Premium HD WLED Display Obsidian Black, Leather 2.0 MP Webcam
Dell WebCam Central 1.0 XPS 1640

Total with Tax: $1,698.46

I've always noticed that when I'm using my laptop (the old one, or even this new one), if I am waiting for anything, it's the hard drive. Despite my heavy development work, the CPU is seldom the bottleneck for me.

Here's a benchmark of the hard disk from HD Tune:



The average Transfer rate is 60.8 MB/sec and the Access time is 24.4 ms. So I sped it up by replacing that HD with an Intel X-25M SSD. Check out the new numbers:




Wow, a 100% improvement in Transfer rate, and a ridiculous improvement in Access time! But this is not the full story. When you're using your computer, the operating system is not usually streaming long contiguous bytes. It's making TONS of teeny tiny little random reads and writes (click here for my source). SSDs are better at this and the Intel X-25M is the highest MLC performer (click here for my source), although OCZ has a great offering.

So let's take a look at those random reads. Here's the data for my Studio XPS 16 with the stock hard drive:



It's doing about 30-40 operations per second, regardless of the transfer size. Remember, your OS does a lot of things at once. It's shooting all over the platter of your hard disk, getting little bits of information. And each time it wants one of those little bits, it needs to move a little arm, and wait for the disk to spin to that spot! But SSDs do not have that limitation. They can read RANDOMLY as quickly as they can read CONTIGUOUSLY. Take a look at that same laptop with the X-25M installed!



Yes, it is literally ORDERS OF MAGNITUDE faster. And you will notice this speed as you boot up faster, log in faster, and launch applications faster.

But, to be fair, SSDs have their limitations. They are notoriously slow when it comes to WRITING. As explained in Andand's article, each time you want to write or overwrite data, you need to perform an erase operation (unless the disk is brand new or was recently wiped). SSD write speed used to be pretty bad, but Intel has raised the bar with the X-25 series, bringing it at least on par with hard drives in most situations. OCZ still has some issues with random writes, but they are improving.

Another SSD limitation is that they wear out more quickly. You can only flash a cell so many times. SSDs wear out faster than Hard Drives. The SSD controller is smart enough to spread your writes evenly throughout its structure, but even then, it will still wear out faster than a hard drive.

Finally, SSDs are far more expensive than hard drives.

Nonetheless, this is the beginning of the end when it comes to hard drives with regard to use as a system volume.
Friday, May 29, 2009 12:12:47 PM (Central Daylight Time, UTC-05:00)
# Wednesday, May 20, 2009
I noticed that my web app, which makes anywhere from one to many MySQL connections per page was running slowly on my new Windows 7 RC laptop. I used dotTrace to compare the page execution to that of my desktop (which runs the app very quickly) and noticed that it was all the MySQL connections that were taking 10x to 100x as long to execute on the laptop.

After a bunch of troubleshooting I finally determined what was causing the performance problem. It was Nod32 4.0. I couldn't just disable Nod32, though. I had to completely uninstall it to cure the MySQL ODBC slowdown!

With Nod32 4.0 installed, some pages were taking 13 seconds to execute.
Without Nod32 4.0 installed, those same pages were taking less than a second to execute.

I observed this behavior on two systems:
  1. Dell Inspiron E1705 w/ Windows 7 RC x86
  2. Dell Studio 16 XPS w/ Windows 7 RC x64 (happened with both 64-bit and 32-bit ODBC drivers, and with both 3.51 and 5.1 versions of each)
Both systems have Windows 7 so this could be a problem only for Windows 7 users with Nod32 4.0. Maybe it's fine with Vista or some other anti-virus application. I hope this helps someone because it took me FOREVER to figure out it was Nod! I sent their support an email explaining all this. Hopefully they will write back with some info. Aside from this, which is a DEALBREAKER, I love Nod32 :(

Wednesday, May 20, 2009 1:02:25 AM (Central Daylight Time, UTC-05:00)
# Wednesday, May 06, 2009
I have a client that needed a text change made in an asp.net web app. Should be easy, right? The problem is that it's an old app, the text was hard-coded in the VB, and the source code is long gone! So how do you edit text that is already in a .NET DLL?

.NET Reflector to the Rescue!
  1. Get .NET Reflector and install it.
  2. Use .NET Reflector to open your assembly.
  3. Expand your assembly, and look for the class that represents the page you would like to edit. In my case it was "viewprintnotice", which represented "viewprintnotice.vb".
  4. Expand that class and click the method you guess the text was set in. I guessed Page_Load.
  5. Right click it and Disassemble.
  6. Did you find the code where the value was set? If so, take note. If not, keep digging until you find it. You can't make the change here, though. To actually edit, you need a plug-in.
  7. Download Reflexil.
  8. Install it.
    1. Close .NET Reflector (this step may not be necessary, actually)
    2. Drop its files into the .NET Reflector directory.
    3. Open .NET Reflector.
    4. View > Add-Ins.
    5. Choose Add, and double-click Reflexil.dll.
  9. Enable Reflexil by going to Tools > Reflexil.
  10. Navigate back to your assembly's class's method that set the text.
  11. Find it under Reflexil's Instructions tab. This may take a bit of digging.
  12. Right-click the instruction, click edit, and make your changes. Update your changes.
  13. Navigate to your dll and click it.
  14. Reflexil will let you save it!
  15. Save it and drop it into your server's bin directory and you've made your text edit.
  16. Take a shower because what you just did was dirty.

Wednesday, May 06, 2009 4:50:11 PM (Central Daylight Time, UTC-05:00)
# Sunday, March 29, 2009
This page tells you how to do it in PHP, and it also tells you what characters need to be escaped. So, converting it to C# was not that hard:
public static string MySqlEscape(this string usString)
{
    if (usString == null)
    {
        return null;
    }
    // SQL Encoding for MySQL Recommended here:
    // http://au.php.net/manual/en/function.mysql-real-escape-string.php
    // it escapes \r, \n, \x00, \x1a, baskslash, single quotes, and double quotes     return Regex.Replace(usString, @"[\r\n\x00\x1a\\'""]", @"\$0");
}
I use it in a static class as an extension method. If you don't speak Regex, what it says is this:
"If you find any of the following list of characters: \r, \n \x00, \x1a, \, ', ", replace them with a backslash followed by themselves."

This will put a backslash before any of the offending characters and make your query safe from SQL Injection. Please don't take my word for it though. If you use it, test it thoroughly.

Sunday, March 29, 2009 5:14:56 PM (Central Standard Time, UTC-06:00)
# Sunday, March 22, 2009

I started by booting the laptop from my Windows 7 Beta Build 7000 (x86) DVD from my MSDN subscription.

I opted to wipe the system and install on a fresh partition. Installation went perfectly. Once I got to the windows desktop, I extracted my Build 7057 ISO with WinRAR and ran setup.exe, following the steps for the upgrade. I'd have just started with this build but I *just* got my hands on it.

The upgrade went smoothly, but it took more reboots than I expected, and reboots happened where I didn't expect them. Oh well, no biggie. Once I got to the desktop, I installed the Vista 32-bit driver for my Radeon Mobility x1400 (downloaded from Dell's site). After a reboot I was at my native 1920x1200 rez.

Next, I installed all recommended and optional updates, which happened to be for my card reader, and the system was fully built and running well! All devices in the device manager are recognized. After that, I installed the Synaptics Touchpad driver (again, I just used the Vista 32-bit driver from Dell's site) and it worked perfectly.

I'm happy with the OS so far. In fact, I'm writing this blog post in Windows 7 right now!


Minor issues I had:
  • I could not join my domain, pendingproductions.com with build 7000. Apparently it's a known issue with long domains. Worked fine with build 7057.
  • My desktop.ini was opening upon every login. I followed these directions to fix that.
2009-03-23 Update: At this point I've installed all my dev and office stuff and it's working great!
  • Office 2007
  • SQL Server 2008 Developer Edition
  • Visual Studio 2008
  • Eset Nod32 Anti-virus version 4
  • WindowClippings (used to take the above screenshot - with alpha channel!)
  • TortoiseSVN
  • VisualSVN
  • HTC Touch Pro (Sprint) phone as modem over USB and Bluetooth
  • Firefox 3
  • WinRAR
Sunday, March 22, 2009 6:49:51 PM (Central Standard Time, UTC-06:00)
# Sunday, March 08, 2009
I have a client that uses Storis as his point-of-sale system. We've got a C#/ASP.NET app running on their intranet that monitors and reports on some other systems, and we wanted to add Storis to the mix. Storis uses IBM UniData as its back end, so this is where we started.

One of the things we got from Storis was a UniData Client CD, which includes an Admin, the UniDK, UniData ODBC, VSG, UniTools, and Dynamic Connect. Included in the UniDK are an OLEDB driver and UniObjects.NET. You might think that UniObjects.NET was the thing to use but that is not what we discovered. We WERE able to pull data out of Storis with UniObjects.NET, but the data was in its native form and SQL was not available. We had to do weird stuff, like query a table for its keys, get them in an array, and then query the table again by its keys. You couldn't just pull back data where Date >= '2009-03-08', for example. At least in no way that was apparent to us.

We installed all that stuff, but it turns out not all of it is necessary. We ended up only using the ODBC driver and VSG.

How we did it:
  1. Install the ODBC Driver
  2. Edit the C:\IBM\UniDK\Config\uci.config file, adding this to the bottom:
    <storis>
    DBMSTYPE = UNIDATA
    network = TCP/IP
    service = udserver
    host = [your storis IP address]
  3. Add an ODBC System DSN
    1. Click Administrative Tools - Data Sources. Note that on a 64-bit system, you will need to access the 32-bit ODBC applet, which you can get to (on Vista x64, for example) in Control Panel -> View 32-Bit Control Panel Items
    2. On the System DSN Tab, Click Add...
    3. Select the IBM UniData ODBC Driver
    4. Click Finish
  4. Configure the DSN
    1. Select your DSN from the list
    2. Click Configure...
    3. Give it a Data Source Name. We went with "StorisUnidata"
    4. For the server, specify "storis", which is the first line you added to the uci.config file above.
    5. Specify your Database name. In the UniData world, they often refer to this as the Account Name, which is a little confusing.
    6. For the User, specify a windows account that can access your database. To eliminate permissions issues, we started with a local system administrator account. We entered that account name under User.
    7. Click OK.
  5. Before you can access your data with SQL, you need to use the Visual Schema Generator to create a SQL Mapping:
    1. Prepare yourself, because this app is a bit ugly :). Think Lotus Notes...
    2. Launch the VSG
    3. This is just like configuring the DSN:
      1. For the server, specify "storis", which is the first line you added to the uci.config file above.
      2. Specify your Database name. In the UniData world, they often refer to this as the Account Name, which is a little confusing.
      3. For the User, specify a windows account that can access your database. To eliminate permissions issues, we started with a local system administrator account. We entered that account name under User.
      4. Enter the password for that windows account.
      5. Click OK.
    4. Click List on the Main Menu, to see all your tables.
    5. Select a table, such as SALES.FLASH.DAILY
    6. Click Open. Note that the dots are illegal in SQL table names, so they will be changed to underscores.
    7. It was not necessary for us to configure any privileges. Possibly because the account was an admin. You may wish to try an Administrator account first as well, then come back here to refine the permissions after you have it working.
    8. Click Map Attributes
    9. Click the columns you want, and hit Add. You may be prompted to rename your column, swapping out illegal characters with underscores.
    10. Click OK.
    11. Click Close.
    12. Hit List on the Main Menu and you should see your SQL Table listed in the right column.
    13. You can exit VSG.
  6. At this point, you should be able to access data in your Storis database via ODBC. So if you're an Access user, you're just about done. You can create a linked table in your usual way, specifying this DSN for your connection information. For .NET programmers, continue:
  7. Your ConnectionString will look something like this: <add key="StorisSystemDsn" value="dsn=StorisUnidata;srv=storis;dbq=YourDatabaseName;uid=YourUserName;pwd=YourPassword;" />
  8. If you're using the Enterprise Library Data Access Application Block (DAAB), your connection string will look more like: <add name="StorisOdbc" connectionString="dsn=StorisUnidata;srv=storis;dbq=YourDatabaseName;uid=YourUserName;pwd=YourPassword;" providerName="System.Data.Odbc" />
  9. You're ready to code!
  10. If your server is 64-bit, your app will not be able to load the 32-bit ODBC driver, and as far as I know, no 64-bit one is available. To get it working in IIS7 on a 64-bit box:
    1. Create a new application pool, and call it something like StorisApp32
    2. In its Advanced Settings, Set Enable 32-Bit Applications to True.
    3. Set your app to use this application pool.
    4. It will now run in 32-bit mode and load the ODBC driver.
    5. You do not have to change the way you compile (no need to specify x86 only, or anything like that).
Grab some data and bind it to a GridView called gvRecords like this:
OdbcConnection odbcConnection = new OdbcConnection(ConfigurationManager.AppSettings["StorisSystemDsn"]);
OdbcDataAdapter odbcDataAdapter = new OdbcDataAdapter("select * from from SALES_FLASH_DAILY", odbcConnection);
DataSet dataSet = new DataSet();
odbcDataAdapter.Fill(dataSet);
gvRecords.DataSource = dataSet.Tables[0];
gvRecords.DataBind();
If using the Enterprise Library, try this:
Database db = DatabaseFactory.CreateDatabase("StorisOdbc");
DbCommand dbCommand = db.GetSqlStringCommand("select * from from SALES_FLASH_DAILY");
DataSet dataSet = db.ExecuteDataSet(dbCommand);
gvRecords.DataSource = dataSet.Tables[0];
gvRecords.DataBind();
That worked for us, and I hope it works for you!

Notes: I was not able to get the OLEDB Driver to work. I kept getting errors about the provider name not being correct. I tried different provider names, even using a script to get the exact name registered with the system, but to no avail. If you get it working, please leave a comment with some instructions :)

Sunday, March 08, 2009 11:25:23 AM (Central Standard Time, UTC-06:00)
# Friday, March 06, 2009
You might see OPTION=3 in your MySQL connection string. That number--3 in this case--is the sum of a couple MySQL option flags. In this case, it's
  1. FLAG_FIELD_LENGTH: "Do not Optimize Column Width", and
  2. FLAG_FOUND_ROWS: "Return Matching Rows
So, that option setting allows you to direct your MySQL server to behave in a specific manner for the duration of each connection. A complete table of these options is available in the MySQL 5.0 Reference Manual.

You might also want to use OPTION=67108864, which allows you to execute multiple sql statements in a single MySQL Connector/ODBC batch, separated by semicolons. To keep other things working the way most people expect, just use 67108867, which is all three options combined.

Friday, March 06, 2009 6:00:23 PM (Central Standard Time, UTC-06:00)
# Friday, February 20, 2009
If you've got the Enterprise Library installed and already know how to connect to SQL Server databases, connecting to MySQL databases is not any harder.

One way to do it is to use ODBC. This is what I did:
  1. Go to MySQL.com and download the latest MySQL ODBC connector. As I write this it's 5.1.5. I used the 64-bit version, as I have 64-bit Vista.
  2. Install the ODBC Connector. I chose to use the no-installer version. I just unzipped it and ran Install.bat at an administrator's command prompt. The MSI version probably works fine, but I did it this way back when I installed the 3.51 connector.
  3. Verify the installation by opening your ODBC control panel and checking the Drivers tab. You should see the MySQL ODBC 5.1 Driver listed there. It seems to even co-exist peacefully with the older 3.51 version if you already have that. Additionally it coexists peacefully with the .NET connector if that is installed too.
  4. At this point you will be doing what you've done to connect to a SQL Server database. All you need to know is what to use for a connection string.
  5. Here's what mine looks like:
    <add name="MySqlDatabaseTest" connectionString="server=myservername;database=mydbname;uid=myusername;pwd=mypassword;driver={MySQL ODBC 5.1 Driver};option=3;" providerName="System.Data.Odbc" />
  6. Of course you can set "name" to whatever you want.
  7. If this is your only database, you can set it up as the defaultDatabase like this: <dataConfiguration defaultDatabase="MySqlDatabaseTest"/>
  8. Access your data in your code like you always do! Here's a plain text sql example:
public List<Contact> Contact_SelectAll()
{
    string sql = string.Format(@"
        select
            *
        from
            Contact
    "
);

    List<Contact> contactList = new List<Contact>();
    Database db = DatabaseFactory.CreateDatabase("MySqlDatabaseTest");
    DbCommand dbCommand = db.GetSqlStringCommand(sql);
    using (IDataReader dataReader = db.ExecuteReader(dbCommand))
    {
        while (dataReader.Read())
        {
            Contact contact = new Contact();
            contact.ID = (int) dataReader["ContactID"];
            contact.FirstName = dataReader["ContactFName"].ToString();
            contact.LastName = dataReader["ContactLName"].ToString();
            contactList.Add(contact);
        }
    }

    return
contactList;
}
Another way to do it is to build and use a MySql provider. This guy did that.
I learned how to do this by adapting these instructions for connecting to Access.
Oh, and here are some more MySql Connection String samples.

Friday, February 20, 2009 1:00:42 AM (Central Standard Time, UTC-06:00)
# Tuesday, February 17, 2009
For the longest time my HTC Touch Pro has told me I've got a voicemail, but it's wrong. I don't. It somehow got out of sync. The phone has a way to reset the voicemail indicator, but it's buried pretty well. How to reset the voicemail indicator of your Windows Mobile 6.1 device:
  1. Hit the "Phone" button like you would to place a call.
  2. Instead of dialing the number, tap "Menu".
  3. Tap "Options".
  4. Navigate to the "Services" tab.
  5. Choose "Voicemail" from the list box.
  6. Click "Get Settings..."
  7. Hit the "Clear" button.
  8. Press "ok" to close the window.
Your main screen should reflect this action immediately, and should not indicate that you have a voicemail!

Tuesday, February 17, 2009 1:35:27 PM (Central Standard Time, UTC-06:00)
# Monday, February 02, 2009
The Event Log shows: "Volume Shadow Copy Service error: An internal inconsistency was detected in trying to contact shadow copy service writers."

I noticed that if, at a command prompt, I ran "vssadmin list writers", I got nothing back. I was under the impression that all the VSS-compatible writers should be listed, such as SQL Server.

This was KILLING ME all morning. I'd been running backups just fine on this server for the longest time, and it stopped working. I think it was related to my uninstallation of Windows Desktop Search 4.0, but the KB article related to that didn't help. Maybe it was some update? Other articles and forum posts suggesting that I stop the VSS and SWPRV services and register a bunch of DLLs didn't help either.

Finally I found the solution. Well, it worked for me anyway. It was a variation of a forum post I found in google's cache. Here's what I did:
  1. Remove the registry key "HKLM\Software\Microsoft\EventSystem\{26c409cc-ae86-11d1-b616-00805fc79216}". You should probably export it first so you can restore it if this doesn't work for you.
  2. Reboot.
  3. The key is re-created.
  4. "vssadmin list writers" returns several writers.
  5. The Backup Utility no longer hangs on "Preparing to backup using shadow copy..." longer than maybe 20 seconds. The backup runs normally now!
This server is a VMWare virtual machine, in case that matters.

Monday, February 02, 2009 1:49:44 PM (Central Standard Time, UTC-06:00)