Posts Tips, Tricks and Code Snippets
Post
Cancel

Tips, Tricks and Code Snippets

Below are a few tips and tricks that I've either created or come across that I've used or have just found interesting enough to store someplace for possible use later.  It's formatted in a FAQ format.

How do I determine the executing assemblies path?

If your wanting to do this with a Windows Forms application, just use:

  <FONT color=#0000ff>Dim path <FONT color=#0000ff>As <FONT color=#0000ff>String</FONT></FONT></FONT> = System.IO.Path.GetDirectoryName(Application.ExecutablePath)

Otherwise, you can use:

  <FONT color=#0000ff>Dim path <FONT color=#0000ff>As <FONT color=#0000ff>String</FONT></FONT></FONT> = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly.Location)

How do I get a list of installed printers?

Use the System.Drawing.Printing.PrinterSettings.InstalledPrinters collection.

How do I translate a Win32 error number into a human readable text message?

You have two ways (using VB.NET) to get a numeric Win32 error message.  One is to use the System.Runtime.InteropServices.Marshal.GetLastWin32Error method, while the other is to use the VB.NET specific Err.LastDllError method.  Now that you have the numeric representation of the Win32 error, we want to turn it into a text representation, you know, the error message in English.

There's couple of ways to accomplish this.  First, we'll explore the Win32 P/Invoke way first.  Using this method is the way that the SDK documentation is pointing out.  What I've done is wrapped the FormatMessage API call with a VB.NET friendly wrapped version. 

<FONT color=#0000ff>Private <FONT color=#0000ff>Declare</FONT> <FONT color=#0000ff>Function</FONT> FormatMessageA <FONT color=#0000ff>Lib</FONT> "kernel32" (<FONT color=#0000ff>ByVal</FONT> flags <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>, <FONT color=#0000ff>ByRef</FONT> source <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Object</FONT>, <FONT color=#0000ff>ByVal</FONT> messageID <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>, <FONT color=#0000ff>ByVal</FONT> languageID <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>, <FONT color=#0000ff>ByVal</FONT> buffer <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>String</FONT>, <FONT color=#0000ff>ByVal</FONT> size <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>, <FONT color=#0000ff>ByRef</FONT> arguments <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>) <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT></FONT>

<FONT color=#0000ff>Public <FONT color=#0000ff>Shared</FONT> <FONT color=#0000ff>Function</FONT> FormatMessage(<FONT color=#0000ff>ByVal</FONT> [error] <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Integer</FONT>) <FONT color=#0000ff>As</FONT> </FONT><FONT color=#0000ff>String
 
<FONT color=#0000ff>Const
FORMAT_MESSAGE_FROM_SYSTEM <FONT color=#0000ff>As</FONT> <FONT color=#0000ff>Short</FONT></FONT></FONT> = &H1000
  <FONT color=#0000ff>Const
LANG_NEUTRAL <FONT color=#0000ff>As
<FONT color=#0000ff>Short</FONT></FONT></FONT> = &H0
  <FONT color=#0000ff>Dim
buffer <FONT color=#0000ff>As
<FONT color=#0000ff>String</FONT></FONT></FONT> = Space(999)
  FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, 0, [error], LANG_NEUTRAL, buffer, 999, 0)
  buffer = Replace(Replace(buffer, Chr(13), ""), Chr(10), "")
  <FONT color=#0000ff>Return
</FONT> buffer.Substring(0, buffer.IndexOf(Chr(0)))
<FONT color=#0000ff>End
</FONT><FONT color=#0000ff>Function </FONT>

You can then use this method as follows:

<FONT color=#0000ff>Throw New Exception(Marshal.GetLastWin32Error)</FONT>

A more friendly .NET Framework method is to use the Win32Exception class.  Normally when you want to know what the human readable version of the numeric value is, you will probably throw this so the user of your application can see the error.  At the very least, so you can easily figure out what is the problem.

<FONT color=#0000ff>Imports System.ComponentModel
<FONT color=#0000ff>Imports </FONT>System.Runtime.InteropServices

<FONT color=#0000ff>Throw New </FONT>Win32Exception(Marshal.GetLastWin32Error)</FONT>

How do I change the color of the text on a tab of the TabControl?

You'll have to set the TabControls DrawMode property to OwnerDrawFixed and draw the text in the TabControls DrawItem procedure.

<FONT color=#0000ff size=2>Private Sub </FONT>TabControl1_DrawItem(<FONT color=#0000ff size=2>ByVal</FONT> sender <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Object</FONT>, <FONT color=#0000ff size=2>ByVal</FONT> e <FONT color=#0000ff size=2>As</FONT> System.Windows.Forms.DrawItemEventArgs) _
<FONT color=#0000ff size=2>  Handles</FONT> TabControl1.DrawItem

 
<FONT color=#0000ff size=2>Dim</FONT> r <FONT color=#0000ff size=2>As</FONT> RectangleF = RectangleF.op_Implicit(e.Bounds)
 
<FONT color=#0000ff size=2>Dim</FONT> ItemBrush <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>New</FONT> SolidBrush(TabControl1.BackColor)

 
<FONT color=#0000ff size=2>Dim</FONT> sf <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>New</FONT> StringFormat
  sf.Alignment = StringAlignment.Center
  sf.LineAlignment = StringAlignment.Center

 
<FONT color=#0000ff size=2>If</FONT> <FONT color=#0000ff size=2>CBool</FONT>(e.State <FONT color=#0000ff size=2>And</FONT> DrawItemState.Selected) <FONT color=#0000ff size=2>Then
    </FONT>e.Graphics.FillRectangle(ItemBrush, e.Bounds)
    e.Graphics.DrawString(TabControl1.TabPages(e.Index).Text, e.Font, Brushes.Red, r, sf)
 
<FONT color=#0000ff size=2>Else
    </FONT>e.Graphics.DrawString(TabControl1.TabPages(e.Index).Text, e.Font, Brushes.Blue, r, sf)
 
<FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>If</FONT>

<FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>Sub </FONT> <P>How can I determine the date for next Friday?</P> <P></P><FONT color=#0000ff size=2>Public</FONT> <FONT color=#0000ff size=2>Function</FONT> GetNextFriday(<FONT color=#0000ff size=2>ByVal</FONT> startDate <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Date</FONT>) <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Date
  </FONT><FONT color=#0000ff size=2>If</FONT> startDate.DayOfWeek < DayOfWeek.Friday <FONT color=#0000ff size=2>Then
    </FONT><FONT color=#008000 size=2>’ If todays day of week is less than Friday.
    </FONT><FONT color=#008000 size=2>’ Add the number of days till next Friday.
    </FONT><FONT color=#0000ff size=2>Return</FONT> startDate.AddDays(DayOfWeek.Friday - startDate.DayOfWeek)
<FONT color=#0000ff size=2><FONT color=#000000>  </FONT>Else
    </FONT><FONT color=#008000 size=2>’ Otherwise, subtract the difference from 7.
    </FONT><FONT color=#0000ff size=2>Return</FONT> startDate.AddDays(7 - (startDate.DayOfWeek - DayOfWeek.Friday))
 
<FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>If
</FONT><FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>Function</FONT> <P>How can I ‘export’ functions from a .NET DLL to non-.NET applications?</P> <P>Well, the official answer is to use COM in order to export your classes to .NET applications.  But what do you do when these other applications are unable to use COM?  Well, you can then possibly use a wrapper DLL written in Managed C++ to accomplish the task.  But wait, there appears to be yet one more way… hack the resulting IL code of your DLL to export directly as a native Win32 type ‘export’.  Export Managed Code as Unmanaged article discusses all the gory details.</P> <P>How do I catch errors in ‘release’ builds, but not while debugging?</P> <P>Here’s the scenario.  You want to setup a global error handler (which you should) for your application.  This is a good thing.  However, it causes a pain when trying to develop within the debugger since now every time an error occurs, your global error handler will capture the error.  Here’s a solution:</P> <P>Often times, applications will have a global exception handler in the Main method that catches any exceptions that weren’t handled elsewhere. The compiler itself uses a strategy similar to this for out of memory situations – once we’ve run out of memory, the compiler’s toast, so we throw an exception indicating “out of memory” and then catch it at the top level, giving a nice “out of memory, please restart the compiler” error. (Hopefully none of you have ever seen it.) Anyway, when you’re debugging the application it can be convenient to not catch exceptions at the top level so that you immediately break into the debugger when you get a global exception. A simple way to do this is to use When to not catch the exception when a debugger is present:</P><PRE><FONT color=#0000ff>Sub</FONT> Main()
<FONT color=#0000ff>Try</FONT>
RunApplication()
<FONT color=#0000ff>Catch</FONT> ex <FONT color=#0000ff>As</FONT> Exception <FONT color=#0000ff>When Not</FONT> System.Diagnostics.Debugger.IsAttached
HandleGlobalException(ex)
<FONT color=#0000ff>End Try
End Sub</FONT></PRE> <P>Source: Paul Vick</P> <P>How do I determine if an assembly was built for debug or release?</P> <P>If you want to determine if your assembly was built using debug or release, you would think you could use the FileVersionInfo.IsDebug or IsRelease; however, the compiler doesn’t apparently set the proper bit as you would expect.  Since that doesn’t work, you could use the DebuggableAttribute on the assembly by using the following code.</P> <P></P><FONT color=#0000ff size=2>Dim</FONT> assm <FONT color=#0000ff size=2>As</FONT> Reflection.Assembly = Reflection.Assembly.LoadFrom(Application.ExecutablePath)
<FONT color=#0000ff size=2>Dim</FONT> found <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Boolean</FONT> = assm.GetCustomAttributes(<FONT color=#0000ff size=2>GetType</FONT>(DebuggableAttribute), <FONT color=#0000ff size=2>False</FONT>).Length > 0
<FONT color=#0000ff size=2>Me</FONT>.Text = "Assembly is " & IIf(found, "debug", "release") <P>Source: Thanks to Jeff Key for posting this tip to his blog (you can view his post for the C# code).</P> <P>How do I build a sockets (network) terminal client.</P> <P>Haven’t had a chance to go through this video walkthrough, but I’m sure it’s excellent since it’s done by Carl Franklin.  As soon as I get a chance to check it out, I’ll update this information.  You can check it out here.</P> <P>Holy crap!!! My application is taking up too much memory and it’s just a default form?  What is going on here?</P> <P>Well, this is actually normal with an application utilizing the .NET Framework.  Many things are happening when you launch your application such as code access security, JIT compilation, memory management and the referencing of the actual .NET Framework library(ies).  However, if you are really concerned with the amount of memory your application is reporting you can try the following to give your application and Windows a kick in the rear to more accurately report the current memory usage of your application.  This tip is purely for cosmetic purposes, to help calm those irritating phone calls asking why your application uses more memory than Microsoft Word does… and it’s just a Hello World application.  There is no performance gain of any kind from using this tip.  See warnings below for additional information.</P> <P><FONT color=#0000ff size=2>Public Class</FONT> MemoryManagement
 
 
<FONT color=#0000ff size=2>Private</FONT> <FONT color=#0000ff size=2>Declare</FONT> <FONT color=#0000ff size=2>Function</FONT> SetProcessWorkingSetSize <FONT color=#0000ff size=2>Lib</FONT> "kernel32.dll" ( _
   
<FONT color=#0000ff size=2>ByVal</FONT> process <FONT color=#0000ff size=2>As</FONT> IntPtr, _
   
<FONT color=#0000ff size=2>ByVal</FONT> minimumWorkingSetSize <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT>, _
   
<FONT color=#0000ff size=2>ByVal</FONT> maximumWorkingSetSize <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer</FONT>) <FONT color=#0000ff size=2>As</FONT> <FONT color=#0000ff size=2>Integer

  </FONT><FONT color=#0000ff size=2>Public</FONT> <FONT color=#0000ff size=2>Shared</FONT> <FONT color=#0000ff size=2>Sub</FONT> FlushMemory()
    GC.Collect()
    GC.WaitForPendingFinalizers()
   
<FONT color=#0000ff size=2>If</FONT> (Environment.OSVersion.Platform = PlatformID.Win32NT) <FONT color=#0000ff size=2>Then
      </FONT>SetProcessWorkingSetSize(Process.GetCurrentProcess().Handle, -1, -1)
   
<FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>If
  </FONT><FONT color=#0000ff size=2>End</FONT> <FONT color=#0000ff size=2>Sub

End</FONT> <FONT color=#0000ff size=2>Class</FONT> </P> <P>This will force a garbage collection to occur and if running on Windows NT, 2000, XP, or 2003, will (according to the SDK documentation):</P> <P>The working set of a process is the set of memory pages currently visible to the process in physical RAM memory. These pages are resident and available for an application to use without triggering a page fault. The minimum and maximum working set sizes affect the virtual memory paging behavior of a process.</P> <P>The working set of the specified process can be emptied by specifying the value -1 for both the minimum and maximum working set sizes.</P> <P>Using a simple windows application, adding a command button, within the click event call upon the FlushMemory method, you will see the application go from using nearly 15meg of memory usage and a VM size of over 7meg to around 1meg (or less) of memory while the VM size stays pretty constant.  </P> <P><FONT color=#ff0000>Warning:  This nice little method doesn’t come without a cost.  Don’t call upon this method during critical sections of your code.  Forcing a garbage collection can be very time consuming.  Also, don’t try to set the minimum and maximum sizes; let .NET’s memory management do it’s job. </FONT><FONT color=#ff0000>A couple of more references (or more accurately oppinions) for you to read if you intend on using GC.Collect: </FONT>Chris Brumme - ReleaseComObject <FONT color=#ff0000>and </FONT>Rico Mariani - Two things to avoid for better memory usage.</P> <P>How do I load an image from a file using a file stream?</P> <P><FONT color=#0000ff>Protected</FONT> Shared Function GetImageFromFile(ByVal FileName As String) As Byte()
    Dim myFile As String = FileName
    Dim fs As FileStream = New FileStream(myFile, FileMode.Open, FileAccess.Read)
    Dim br As BinaryReader = New BinaryReader(fs)
    Dim bytesize As Long = fs.Length
    ReDim GetImageFromFile(bytesize)
    GetImageFromFile = br.ReadBytes(bytesize)
End Function </P> <P><FONT color=#000000>To use the above function:</FONT></P> <P><FONT color=#0000ff>Dim</FONT> img As New Bitmap(New IO.MemoryStream(GetImageFromURL("c:\file.jpg")))
Me.BackgroundImage = img </P> <P>Source: Duncan MacKenzie</P> <P>How do I load an image from a URI address?</P> <P><FONT color=#0000ff>Function</FONT> GetImageFromURL(ByVal url As String) As Byte()
    Dim wr As HttpWebRequest = _
       DirectCast(WebRequest.Create(url), HttpWebRequest)
    Dim wresponse As HttpWebResponse = _
       DirectCast(wr.GetResponse, HttpWebResponse)
    Dim responseStream As Stream = wresponse.GetResponseStream
    Dim br As BinaryReader = New BinaryReader(responseStream)
    Dim bytesize As Long = wresponse.ContentLength
    Return br.ReadBytes(bytesize)
End Function </P> <P><FONT color=#000000>To use the above function:</FONT></P> <P><FONT color=#0000ff>Dim</FONT> img As New Bitmap(New IO.MemoryStream(GetImageFromURL("http://msdn.microsoft.com/longhorn/art/codenameLonghorn.JPG")))
Me.BackgroundImage = img </P> <P>Source: Duncan MacKenzie</P> <P>How do I use animated cursors in .NET?</P> <P>Check out the Using Colored and Animated Cursors article by Dr. GUI.</P> <P>How do I create a Windows Service?</P> <P>MSDN has an excellent article (Walkthrough: Creating a Windows Application in the Component Designer) that shows how to create a Windows Service from start to finish.  I would also recommend reading the Install a Windows Service the way you want to article available on CodeProject.com that shows how to do a few of the features that seem to have been left out; such as adding a service description and modifying the All service to interact with the desktop option.</P> <P>How do I generate a GUID (Globally Unique IDentifier)?</P> <P>You can use the System.Guid class.</P> <P class=MsoNormal style="MARGIN: 0in 0in 0pt">Dim guid As String = System.Guid.NewGuid.ToString</P> <P>You can also control how the guid is formatted.  For example, if you use ToString(“N“), the dashes (“-“) will be removed.</P> <P>Have any other ideas?  Leave a comment.</P>

This post is licensed under CC BY 4.0 by the author.