Showing posts with label winform. Show all posts
Showing posts with label winform. Show all posts

Wednesday, May 12, 2010

You can get my projects at Softpedia now, hehe

Softpedia Editorial Team informed me that they have included my projects in their sites. 
1) Analog Clock - A small desktop gadget that will display the current time (Downloads: 44)



2) SQL Management Console 0.1.1.29977 -Query pane and result pane (Downloads: 50)


Again, really thanks to them.

Sunday, December 14, 2008

Application.StartupPath != Environment.CurrentDirectory

When developing the .NET app, you are not only creating an .exe. Most of the time, you will need some other files like .bmp, App.Config, and .xml. For those resource files(data or images), you could simply embed into the main exe and access it class "ResourceManager", though it might increase the size tremendously. But what if for those XML file that need user customization? You might put them along with your main executable file during deployment, for initialization. Thus you will need to find where your .exe starts, and to read XML file that relative to it. So now you might think you got at least two choices, "Environment.CurrentDirectory" & "Application.StartupPath".

From the MSDN, the definition of:
a) Environment.CurrentDirectory
Gets or sets the fully qualified path of the current working directory.
b) Application.StartupPath
Gets the path for the executable file that started the application, not including the executable name.

They look similar & match your purpose. "Environment.CurrentDirectory" looks good, especially it is located inside "System" namespace, so you no need to add any reference; while "Application.StartupPath" needs to add reference to assembly "System.Windows.Forms". You might think the former one is better for console application, and even windows service! Windows service does not need any GUI and would suppress any messagebox from pop-up. So using "Environment.CurrentDirectory" seems a good choice to prevent the developers simply calling messagebox in windows service if without adding reference to assembly "System.Windows.Forms", from design perspective.

So I decided to use "Environment.CurrentDirectory" for my dll, which is eventually called by the windows service, and the code to load the XML file would be similar to this:

Dim strXMLFile As String = Environment.CurrentDirectory & "\" & INITIALIZATION_XML
If Not File.Exists(strXMLFile) Then
Throw New FileNotFoundException("The initialization file " & INITIALIZATION_XML & " does not exist.")
End If
I created a WinForm for test harness of the dll, and everything was fine. Then this dll consumed by the windows services. Bang! I get an "FileNotFoundException" exception. I use Debug.Print to find that my XML look-up path was at: "C:\WINDOWS\system32"???

Why? It's because Windows service applications run in their own security context.
and more definition for "Environment.CurrentDirectory":

Gets and sets the fully qualified path of the current directory; that is, the directory from which this process starts.

Using the Reflector:
a) Environment.CurrentDirectory

b) Application.StartupPath


So, the "Environment.CurrentDirectory" is equivalent to "Application.StartupPath" when running as WinForm/console app and will become variable "%SystemDirectory%" eventually if run under windows service! A lesson learned.

p/s: You could use reflection from class Assembly as well, to find the start-up path.

Tuesday, July 15, 2008

How to capture the output from Console.WriteLine

Sometimes, windows/console application needs to capture the output from console.writeline for debugging purpose. It's useful if the application can run in verbose mode, so that we can know at which point the system crashes. Maybe you might think we can implement ConsoleTraceListener Class in .Net 2.0.

While doing some tutorials on Linq on .Net 3.0, I found the sample have another simpler way to achieve that. Here are the steps:

1) Create a windows application


2) Design a simple GUI. Button represents you business logic and multiline textbox means the trace information.


3) Set the StreamWriter to the Console output, re-capture it with TextWriter will do.

Imports System.IO

Public Class Form1
Private ReadOnly _OutputStreamWriter As StreamWriter = New StreamWriter(New MemoryStream())

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
' Capture console output
Dim writer As StreamWriter = _OutputStreamWriter
Dim oldConsoleOut As TextWriter = Console.Out
Console.SetOut(writer)
Dim stream As MemoryStream = CType(writer.BaseStream, MemoryStream)
stream.SetLength(0)

DoSomething
' set to result pane
writer.Flush()
Console.SetOut(oldConsoleOut)
TextBox1.Text += writer.Encoding.GetString(stream.ToArray())

End Sub

Private Sub DoSomething()
Console.WriteLine("Hello world!")
End Sub
End Class

4) Here's the final result: