Send mail to the author(s)

October 28, 2004

Ultra-Simple Application Logging

This is a really cool technique that you can use to add simple logging/tracing functionality to your .NET Compact Framework apps. In Windows CE, there is a Win32 API which goes by the moniker of SetStdioPathW. By calling this API, you can redirect standard input, output and error output. The cool thing about this is that you can actually redirect the I/O to a text file! By redirecting standard output like this, you can scatter Console.WriteLine()'s all throughout your code and hey presto! Instant instrumentation.

So let's look at some VB code showing how to do this. As a best practice, it is always a good idea to revert the I/O redirection when you are done. To do this, we need to find out what the current standard I/O path is and this can be achieved by calling GetStdioPathW. The method signature for P/Invoking this is:

    <DllImport("coredll")> _

    Public Shared Function GetStdioPathW( _

        ByVal id As Integer, _

        ByVal originalPath As StringBuilder, _

        ByRef pathLength As Integer _

        ) As Integer

    End Function

And you call it like this:

    Dim STDOUT As Integer = 1

    Dim originalPath As New StringBuilder

    Dim pathLength As Integer = 256

    GetStdioPathW(STDOUT, originalPath, pathLength)

Now that you have retrieved the existing standard I/O configuration, you can set the I/O path. To do that, you need to P/Invoke SetStdioPathW. The signature for this is as follows:

    <DllImport("coredll")> _

    Public Shared Function SetStdioPathW( _

        ByVal id As Integer, _

        ByVal originalPath As String _

        ) As Integer

    End Function

And you call it like this:

    Dim myLogFile As String = "\My Documents\MyLogFile.txt"

    SetStdioPathW(STDOUT, myLogFile)

So, putting all this together in a simple VB Windows CE console app, we get something like this:

    Imports System.Runtime.InteropServices

    Imports System.Text

 

    Public Class MyConsoleApp

        <DllImport("coredll")> _

                Public Shared Function GetStdioPathW( _

                ByVal id As Integer, _

                ByVal originalPath As StringBuilder, _

                ByRef pathLength As Integer _

                ) As Integer

        End Function

 

        <DllImport("coredll")> _

        Public Shared Function SetStdioPathW( _

            ByVal id As Integer, _

            ByVal newPath As String _

            ) As Integer

        End Function

 

        Shared Sub Main()

            Dim STDOUT As Integer = 1

 

            ' Retrieve the existing path for standard output

            Dim originalPath As New StringBuilder

            Dim pathLength As Integer = 256

            GetStdioPathW(STDOUT, originalPath, pathLength)

 

            ' Set standard output to redirecto to a

            ' file in MyLogFile.txt

            Dim myLogFile As String = "\MyLogFile.txt"

            SetStdioPathW(STDOUT, myLogFile)

 

            ' Write to standard output

            Console.WriteLine("Hello World 1")

            Console.WriteLine("Hello World 2")

            Console.WriteLine("Hello World 3")

 

            ' Revert the settings to their original values

            SetStdioPathW(STDOUT, originalPath.ToString())

        End Sub

    End Class