Friday, October 3, 2008

Check with VB.NET if running under IDE

When you write your VB.NET application and debug it under IDE, you know it's running under IDE. Your application does not know it but in some cases it should know that it's running under IDE.

When the application can check if it's running under IDE or as a standalone application, it can make different decisions based on that knowledge.

One scenario would be to use different paths to data files. Under IDE the application can use path to some data made for debugging purpose. When running as a standalone application it can use path to real data.

Another scenario where your application can use this information, is to display debugging information. When you debug application under IDE, it can use extensive debug information dumping. But when you hand your application over to testers, they like to have your application behaving like end users would see it.

Test with VB.NET if running in IDE

With VB.NET it's quite simple to test if the application runs in IDE. System.Diagnostics namespace contains Debugger class. From Debugger class you can check IsAttached property which tells if a debugger is attached to the running process. This is the case when your application runs in IDE.

''' <summary>
''' Returns boolean value telling if the application is running under IDE
''' </summary>
''' <returns>True if the application is running under IDE</returns>
''' <remarks></remarks>
Public Function RunningUnderIDE() As Boolean
  '
    Return System.Diagnostics.Debugger.IsAttached()

End Function

Test with Visual Basic 6 if running under IDE

Just for the comparison I went through my "Old Code Archive" and under the dust I found how the same test was done with VB6. I have used this code to test if my application was running in IDE with VB6, but I know there were other (maybe simpler) ways to do it.

First, some helper routines and declarations.

Const FileFromFullName = 2

Private Declare Function GetModuleFileName Lib "kernel32" _
  Alias "GetModuleFileNameA" (ByVal hModule As Long, _
  ByVal lpFileName As String, ByVal nSize As Long) As Long
  
Private Declare Function GetModuleHandle Lib "kernel32" Alias _
  "GetModuleHandleA" (ByVal lpModuleName As String) As Long

Private Function GetFileFromFullName(ByVal SourceFile As String) As String
'
' Return the file name and extension part of SourceFile.
'
Dim SlashPos As Integer
Dim LastPos As Integer
  
  ' Find out the position index for the last slash character (LastPos)
  SlashPos = InStr(SourceFile, "\")
  LastPos = SlashPos
  Do Until SlashPos = 0
    SlashPos = InStr(LastPos + 1, SourceFile, "\")
    If SlashPos <> 0 Then
      LastPos = SlashPos
    End If
  Loop
  
  ' Now return last 'LastPos' chars from the original SourceFile string
  GetFileFromFullName = Mid$(SourceFile, LastPos + 1)

End Function

Public Function GetProcessName() As String
Attribute GetProcessName.VB_Description = "Returns the name of the mother process, which is different to app.name if program is a dll."
'
' Returns the name of the mother process (different to app
' if we are in a dll)
'
Dim StringBuffer As String
Dim FileName As String
Dim Length As Long
  
  StringBuffer = Space(255)
  Length = GetModuleFileName(GetModuleHandle(vbNullString), _
    StringBuffer, Len(StringBuffer))
  FileName = GetFileFromFullName(Left$(StringBuffer, Length))
  FileName = Left$(FileName, Len(FileName) - 4) ' Remove .exe
  GetProcessName = FileName

End Function

And finally the actual function.

Public Function RunningUnderIDE() As Boolean
Attribute RunningUnderIDE.VB_Description = "Returns boolean value telling if program is running under IDE. False means that program is compiled version."
'
' Returns boolean value telling if we are running under IDE
' (False means we are running the compiled version)
'
  RunningUnderIDE = (GetProcessName <> App.EXEName)

End Function

Well, it worked but that's a quite lot more code than in VB.NET version.