Friday, July 20, 2007

4238.aspx

A Rolling File Appender in VBScript

I use log4j and log4net in most of my projects but I did not have a decent alternative for VBScript so I implemented my own. The script below implements the most important features of the log4j/log4net rolling file appender. It lets you configure:



  • file to log to

  • size of each file

  • number of backups/old copies to keep

The code below uses test.txt as the log file with 4 backups. Test.txt contains the last logged data. When it is full, it is renamed to the backup file test.txt.1. The older logs are kept in the files test.txt.2, test.txt.3, … test.txt.N


Note that the size calculation is not accurate as the file is kept open. It is slower, but the size will be correct, if you open and close the file each time you log something. I did not care about accuracy so I chose the faster implementation below.


option explicit


'== CONFIG
const LOG_FILE = "C:\temp\test.txt"
const LOG_FILE_BACKUPS = 4
const LOG_FILE_SIZE_KB = 1000
const LOG_TO_CONSOLE = false



const LOG_FATAL = 0
const LOG_ERROR = 1
const LOG_WARN = 2
const LOG_INFO = 3
const LOG_DEBUG = 4


const LOG_FILE_LEVEL = 4



dim currentLogStream
set currentLogStream = nothing



'==== Test ONLY. Delete this section in production code
'Main tester
WScript.echo "Press CTRL+C to exit"
do while true
 traceLog LOG_DEBUG, "Debug level test " & String(1000,"d")
 traceLog LOG_INFO, "Info level test" & String(1000,"i")
 traceLog LOG_WARN, "Warn level test" & String(1000,"w")
 traceLog LOG_ERROR, "Error level test" & String(1000,"e")
 traceLog LOG_FATAL, "Fatal level test" & String(1000,"f")
 
 Wscript.sleep (1)
Loop
'==== End Test



public sub traceLog (level, message)
dim prefix


 prefix = "[UNKNOWN]"
 if level <= LOG_FILE_LEVEL then
  select case level
   case LOG_FATAL
    prefix = "[FATAL]"
   case LOG_ERROR
    prefix = "[ERROR]"
   case LOG_WARN
    prefix = "[WARN]"
   case LOG_INFO
    prefix = "[INFO]"
   case LOG_DEBUG
    prefix = "[DEBUG]"
  end select


  rollingAppend prefix & vbTab & now() & vbTab & message  
 end if
end sub


sub rollingAppend (message)
'Special case the first time (file not opened)
dim oFS
dim oFile
dim fileNum
 on error resume next 'NEVER bomb while logging
 set oFS = CreateObject("Scripting.FileSystemObject")
 if currentLogStream is nothing then
  'Open stream for APPEND, creating the file if it does not exist
  set currentLogStream = oFS.OpenTextFile(LOG_FILE, 8, true)
 end if


 'Log
 currentLogStream.WriteLine (message) 
 if LOG_TO_CONSOLE then WScript.echo message
 
 'Roll over if we should
 set oFile = oFS.getFile(LOG_FILE)
 if oFile.size >= LOG_FILE_SIZE_KB * 1024 then
  currentLogStream.close()
  set currentLogStream = nothing
  
  'Delete the last backup   
  if oFS.FileExists(LOG_FILE  & "." &  LOG_FILE_BACKUPS) then
   oFS.DeleteFile LOG_FILE  & "." &  LOG_FILE_BACKUPS
  end if
  
  'Rename all the old log files so log_file.1 -> 2, 2->3, etc.
  for fileNum = LOG_FILE_BACKUPS - 1 to 1 step - 1
   if oFS.FileExists (LOG_FILE  & "." &  fileNum) then
    oFS.MoveFile LOG_FILE  & "." &  fileNum, LOG_FILE  & "." &  fileNum + 1
   end if
  next
  
  'Move current file to .1
  oFS.MoveFile LOG_FILE, LOG_FILE & "." & 1  
 end if
end sub

Tuesday, July 17, 2007

4227.aspx

How we see the world

I always imagined my eyes send a full color image/movie to my brain, letting the brain sort out the what happens in the world.  The brain has a lot of processing power but how can it decipher what it sees so fast? The failures of first DARPA Grand Challenge shows just how difficult it is to interpret visual data in real time.


It turns out that the brain does not accomplish the task by itself. It gets a hand by the eyes which pre-processes the data in a way I never imagined.


Frank Werblin and Botond Roska explain the results of their research in The Movies in our eyes article in Scientific American. It turns out that the eye, of a rabbit in their tests, does not send one stream of information but 12 parallel "movies" of the world.  This movie illustrates very well the different (simulated) signals sent to the brain:


Different layers of cells in the retina interpret the world and send separate “movies“. The orange movie shows the contours which is great for pattern matching whereas the beige movie focuses on bright areas. The movies are then combined by the brain to give the world we see.


Another key point is that they eyes do not send a continuous movies, it only sends highlights thereby reducing the work the brain has to do. Flashing a light for one second at a specific area in the retina does not send a continuous signal for one second. The retina sends a signal shortly after the bright flash starts, then it remains silent until there is a short signal when the light goes off again.


A great example of solving a complex problem by distributing the work and breaking it down in the manageable pieces.


Yet another lesson learned from mother nature.

Thursday, June 14, 2007

4203.aspx

Grasshopper: code in Visual Studio, build Java and deploy on Linux

This sounds too good to be true: Code in .NET 2.0, Build for Java, Run on Linux with Grashopper 2.0





After more than 100 person years and $12 million of direct R&D investment, and the cross-compilation of 4.7 million lines of code from .NET to Java™, we’re celebrating the release of Grasshopper 2.0. This freely-available plug-in to the Visual Studio® 2005 IDE enables you to produce .NET Web and server applications that run on Tomcat under Linux® and other Java-enabled platforms, without having to rewrite your C# or Visual Basic code. Version 2.0 introduces support for Microsoft's® Visual Studio 2005 IDE, the .NET Framework 2.0, ASP.NET 2.0 controls, role-based security, and C# generics.


Here you'll find articles, code samples, and forums that you can use to jump into Grasshopper 2.0. For deployments on enterprise-class Java EE servers and portal servers, as well as multiple-CPU deployments, check out Mainsoft's Enterprise and Portal editions.


To be honest, I need tools that work the other way around at the moment, letting me run Java code in a managed environment. The Microsoft Java Language Conversion Assistant 3.0 tries to convert Java to .NET but it is way behind as it only supports JDK 1.3.


For now I am forced to integrate Java in .NET using JNI or SOAP. Let me know if you find any other valid alternatives.

Wednesday, June 13, 2007

4200.aspx

"Value cannot be null. Parameter name: value" error in .TEXT

I know, I know. .TEXT is old ancient but it is working. I have made a couple of changes to the code and it has served me faithfully for almost 3 years, which is why I got very surprised when I suddenly started getting this error on a daily basis: "Value cannot be null. Parameter name: value"


K. Scott Allen found the solution a long time ago; It is a bug in .TEXT which you can work around by setting queueStats=”false” in the Tracking section of web.config.


I just updated my blogs. Please give me a shout if you see this error again.

4199.aspx

How to remove accents from strings in .NET

A friend asked how to remove accents from strings in .NET 2.0. I found the code below on Michael Kaplan's blog.


The code uses String.Normalize() to get a normalized Unicode representation of the string where the base character and the accents are stored separately. It then loops on each character and ignores the accent mark characters so "àáåæéèøÜü" becomes "aaaæeeøUu".


public static String RemoveDiacritics(String s)       


{


    String normalizedString = s.Normalize(NormalizationForm.FormD);


    StringBuilder stringBuilder = new StringBuilder();


 


    for (int i = 0; i < normalizedString.Length; i++)


    {


        Char c = normalizedString[i];


        if (CharUnicodeInfo.GetUnicodeCategory(c) != UnicodeCategory.NonSpacingMark)


            stringBuilder.Append(c);


    }


    return stringBuilder.ToString();


}

Thursday, May 24, 2007

4186.aspx

ASP/ASP.NET Response.AppendToLog() max size limit

Response.AppendToLog() is a great way to log short information with web requests in the IIS log in the "cs-uri-query" field. It makes traffic analysis and troubleshooting a lot simpler as it is possible to enrich the log with information that is not passed in the query string. You can for example log data from the users session:



Response.AppendToLog("&userid=" + Request.Session[userID])


Best of all:



  • The log is written automatically by IIS asynchronously

  • IIS takes care of rolling over the file by hour/day etc

  • The data is logged as part of the request in the IIS log exactly where you need it so you do not have to “join“ data from multiple logs

The documentation I found on the internet claimed that it is only possible to append 80 characters. This is no longer true in IIS 6 where it is possible to append data until the field is 4kb (4096 bytes)


The IIS log system has, in my opinion, one bug. If the total length of the cs-uri-query field exceeds 4kb, IIS drops all the data in the cs-uri-query field and only logs "…". I expect it to log 4093 bytes of data from the log plus a trailing "…"

4184.aspx

Community Days 2007 Milano: 21/6-22/6

Community Days 2007 Milano is an initiative by several Italian communities; ASPItalia.com, UGIdotNET.org, Visual Basic Tips&Tricks and WinFXItalia.com. The event is not free like it was last year, but the agenda looks interesting enough to be work the cost (120 euro for one day, 180 for both days).


Thursday 21 June


Web Track



  • ASP07-301 - IIS 7.0 vs. ASP.NET

  • ASP07-302 - Client-side AJAX in ASP.NET

  • ASP07-303 - ASP.NET: Advanced AJAX

  • ASP07-304 - ASP.NET: implementare ModelViewPresenter mediante la Microsoft Web Client Software Factory

  • ASP07-305 - Extending ASP.NET

Extreme track



  • EXT07-301 - Gestire la codebase con Team Foundation Server

  • EXT07-302 - Sviluppo e debug di UDF con SQLCLR e VS2005

  • EXT07-303 - BizTalk vs. servizi WCF

  • (to be announced)

  • EXT07-305 - XPS: usare XAML per creare documenti

Friday 22 June


Track WinFX



  • WFX07-301 - WPF: da Visual Studio a Expression Blend, e ritorno

  • WFX07-302 - Data binding con WPF

  • WFX07-303 - Windows Presentation Foundation 101

  • WFX07-304 - Windows Communication Foundation 101

  • WFX07-305 - Introduzione a CardSpace

Track Orcas



  • ORC07-301 - Introduzione a LINQ

  • ORC07-302 - .NET Compact Framework 3 (Orcas Edition)

  • ORC07-303 - LINQ vs. Nhibernate

  • ASP.NET 3 (Orcas Edition) Overview

  • ORC07-305 - Client-side web: Microsof Silverlight (a.k.a. WPF/E)

I learned several new things during the Community Days 2006 so I will probably go this year as well.