Saturday, March 15, 2008

The .NET Dataset for Stored Procedures in Visual Studio – the easy way

In case you need to call or retrieve data from a lot of stored procedures in SQL Server. You basically have two options:

A) “Hardcore”

You create your own class and define a SqlCommand object for each stored procedure manually. While doing this, tell your wife you can't see her for the next weeks

B) “Lazy man”

You use a dataset and let Visual Studio do the hard work. You use those generated procedure, tell your boss how many hours this took and leave early to enjoy your weekend.


The last option seems to be better IMHO, but the DataSet has some funny glitches that can make using it a pain. I’ll try to sort them out here.

Step 1: Create a dataset

Easy, just right-click your project, select “Add item” and choose “Dataset”. In this case, the dataset is called “DataSetStoredProcedures”.

Step 2: Move the generated dataset

To not clutter the project, create a new folder (right-click project, “Add” -> “New Folder”) called “DatabaseDataset”. Drag and drop “DataSetStoredProcedures.xsd” there.

Step 3: Add stored procedures

Select “View” -> “Server Explorer” to display the Server Explorer window. Right-click “Data Connections” and select “Add Connection”. Define the properties so Visual Studio can connect to the database. Open the new entry in the tree view and move to “Stored Procedures”.


In case you haven’t opened DataSetStoredProcedures.xsd, simply double-click it. Simply drag and drop the stored procedures you want to use to this window.

You may be asked how the connection should be called that will be used to execute this stored procedure, simply choose a name that makes sense to you. Once this all has being done, the project should look something like this:


Step 4: Check the stored procedures

At any time, you can simply click on a stored procedure, open the properties window and click on the “…” button for the Parameters:


You should do this simply because sometimes the generation is not done right. For example, in this project there is a user defined function (yes, you can also add UDFs) called “fncLTC2UTC” that return an SQL Server datetime value. However, the dataset converted this to “Object”. By using the parameters collection, you can simply change the value of @RETURN from object to DateTime.

Step 5: The glitches, Part I

By using the object browser, you can have a look at the namespace layout:


The project where we have added all this is called “x.server”. Because we have created a subfolder to put the dataset in, the namespace of the dataset has become “x.server.DatabaseDataset”. Beside this, the stored procedures where create in a sub object “QueriesTableAdapter” that has the namespace “x.server.DatabaseDataSet.DataSetStoredProceduresTableAdapters”:

Now this is a hell of a namespace we need to add it before we can call a stored procedure:


using x.server.DatabaseDataset.DataSetStoredProceduresTableAdapters;

class JustTesting
{
public static void Test1()
{
QueriesTableAdapter qta = new QueriesTableAdapter();
qta.procClientAuthentication_GetLoginData(…


Step 6: The glitches, Part II

Beside this namespace glitch, there is another one: By default, the dataset insists on using the connection string that each stored procedure has attached to (Properties viewer) and you can not to change this. In case you do not want to have the database connection inside app.config this would normally stop the use of the dataset.


Step 7: The solution

However, both glitches can easily be fixed. Within your normal namespace (e.g. “x.server”) simply define a class like this:


using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using x.server.DatabaseDataset.DataSetStoredProceduresTableAdapters;

namespace x.server
{
///


/// Shortcut class to all database stored procedures (procXXX).
///
public class DatabaseProcs:QueriesTableAdapter
{
public DatabaseProcs()
: base()
{
string sConnString = “Your Connection string here”;
foreach (IDbCommand cmd in CommandCollection)
{
cmd.Connection.ConnectionString = sConnString;
}
}
}
}



This class solves the two glitches: You need to reference the namespace only in this class (DatabaseProcs), all other objects that will use this class do not need to do it.

Second, DatabaseProcs is derived from QueriesTableAdapter so it can use the protected property “ConnectionString” and change it to anything you want.

With this class in between, calling a stored procedure is quite simple:


using System;
using System.Collections.Generic;
using System.Text;

namespace x.server
{
class JustTesting
{
public static void Test1()
{
DatabaseProcs procs = new DatabaseProcs();

procs.procClientAuthentication_GetLoginData(…




No more stupid namespaces and you your custom connection string is also set.


Note

The generated class will also leave the connection in the same state as it was before. This means, when you use the class DatabaseProcs (aka “QueriesTableAdapter”) like this, a connection will be opened when you execute it and closed right after that.

This might lead to a performance issue if you do not use connection pooling. To enable connection pooling simply use a connection string like this:


Data Source=(local)\SQLEXPRESS;Initial Catalog=X;Integrated Security=True;Pooling=True;Min Pool Size=0;Max Pool Size=5;Application Name=MyApp


If pooling is activated, a Connection.Close() does not actually close the connection but instead it will put the connection in the pool and reuse it when the next request to Connection.Open() comes in.


Enjoy!

Wednesday, March 5, 2008

Java Embargo

Okay, I know Germany and the USA had their problems in the past. But this is going too far...

Tuesday, February 26, 2008

Backup Exec 12: Error "The Backup Exec Server Service detected a schema version mismatch."

[UPDATE] The exact same can happen in BE 12.5. See this post for details. [/UPDATE]

I just tried to update our Backup Exec 11d SP1 to Backup Exec 12 and although all pre-checks were okay and the installation did also not issue any errors, BE didn't started. Checked the event log and the following events were logged:

The Backup Exec Server Service detected a schema version mismatch.

and

The Backup Exec Server Service did not start. An internal error (-536813108) occurred in object 1.

Oh, I really love database schema errors. According to the Symantec support website (http://seer.entsupport.symantec.com/docs/283038.htm or http://seer.entsupport.symantec.com/docs/254014.htm) you need to recreate the entire database if this error happens which means you need to recreate everything from scratch! Thanks for nothing buddy!

Using SQL Server Profiler, I was able to figure out what the problem was. BE uses two tables as schema reference: ControlInfo and Version (you can simply install the SQL Server Mngmt Studio Express and issue an "select * from …" for these two). In this case here, ControlInfo was okay (Version 12.0) but Version still had 11 for some components listed.


There are two SQL files you need to execute against your BEDB database (using Mngmt Studio Express for example):

C:\Program Files\Symantec\Backup Exec\dbupgrade11.5.sql

If there are any errors, you may ignore them.


Once this has run, run

C:\Program Files\Symantec\Backup Exec\dbupgrade11.5-viewandsp.sql

Inside this file, there might be a problem with the following command:

-- sync with bedb.sql version, 1.644

ALTER TABLE [dbo].[Alert] ADD

CONSTRAINT [DF_Alert_UMI] DEFAULT (N'') FOR [UMI]

GO


Simply delete these lines and the script will run to the end. Restarting Backup Exec should now show that BE does no longer throw an schema mismatch error.


Enjoy!

Monday, February 18, 2008

Setting the right font for a Windows Forms application

If you create a new form in Visual Studio, the default font will always be "Microsoft Sans Serif" although you should use a font that depends on the Windows version you are running on. For Windows 2000, XP, Server 2003 you should use "Tahoma" for Vista and above it should be "Segoe UI". In any case, do not use "MS Sans Serif".

Unfortunately, there is no simple property available so the form uses the correct font automatically. Benjamin Hollis has a blog entry about this problem already and his code is quite simple and works quite well.

It just does not take into account if a form contains other, specialized fonts or if the fonts used have special styles (Underlined, Italics etc.) applied. I have tweaked his code a little bit.. ähm.. a lot actually and this is the result: FormFontFixer.

UPDATE: The code is now licensed under a BSD license (see below)


//Original idea and code (3 lines :-) by Benjamin Hollis: http://brh.numbera.com/blog/index.php/2007/04/11/setting-the-correct-default-font-in-net-windows-forms-apps/
//Copyright (C) TeX HeX of Xteq Systems: http://texhex.blogspot.com/ and http://www.texhex.info/
public static class FormFontFixer
{
//This list contains the fonts we want to replace.
static readonly List<string> FontReplaceList
= new List<string>( new string[] { "Microsoft Sans Serif", "Tahoma" } );


static Font _DefaultFont;
static bool _CanFixFonts;


static FormFontFixer()
{
//Basically the font name we want to use should be easy to choose by using the SystemFonts class. However, this class
//is hard-coded (!!) and doesn't seem to work right. On XP, it will mostly return "Microsoft Sans Serif" except
//for the DialogFont property (=Tahoma) but on Vista, this class will return "Tahoma" instead of "SegoiUI" for this property!

//Therefore we will do the following: If we are running on a OS below XP, we will exit because the only font available
//will be MS Sans Serif. On XP, we gonna use "Tahoma", and any other OS we will use the value of the MessageBoxFont
//property because this seems to be set correctly on Vista an above.

if (Environment.OSVersion.Platform==PlatformID.Win32Windows)
{
//95, 98 and other crap
_CanFixFonts = false;
return;
}

if (Environment.OSVersion.Version.Major < 5)
{
//Windows NT
_CanFixFonts = false;
return;
}

if (Environment.OSVersion.Version.Major < 6)
{
//Windows 2000 (5.0), Windows XP (5.1), Windows Server 2003 and XP Pro x64 Edtion v2003 (5.2)
_CanFixFonts = true;
_DefaultFont = SystemFonts.DialogFont; //Tahoma hopefully
}
else
{
//Vista and above
_CanFixFonts = true;
_DefaultFont = SystemFonts.MessageBoxFont; //should be SegoiUI
}
}

public static void Fix(Form form)
{
//If we can't fix the font, exit
if (_CanFixFonts == false)
{
return;
}


//Now start with the real work...
foreach (Control c in form.Controls)
{
//only replace fonts that use one the "system fonts" we have declared
if (FontReplaceList.IndexOf(c.Font.Name) > -1)
{
//Now check the size, when the size is 9 or below it's the default font size and we do not keep the size since
//SegoiUI has a complete different spacing (and thus size) than MS SansS or Tahoma.

//Also check if there are any styles applied on the font (e.g. Italic) which we need to apply to the new
//font as well.

bool bUseDefaultSize = true;
bool bUseDefaultStyle = true;

//is this a special size?
if ((c.Font.Size <= 8) || (c.Font.Size >= 9))
{
bUseDefaultSize = false;
}

//are any special styles (bold, italic etc.) applied to this font?
if ( (c.Font.Italic == true) ||
(c.Font.Strikeout == true) ||
(c.Font.Underline == true) ||
(c.Font.Bold == true))
{
bUseDefaultStyle = false;
}

//if everything is set to defaults, we can use our prepared font right away
if ((bUseDefaultSize == true) && (bUseDefaultStyle == true))
{
c.Font = _DefaultFont;
}
else
{
//There are non default properties set so
//there is some work we need to do...


//Restrive custom font style
FontStyle Style = FontStyle.Regular;
if (bUseDefaultStyle == false)
{
if (c.Font.Italic) {
Style = Style | FontStyle.Italic;
}
if (c.Font.Strikeout) {
Style = Style | FontStyle.Strikeout;
}
if (c.Font.Underline) {
Style = Style | FontStyle.Underline;
}
if (c.Font.Bold){
Style = Style | FontStyle.Bold;
}
}

//Retrive custom size
float fFontSize = _DefaultFont.SizeInPoints;
if (bUseDefaultSize == false)
{
fFontSize = c.Font.SizeInPoints;

}

//Finally apply this font...
Font font = new Font(_DefaultFont.Name, fFontSize, Style, GraphicsUnit.Point);
c.Font = font;

}
}
}

}
}


Copyright (c) 2008, TeX HeX (http://www.texhex.info/)

All rights reserved.

Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:

* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
* Neither the name of the Xteq Systems (http://www.xteq.com/) nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

Saturday, February 16, 2008

Security Neutral Mutex

We have just completed a project where we had a very “strange” requirement: A Mutex that is normally created by a service but might also be changed or created by the application running as a limited user. Before .NET, we would simply have created a Mutex with a NULL DACL but this is no longer possible because the Mutex Class will actively prevent this.

Fortunately, we found a blog post where the author simply created a Mutex and give EVERYONE full rights on the Mutex which is basically the same as a NULL DACL: http://rdn-consulting.com/blog/2007/09/14/more-on-using-a-named-mutex-in-vista/

We changed the code a little bit and here is the result:


//Original Code: http://rdn-consulting.com/blog/2007/08/20/kernel-object-namespace-and-vista/

public static Mutex Create(string Name)
{
bool bTrash;
return Create(Name, out bTrash);
}

public static Mutex Create(string Name, out bool MutexWasCreated)
{
//Always use global scope
string name = @"Global\" + Name;

MutexSecurity sec = new MutexSecurity();

MutexAccessRule secRule = new MutexAccessRule(

new SecurityIdentifier(WellKnownSidType.WorldSid, null),

MutexRights.FullControl, AccessControlType.Allow);

sec.AddAccessRule(secRule);

bool mutexWasCreated;

Mutex m = new Mutex(false, name, out mutexWasCreated, sec);

MutexWasCreated = mutexWasCreated;

return m;

}

Friday, February 8, 2008

XQGetOSVer 3.0 available

We have just released Xteq Systems GetOSVersion 3.0 (XQGetOSVer).

XQGetOSVer returns a number for each detected OS (Windows 95 up to Windows Server 2008) and can therefore easily be used for batch files where you want to execute special commands depending on the OS in use.

Thursday, January 31, 2008

WiX Toolkit (Windows Installer) Custom actions and conditions

Normally, for setup projects I use InnoSetup from Jordan Russel which is, put simple, the best setup creator you will find.

However, for a project I was forced to produce a Windows Installer package and used the WiX toolkit for it. Basically, after several dead-ends I was finally completely stuck. I simply wanted to have Windows Installer executing a custom action on every install of the application, regardless if it's already installed or not. If the application is being removed, my custom action shouldn't be executed.

By default, you would simply use the condition "NOT Installed" which means: If the application is not installed, execute it. Else, leave it alone. But as I said I wanted it to be execute every time somebody issues a command like MSIEXEX /I MyProduct.msi. The default condition would evaluate to FALSE (since the application is already installed) and thus, the custom action isn't started. Of course, you could pass /fa to MSIEXEC.exe but I feared this would be forgotten and thus I would get more "Nothing is working here calls".

After searching and testing for nearly two hours (and found an excellent post about custom actions and properties from Jeff Wharton) I was able to find the correct solution:

<custom action="LaunchExe" after="InstallInitialize">NOT (REMOVE="ALL")</custom>

This simply means: If the application is NOT being removed, execute the custom action.

If you know how, it's simple.

Thursday, January 24, 2008

Using caspol.exe to change .NET security policy - done right

Maybe you know CASPOL.exe to modify or add your own security policy for the .NET Framework.

Most examples you will find on the internet will simply add a code group to the configuration and most people use it this way: Upon each installation, CASPOL.EXE is exeucted.

What most people not realize is that CASPOL does not remove the old group when adding a new one with the same name. See this screenshot:

This is no broken installation, for .NET everything is fine even if 100+ groups with the same name would exist. However, for the user this looks like a bug so he will call support. To make things even worse: When you have changed the group membership of your custom group later on you will end up with two groups with completely different membership conditions.

To avoid this, I developed the following batch file that you can use and customize. The basic trick is to first list all available groups and if the script finds one that has the same name, it will be deleted.

For more information about CasPol.exe, see MSDN.

Enjoy!


@echo off
Rem .NET Framework 2.0 CasPol.exe batch by TeX HeX
Rem http://texhex.blogspot.com
Rem Version 1.0

Rem Set this to the name of the group you want to create
SET GROUP=Testing123
Rem Set this to the description your group should have
SET GROUPDESC=Just testing group

SET CASPOL=%WINDIR%\Microsoft.Net\Framework\v2.0.50727\caspol.exe
SET ERRLVL=9

echo ---- Setting prompt off ----
%caspol% -polchgprompt off

Rem Check if this group exists already
echo ---- Check group existence ----
%caspol% -m -ld|find /C /I "%GROUP%"
IF NOT ERRORLEVEL 1 GOTO DELETE_GROUP
GOTO CREATE_GROUP


Rem Deleting old group (two times to make sure that we do not have one left over)
:delete_group
echo ---- Removing old group ----
CASPOL% -m -remgroup "%GROUP%"
CASPOL% -m -remgroup "%GROUP%" >NUL


:create_group
echo ---- Creating group ----
REM %CASPOL% -m -addgroup All_Code -url "\*" -zone MyComputer FullTrust -name "%GROUP%"
REM %CASPOL% -m -addgroup All_Code -strong -file c:\arg.dll -noname -noversion FullTrust -name "%GROUP%" -description "%GROUPDESC%"

%CASPOL% -m -addgroup All_Code -zone MyComputer FullTrust -name "%GROUP%" -description "%GROUPDESC%"
SET ERRLVL=%ERRORLEVEL%

echo Result is %ERRLVL%

Rem Patch prompting again
echo ---- Setting prompt on ----
%caspol% -polchgprompt on



Rem Now check the result
IF %ERRLVL% EQU 0 (
echo "All fine!"
exit 0
) ELSE (
echo "Error!"
exit -1
)




Monday, January 21, 2008

New Snom Auto update script

Since Snom does now offer the v7 firmware officially, it was time to update my Snom update script. That's because the transition to v7 must be done if a very special way (first firmware 6.5.15, then linux 3.38 and then the special update firmware).

Before you can use this script, you need to create several folders to include the parts you need to do the update:
  • /v6: includes the 6.5.15 firmware which is needed to update to v7 (snom3X0-6.5.15-SIP-j.bin)
  • /v6ux: includes the 3.38 Linux system also needed for v7 but can only be installed once the firmware is 6.5.15 (snom3X0-3.38-l.bin)
  • v6to7: this folder includes the special firmware that will update v6 to v7 while keeping all settings (snom3X0-update6to7-7.1.30-bf.bin)
  • v7: the normal firmware files for phones that already have v7 installed
All these files can be downloaded from http://wiki.snom.com/Firmware/V7/Update_Description.

To test it, you can simply use an URL like .../snom-firmware.asp?UA=Mozilla/4.0+(compatible;+snom320-SIP+6.5.15;+snom320+jffs2+v3.36;+snom320+linux+3.38) which will tell the script you would like to use the User agent of a Snom 320.

Once all these files are in place, you might use the following ASP script:




# Auto Update Skript
# Coypright (C) 2007-2008 TeX HeX
# http://texhex.blogspot.com
# All Rights Reserved

<%
'Example URLs (for testing):
'.../snom-firmware.asp?UA=Mozilla/4.0+(compatible;+snom320-SIP+6.5.10;+snom320+jffs2+v3.36;+snom320+linux+3.25)
'.../snom-firmware.asp?UA=Mozilla/4.0+(compatible;+snom320-SIP+6.5.15;+snom320+jffs2+v3.36;+snom320+linux+3.38)
'../snom-firmware.asp?UA=Mozilla/4.0+(compatible;+snom320-SIP+7.1.30)
'Definition of download URLs
URL_BASE="http://my-server.internal.company.com/snom"

URL_BASE_V6=URL_BASE & "/v6"
URL_BASE_V6_UX=URL_BASE & "/v6ux"
URL_BASE_V6TO7=URL_BASE & "/v6to7"
URL_BASE_V7=URL_BASE & "/v7"

URL_V6_FW_300=URL_BASE_V6 & "/snom300-6.5.15-SIP-j.bin"
URL_V6_FW_320=URL_BASE_V6 & "/snom320-6.5.15-SIP-j.bin"
URL_V6_FW_360=URL_BASE_V6 & "/snom360-6.5.15-SIP-j.bin"

URL_V6_UX_300=URL_BASE_V6_UX & "/snom300-3.38-l.bin"
URL_V6_UX_320=URL_BASE_V6_UX & "/snom320-3.38-l.bin"
URL_V6_UX_360=URL_BASE_V6_UX & "/snom360-3.38-l.bin"

URL_V6TO7_FW_300=URL_BASE_V6TO7 & "/snom300-from6to7-7.1.30-bf.bin"
URL_V6TO7_FW_320=URL_BASE_V6TO7 & "/snom320-from6to7-7.1.30-bf.bin"
URL_V6TO7_FW_360=URL_BASE_V6TO7 & "/snom360-from6to7-7.1.30-bf.bin"

URL_V7_FW_300=URL_BASE_V7 & "/snom300-7.1.30-SIP-f.bin"
URL_V7_FW_320=URL_BASE_V7 & "/snom320-7.1.30-SIP-f.bin"
URL_V7_FW_360=URL_BASE_V7 & "/snom360-7.1.30-SIP-f.bin"
'''URL_V7_FW_370=URL_BASE_V7 & "/snom370-7.1.30-SIP-f.bin"

'----------STOP EDITING-------------------
Dim CRLF
CRLF=chr(13) + chr(10)

Function Log(Text)
Response.Write("# " & Text)
Response.Write(CRLF)
End function

Function SendOutFirmware_V6
Log("Sending v6 Firmware")
Call SendOutFirmware(URL_V6_FW_300,URL_V6_FW_320,URL_V6_FW_360)
End Function

Function SendOutLinux_V6
Log("Sending v6 Linux")
Call SendOutFirmware(URL_V6_UX_300,URL_V6_UX_320,URL_V6_UX_360)
End Function

Function SendOutFirmware_V6to7
Log("Sending v6 to v7 Firmware")
Call SendOutFirmware(URL_V6TO7_FW_300,URL_V6TO7_FW_320,URL_V6TO7_FW_360)
End Function

Function SendOutFirmware_V7
Log("Sending v7 Firmware")
Call SendOutFirmware(URL_V7_FW_300,URL_V7_FW_320,URL_V7_FW_360)
End Function


Function SendOutFirmware(url300, url320, url360)
'Only write out "firmware:"" tag if it's in the night (21:00 = 9 PM, 05:00 = 5 AM)
if ( (hour(now())>=21 or hour(now())<=5) or sNow="1" ) then
'if true then
Dim sURL

pos=InStr(sUA,"snom300")
if pos>0 then
sURL=url300
end if

pos=InStr(sUA,"snom320")
if pos>0 then
sURL=url320
end if

pos=InStr(sUA,"snom360")
if pos>0 then
sURL=url360
end if

if len(sURL)>0 then
Response.Write("firmware: " + sURL)
Response.Write(CRLF)
else
Log("Unable to get download URL!")
end if
else
'Debug output, I don't think Snoms can actually undestand this :)
Log("Firmware download disabled: It's not in the night! We have now: " + cstr(now()) )
end if
End Function


Dim sUA
sUA=Request.QueryString("UA")
if len(sUA)=0 then
Log("Parameter UA is empty, defaulting to HTTP_USER_AGENT")
sUA=Request.ServerVariables("HTTP_USER_AGENT")
Response.Write(CRLF)
end if

Dim sNow
sNow=Request.QueryString("Now")

'Debug output, just for reference
Log("Parameter [USER AGENT] is --> " + sUA)

Log("Parameter [Now] (direct update) is --> " + sNow)


'Try to find out the current firmware version
Dim iPosStart,iPosEnd,sTmp
iPosStart=0
iPosEnd=0
sTmp=""

'Start searching
Log("Searching firmware version")
iPosStart=InStr(sUA,"-SIP")
if iPosStart>0 then
sTmp=Right(sUA,len(sUA)- (iPosStart+4)) '+4 to cut the "SIP " part
Call Log("Version sniffing - part 1: " + sTmp)

'now search for next ;
iPosEnd=InStr(sTmp,";")
if iPosEnd>0 then
sTmp=left(sTmp,iPosEnd-1)
Call Log("Version: " + sTmp)
else
'maybe a new 7.x phone - search for ")"
iPosEnd=InStr(sTmp,")")
if iPosEnd>0 then
sTmp=left(sTmp,iPosEnd-1)
Call Log("Version: " + sTmp)
end if
end if
end if

'Log sTmp

Dim sCurVersion
sCurVersion=""

'Now check if the version can be found!
if iPosStart<=0 or iPosEnd<=0 then
'No version info found, send to last v6 release!
Call Log("No version info found!")
Call SendOutFirmware_V6()
else
'Okay, we have a version! If this is 6.5.15 we need to send out the newest linux!
sCurVersion=sTmp
Call Log("Found version: " & sCurVersion)

if CInt(left(sCurVersion,1))<=6 and sCurVersion<>"6.5.15" then
Call Log("Version is 6 or below but not 6.5.15!")
Call SendOutFirmware_V6()
else
'Is this 6.5.15?
If sCurVersion="6.5.15" then
'Do we need to do a linux update?
iPosStart=0
iPosEnd=0
sTmp=""

Log("Searching linux version")
iPosStart=InStr(sUA," linux")
if iPosStart>0 then
sTmp=Right(sUA,len(sUA)- (iPosStart+6)) '+4 to cut the " linux" part
Call Log("Version sniffing - part 1: " + sTmp)

'now search for )
iPosEnd=InStr(sTmp,")")
if iPosEnd>0 then
sTmp=left(sTmp,iPosEnd-1)
Call Log("Version: " + sTmp)
end if
end if

if iPosStart<=0 or iPosEnd<=0 then
Log("Unable to find linux version!")
else
if sTmp<>"3.38" then
Log("Version to old, sending new linux!")
Call SendOutLinux_V6()
else
'Firmware is 6.5.15 and linux version okay!
'-> Update to 7.1.30!
Call SendOutFirmware_V6to7()
end if
end if
else
'Firmware is not 6.5.15/UX 3.38, more like 7+
Call SendOutFirmware_V7()
end if
end if
end if



Log("Done!")

%>





Monday, January 14, 2008

SOME of your network connections are down

SOME of your network connections are down...

Wednesday, January 9, 2008

Lost in translation: ASC16-UTF8-1252

As soon as you start to deal with any string data, you need to make sure of which character encoding type this string is. The most commonly used are ASCII, ISO-8859-1, Windows-1252 and the two Unicode encodings UTF-8 and UTF-16.

Normally, you can fully ignore which character encoding you are using but as soon as you need to communicate with an external source, or need to make sure in which format an external data source is, you need to know the encoding.

Here is the list of the most commonly used encodings:

ASCII (http://www.asciitable.com/) is very old but still very widely used. Every character consists of one byte but only the values 0 – 127 are defined which makes it 7 bit. The characters between 128 and 255 (8 bit) are so called "Extended ASCII" and which characters they map can be defined in a codepage. This means: If you are using data that contains ASCII characters about 127, you need to make sure that sender and receiver use the same codepage.

ISO-8859-1 Latin-1 (http://en.wikipedia.org/wiki/ISO/IEC_8859-1) is very widely used in the internet since it's the default encoding for the "text/" MIME type. Basically it's a codepage that maps 0 – 127 to the same characters like ASCII, 128 and above to several characters of the Latin alphabet.

Windows-1252 (http://en.wikipedia.org/wiki/Windows-1252) is based on ISO-8859-1 and is still the most used codepage for Windows. It differs in the 0x80 to 0x9F range which contains non-printable characters in ISO-8859-1 but printable characters on Windows-1252.

UTF-8 (http://en.wikipedia.org/wiki/Utf-8) is a Unicode character encoding that again maps 0 – 127 like ASCII but can also display all Unicode characters. UTF-8 is a variable-length encoding which means the values 0-255 is mapped to one byte, like in "Extended ASCII", but UTF-8 can use two, three or even four bytes per character when needed. Because of this variable-length encoding and the backward compatibility with ASCII, it is the encoding you should use.

UTF-16 (http://en.wikipedia.org/wiki/UTF-16) is also a Unicode character encoding but maps 0 – 127 differently from ASCII and uses only two or four bytes per character. Because of this it requires more data space and should only be used if you need to use. Use UTF-8 in any other case.

Monday, December 31, 2007

Strange Delphi Bug – again

It really seems that somebody at Borland/CodeGear hates me. Why? Because with every new release of Delphi I run into a very strange bug. This time: The type library editor on Vista “can’t rename XXX.$$$ to XXX.tlb”.

The first message of this bug will be “Can’t copy XXX.tlb to __history\XXX.~1~” (or something like that). Okay, no problem simply switching off backup copies (Preferences – Editor) and you are done. Not really, since now Delphi will throw a new error “Can’t rename XXX.$$$ to XXX.tlb”. Checking with Process Monitor reveals that Delphi itself (BDS.exe) is locking the TLB file. Nice, isn’t it?

Looking a little bit around and it seems this bug only appear when Delphi is installed on Vista AND the type library you are editing has a reference to OLE Automation v1.0 (stdole32.tlb). If the type library has a reference to OLE Automation v2.0 (stdole2.tlb) this bug won’t show up. The solution I found was to open the project on Windows XP, exchange the reference and reopen the project on Vista. But I don’t have an XP box anymore so the solution was a little bit strange:

Exchange the reference of OLE Automation v1.0 to v2.0 inside the Type Library Editor (Tab “Uses”), then try to compile the project. This will fail because of the “Can’t rename…” error. Anyway, copy the [FILENAME].$$$ from the project folder to a new folder while Delphi is running. Once this is done, close BDS (no, you can’t save the project because of the error). Now delete the old TLB file and rename [FILENAME].$$$ to [FILENAME].TLB and copy it to the project folder.

Start Delphi again, open the project and check if the “Uses” tab now says you are using OLE Automation Version 2.0. If so, everything should be back to normal again.

Thursday, December 27, 2007

I just want a !"§$% iPod bag!

Okay, I finally managed it to buy me a new iPod Classic 80GB since my 2nd generation iPod seems to have some gremlins.

As I know that Apple does no longer deliver a bag, I through it should be easy to get a bag from a 3rd party. Boy was I wrong.

You basically get everything, silicon slip-in cases, sports armband cases, charge cases, kitty cat cases.... But I just wanted a simple case. Means: Put the iPod in for transportation and put it out if you plan to use it or not.

Believe me or not, the only simple case I found was one from Marware: Sportsuit Sleeve for iPod classic and video.

Sometimes the simple things are just so hard to get.

Tuesday, December 11, 2007

Hostile Ad

Okay, I don't like Macs, I don't have one and I think Vista is better than MacOS X.

But this add is just so funny...


Wednesday, November 14, 2007

Windows Vista's Constant HD Activity Craziness

Any user that has used Windows XP and updating to Vista will notice one thing: In Vista, your hard drive thinks it's a bewitched lawnmower – it's always active. Even after all startup programs are loaded, the HD is still active: Vista's Constant HD Activity Craziness.

Beside the typical babble of "Microsoft is now reading all your files and sent them to Redmond to gain the world domination!" the funny thing is that I was not able to find a resource on the web that describes what Vista is doing all the time. Therefore I decided to write this little article and listing all processes that cause a lot of HD activity, what they are doing and how they can be configured.

Introduction

Especially the typical XP user switching to Vista will notice that the HD is much more used in Vista than it was in XP. But why are these users (like me) noticing this anyway? Because in XP HD activity usually meant: "I'm busy. Go away.". In Vista this is not necessarily true. Even if HD led is gleaming all the time, you can mostly use Vista as if there would be no HD activity – thanks to several changes Microsoft has done in Vista.

For example, several programs and services will now use an IO (Input/output) Priority of "Background". This simply means, if there is no work to do for the HD, these programs will get the full speed of it (e.g. 15 MB/sec). As soon as a program with "Normal" priority is started, e.g. you double-click the iTunes icon, this program is getting full access (15 MB/sec) and the "Background" program is delayed (0 MB/sec). This will start iTunes as fast as you would expect it although there is another program in the background that is using the HD heavily.

So, the first thing to notice is that a constantly flushing HD LED is not such a performance killer as it was in XP. Secondly, all these services I'm listing are basically good configured out of the box and worth the stress they put on your HD. Except for some configurations, you do not need to disable any reconfigure any of them.

Below I have noted the features of Windows that know I know so far that cause a lot of HD activity. For each feature, I also noted the process name that appears in "Resource Monitor" so you know what is currently executing. For a description how to start Resource Monitor, please look at the bottom of this article.


SuperFetch

Displayed in Resource Monitor as: svchost.exe (LocalSystemNetworkRestricted)

To understand what SuperFetch does, you first need to understand what is happening when you load a file (regardless if it's a program or a document like a PDF).

Any file you are dealing with needs to be put into memory before your CPU can use it. This means that the different chunks of the file need to be retrieved from your HD and loaded into memory.

Think of a file as a song on a platter and the HD is the record player for this platter. To retrieve the file, the pickup of the record player needs to be moved forwarded until the song (file) begins and then read it until it's over.

In an ideal world, all files are organized as the songs on a platter: Song 1, Song 2, Song 3. However, in real life it's more like Song 1 Part A, Song 2 Part B, Song 1 Part C, Song 2 Part A, Song 1 Part B etc. You see, the pickup needs to move a lot until it has collected the complete Song 1. This moving around the entire platter simply takes time.

If an HD can read a file in one "move" this is called sequential I/O (Input/Output) and it's very fast – you can expect 50 MB per second or more. However, if the HD needs several "moves" until it has found the entire song (Random I/O), it will drop to 3 MB per Second or even less.

And this is one of the scenarios where SuperFetch kicks in: SuperFetch will first try to optimize this moving so files (songs) can be retrieved faster. Given the example from above (Song 1 Part A, Song 2 Part B, Song 1 Part C, Song 2 Part A, Song 1 Part B) a "stupid" load would first retrieve Song 1 Part A, then Song 1 Part B, then Song 1 Part C.

SuperFetch would in this case retrieve Song 1 Part A, then Song 1 Part C, then Song 1 Part B (as C comes before B on the platter) and later on reorder them in memory. With this optimization the data is more sequential retrieved and thus faster. Of course, in this simple example you would not notice any performance gain but think of a song with 50, 200 or even 500 fragments.

The second optimizations sounds a little bit like Voodoo: SuperFetch will try to read data from the HD BEFORE it's actually needed.

A good example of this is that you launch, each time you start Windows, Firefox and Outlook. Because SuperFetch will learn this the start of either Firefox or Outlook is very fast simply because there is no HD activity anymore: the data is in the memory already.

Or, you might start a game during lunch. As you do it regularly, SuperFetch can learn over time that the data of this game is needed every day at 12:04 (four minutes until your boss has left the office:-). SuperFetch will in this case pre-load the data from the HD to the memory so when you start the program, Vista does not read it from the HD but has the data ready-to-use in memory.

You can also monitor this in task manager: Directly after you have started Windows, you have plenty of free memory and only some data inside the cache.

If you wait 1-4 minutes, the cache will be filled:

And before you ask: No, this memory is not gone and you do not need any stupid memory manager. If you start an application that requires memory, the cache will be cleared (in less than a second) and ready to be used by any application that requires it.

SuperFetch has some more strategies and if you are interested, watch this video:

http://channel9.msdn.com/showpost.aspx?postid=242429

If you wish to stop SuperFetch from doing this, simply disable the service "SuperFetch" (see the bottom of this article how to disable a service).


System Protection

Displayed in Resource Monitor as: System (with PID 4) accessing C:\System Volume Information

System Restore is a combination of two completely different techniques: Restore Points and Previous Version. By default, it runs on every system startup once a day and then on midnight.

Restore Points might be known from Windows XP already and helps to recover if Windows won't boot any more. It simply takes a backup of important system files and configuration information (Registry) and stores them. If Windows is unable to boot, you can use the DVD and repair your Windows. For example, if you install a new driver (which will trigger the creation of a restore point automatically) and this driver is crashing upon start, Windows will simply restore the Restore Point and can be started again.

Beside this restore, you can also use System Protection to go back to a Restore Point in Windows itself. This is mostly used if you system is acting "strange", but still boots and you don't know what this has caused.

The creation of a Restore Point is very fast, for example on my system it only takes round about 20 seconds.

After the creation of the Restore Point, previous versions will start which is a technique to create backup copies of your files. Every time it runs it will check if a given file has been changed since the last backup and if so, create a backup copy. You can access a previous version of a file by simply right-clicking it and opening the "Previous Versions" tab. If you have deleted a file, you can also right-click the folder where it was stored and select "Previous Versions". Windows will then display all previous versions it has saved from this folder and you can simply view the contents by clicking "Open".

The big difference between Previous Versions and a "normal" backup tool is that previous versions are using a technique called "Shadow Copies". When previous versions are instructed to start, it will first ask Windows to create a shadow copy of the entire drive. Windows will stop all write requests to the HD for some seconds and then create a virtual copy of your HD. The creation of the shadow copy only takes some seconds more and after that, previous versions will start to work with the shadow copy of your HD.

Although this sounds a little bit like magic creating a copy of a 100 GB HD in some seconds, you need to remember that this is only a virtual copy. This means, Windows will not create a 100 GB file called DISK.IMG. What shadow copy does is that it will, as soon as a file is changed, copy this file and include it in its virtual copy. If a file is not changed or deleted, shadow copy will simply use the file as it is on your HD. That's the reason why it will stop all requests for some seconds to copy the files that are currently accessed or changed. Explaining more detailed how shadow copies work would take too long, so if you interested see the technical documentation on http://msdn2.microsoft.com/en-us/library/aa384961.aspx or view the following video on Channel 9: http://channel9.msdn.com/Showpost.aspx?postid=286303

With the virtual copy of your HD shadow copies has created, previous versions will simply check each and every file if it has changed since it was last backed up. If so, a backup copy is saved. This will also be true for directories but only changes will be saved. For example, if you have added a new file to the folder "Desktop", previous versions will not save the entire contents of the folder with 30 or more files but only the one file that was added. Inside the display of the folder (using the previous versions folder tab and clicking on Open) you will of course see the entire contents of the folder.

The HD stress comes from the fact that previous versions need to access every single item on your HD so it needs to check every file and every folder for changes. Depending on how many files you have, this can take up to 30 minutes until previous versions is finished. When you start Vista, most of the HD activity you see will be from previous versions.

Known this, you maybe want to disable previous version but keep the Restore Points in case there is a driver problem. To make it short: You can't - you can only enable or disable both.

As previous versions took a very long time to create, you might also think about excluding several files where you do not need a backup copy. Previous versions already exclude several folder and files that belong to Windows automatically. There is also a registry key to define files or folders that should be excluded. But (and that's a huge BUT) this won't make the creation of previous versions any faster: "In addition, excluding files from shadow copies may slow down shadow copy creation." http://msdn2.microsoft.com/en-us/library/aa819132.aspx

Please keep in mind that you will need an extra of your data on an external HD or DVD anyway. Previous versions do not replace your normal backup! If you HD dies because of a hardware failure previous versions won't help anything since their backup copies have died together with your HD. Always backup to external media!

"System Protection" (aka. Restore Points and Previous Versions) is really worth the extra stress on your HD! If you ever delete a file by accident that was important and you do not have it on your normal backup (e.g. the typical "I will do the backup tomorrow!") it can save your life. In fact, the draft of this document was deleted and only previous versions were able to recover it.

Even if you don't plan to use previous versions, leave system protection enabled because of restore points. If you have ever stared on the almighty "Blue Screen Of Dead" directly when starting Windows, you really know what PANIC means.

However, if you know what you are doing you can of course disable System Restore:

Go to Control Panel, "System and Maintenance", "System" and click on this header.

Inside the appearing window select "System protection" on the left side.


Defrag

Displayed in Resource Monitor as: DfrgNtfs.exe

Out of the box, Windows is configured to run a defragmentation of your HD every week. Fortunately, defrag (DfrgNtfs.exe) is smart enough to not execute if your HD is not fragmented a lot. Unfortunately, as Vista puts a lot of stress on the HD, it usually take only some months until defrag thinks the HD need to be "cured" and thus will be running.

To configure this automatic defragmentation, go to Control Panel, "System and Maintenance", "Administrative Tools" and click on "Defragment your hard drive":

Inside the appearing windows you can change the schedule. Either set it to run only once a month or simply disable it and later on run it manually.

Keep however in mind the typical user is more likely to forget the defragmentation so having it run automatically is the better decision.


Indexing (Desktop Search)

Displayed in Resource Monitor as: SearchIndexer.exe (several instances)

Indexing is one of the huge improvements in Vista and based on Windows Desktop Search you might already know. Indexing is used to allow you to search for a term and get the result from the index instantly. However, to find a document Indexing must first read it and save it to the index, a process also known as "crawling" or "indexing".

And this is where the trouble starts: The basic idea should is that Indexing does only put a lot of pressure on your HD directly after you have installed Vista until it has indexed all your documents. Once this has happened, Indexing should only crawls documents it does not have so far or which were updated.

However, as it looks like Indexing will at least "scan" all your documents on every startup of your PC. This can cause a lot of HD activity.

In case you have a lot of documents and you search for them regularly, I would recommend not changing the Indexing settings. However, if you have only some locations you wish to search for you can change the settings, having less files Indexing will touch and thus less HD activity.

As a recommendation from my side: Always index the Start menu. It's one of my top time saves to simply enter the name of a program into the input box of the Start menu and don't need to remember in which folder it is exactly.

To configure Indexing, go to Control Panel, "System and Maintenance", "Indexing Options" and click on "Change how Windows searches":

The settings of Indexing are normally fine out of the box as it will only index the documents inside your user folder among some other folder. However, if you only want the feature of Vista to search inside your Start Menu, you may simply exclude all other locations and thus reduce the amount of data Indexing will need to check.

To do so, just open the "Change how Windows searches" and click on the "Modify" button. Inside the appearing window select "Show all locations" and accept the UAC prompt.Inside the appearing window simply deselect the "Users" folder which normally contains most the data you use. If may also add another folder that contains the real important files, e.g. "C:\Data".

On my system, disabling "Users" caused the index to shrink from 22.747 files to round about 301. However, keep in mind: what is not indexed is not found when you search for it!

And in case you are interested: If you really don't need this indexing feature at all, you can simply disable the service "WSearch" but I really don't recommend this since a lot of applications depend on indexing to be working correctly.


Conclusion

When talking about "Vista's Constant HD Activity Craziness" you really need to know what is causing most of this activity and if it's worth the trouble. Except for the Index service that maybe needs to be reconfigured, all other services are really worth the stress they put on your HD.


Appendix A – How to enable/disable a service

Go to Control Panel, "System and Maintenance", "Administrative Tools" and click on this header.

In the newly opened window, select the first item "Computer Management". After an UAC prompt, "Computer Management" is started.

From the navigation view on the side, select "Services and Applications" and then "Services". Now all the services on your computer are displayed in the panel on the right.


Appendix B– Resource Monitor

The best way to monitor what is currently stressing your HD is to use the "Resource Monitor". To start it, simply right-click the taskbar, select "Task Manager", select the "Performance" tab and click on "Resource Monitor" on the bottom.

After the UAC prompt, the Resource Monitor will start. Inside, click on "Disk" and you see all applications in real time that access your HD.