# VBForums CodeBank > CodeBank - Visual Basic 6 and earlier >  VB - Detect if you are running in the IDE...

## crptcblade

VB Code:
Option Explicit Private Declare Function GetModuleFileName Lib "kernel32" Alias "GetModuleFileNameA" (ByVal hModule As Long, _                                                                                      ByVal lpFileName As String, _                                                                                      ByVal nSize As Long) _                                                                                      As LongPrivate Declare Function GetModuleHandle Lib "kernel32" Alias "GetModuleHandleA" (ByVal lpModuleName As String) As Long Private Function InIDE() As BooleanDim s As String     s = Space$(255)        Call GetModuleFileName(GetModuleHandle(vbNullString), s, Len(s))        InIDE = (UCase$(Trim$(s)) Like "*VB6.EXE*")    End Function 'usageMsgBox InIDE

This is for VB6, for versions below 6, change the bolded section to the file name of the VB executable (VB5.exe, etc).

----------


## si_the_geek

Here is an equivalent function, but this does not require any API functions to be declared, and does not need any alterations based on the version of VB you run.

VB Code:
Option Explicit
 Function RunningInVB() As Boolean
'Returns whether we are running in vb(true), or compiled (false)
     Static counter As Variant
    If IsEmpty(counter) Then
        counter = 1
        Debug.Assert RunningInVB() Or True
        counter = counter - 1
    ElseIf counter = 1 Then
        counter = 0
    End If
    RunningInVB = counter
 End Function
 'Usage:
MsgBox RunningInVB

----------


## crptcblade

> _Originally posted by si_the_geek_ 
> *Here is an equivalent function, but this does not require any API functions to be declared, and does not need any alterations based on the version of VB you run.*


Your code works, however, if you use my code in an ActiveX Control/DLL, it will return true even if the AX project is not loaded in the IDE, but the project that uses the reference/component is running from VB.  This can be useful if you have subclassing or whatever that you want to be able to turn off when not running fully compiled.

 :Smilie:

----------


## eyeRmonkey

Here is another method (from vbAccelerator):

VB Code:
' modular level variable:
Private m_bInIDE As Boolean
 Public Property Get InIDE() As Boolean
   Debug.Assert (IsInIDE())
   InIDE = m_bInIDE
End Property
 Private Function IsInIDE() As Boolean
   m_bInIDE = True
   IsInIDE = m_bInIDE
End Function

I don't like static variables that much (don't ask why) so I think this method is somewhat cool. The only problem is that you need more lines of code.

----------


## M.Zafar Iqbal

hi,
     you can do the same with 

App.LogMode

----------


## wiz126

I think you can like this, but i don't have vb with me to check:


VB Code:
Private Sub Command1_Click()
Dim mode
    mode = App.LogMode
        If mode = 0 Then
            MsgBox "Running In IDE Version"
        ElseIf mode = 1 Then
            MsgBox "Running in Compiled Version"
        End If
End Sub

----------


## bushmobile

since it's not been mentioned, here's another way:


VB Code:
Public InIDE As Boolean
 Private Sub Main()
  On Error Resume Next
  Debug.Print 1 / 0
  InIDE = Err.Number
 End Sub

----------


## rjbudz

I like bushmobiles best, but I've always used:

' Declarations:

VB Code:
Public InIDE            As Boolean
' In Form Load or Sub Main:

VB Code:
InIDE = False               ' for clarity
    Debug.Assert CheckForIDE    ' set value of InIDE to true if in Dev Environment
' In form or module

VB Code:
Prublic Function CheckForIDE() As Boolean
' identifies app running in DEV environment
    InIDE = True
    CheckForIDE = True
End Function
Debug.Assert will only run in the IDE.  Check InIDE for True = in IDE.

----------


## marcusmiris

another way..

With no API declaration, no outside variable declaration, only a single function, tested in ActiveX DLL!


VB Code:
Public Function InIDE() As Boolean    Static i As Byte    i = i + 1    If i = 1 Then Debug.Assert Not InIDE()    InIDE = i = 0    i = 0End Function

----------


## *PsyKE1*

vb Code:
Public Function InIDE() As Boolean    InIDE = CBool(App.LogMode = 0)End Function

----------


## LaVolpe

> vb Code:
> Public Function InIDE() As Boolean
    InIDE = CBool(App.LongMode = 0)
End Function


LogMode maybe?  :Wink: 
See post #5 & #6 above

----------


## *PsyKE1*

xD Sorry men
I had not noticed
And yes, it should be : LogMode
Not LongMode! xD

----------


## LaVolpe

I know this is a very old thread, but I like all the different approaches listed above.

Thought I'd add one more. This applies to usercontrols only

1) VB only. Not guaranteed to apply to other "IDEs": Word, Access, IE, etc
2) Your usercontrol is uncompiled and you want to know if whatever is hosting it is in design-view

Normally, we'd use Ambient.UserMode which would return False indicating the host is in design view, not run-time. However, while designing, let's say you create a second usercontrol (UC) that hosts the first UC. Everything is in design view, neither UC is compiled. 

What's the problem? The 1st UC that's hosted in the 2nd UC will return Ambient.UserMode = True. This may be an issue if you are using that return value to start subclassing or API timers or something else that shouldn't be run in design view. UCs in design view are not guaranteed to get a Terminate event in design view; so subclassing, etc, should be handled carefully. You can test this by placing a debug.print statement in the control's Terminate event, then 
1) On the form, right click on the form and choose menu: update controls. Debug.Prints show
2) Now open a UC code window & hit carriage return anywhere to force cross-hatching & close the UC
3) On the form, update controls again: No Debug.Prints show. Any subclassing may be crashing IDE
4) Compiled UCs get terminate events.

Solution. If you create a Private Sub Main(), in a bas module, and set your UC to start with Sub Main via the UC properties dialog, then you can use that to your advantage. Add a public boolean variable to that module and in Sub Main() set that variable to True. Where you were testing for Ambient.UserMode, now test for that public boolean's value instead.

While the UC is uncompiled and host is in design view, VB does not call the Sub Main() of the UC, but  the Ambient.UserMode can change as described earlier.

Simple example
1) Start a new project (exe type)
2) Click on IDE menu: File | Add Project. This will create a group project
3) Choose Active-X Control project
4) In that Active-X project, add 1 module, set the UC's AutoRedraw to True
5) In the module, paste this code


```
Public g_UserMode As Boolean
Private Sub Main()
   g_UserMode = True
End Sub
```

6) In the UC add this in the Show event


```
Print "Ambient.UserMode = "; Ambient.UserMode
Print "g_UserMode "; g_UserMode
```

7) In the UC's properties, set the startup to Sub Main. IDE Menu: Project | Project2 Properties
8) Close all the UC windows opened in design view
9) Place the UC on the form. You should see that the printed lines return the same value, both in design view & run-time

When done playing, return to IDE and close all windows. Then
1) Add 1 more project to the group and make it an Active-X Control also
2) Change the control's name in the property sheet from UserControl1 to UserControl2
3) In that new UC, draw the 1st UC in it and close all IDE windows
4) Open the form in design view and draw the 2nd UC on the form

You will notice the 2 UC's display different Ambient.UserMode values in design time, but the same in run time

----------


## DEXWERX

similar to Post#1



```
Public Declare Function InIDE Lib "kernel32" Alias "GetModuleHandleA" (Optional ByVal lpModuleName As String = "vba6.dll") As Long
```

----------


## MountainMan

I know this thread is old but I have run the various techniques for determining whether the code is executing in the IDE or in a compiled form. In each case I put the code into a function that returned True if the code was executing in the IDE and False otherwise. The times below are the number of milliseconds required for each function to run 100 million times.



```
                                                     Un-compiled    Compiled
vbAdvance "In_IDE" conditional compilation command      4,510 ms      196 ms
Using Debug.Assert (similar to post #4)                10,490         196
Using App.Log (see posts #5 & 6)                       12,807      10,340
Debug.Print a  /0 (see post #7)                        42,520       7,330
Look for IDE window (see post #16)                    478,000      49,600
```

The above techniques are all based on doing something in the IDE that doesn't exist in the compiled code. The vbAdvance method overrides a compilation constant at compile time.  The others use Debug.Assert, Debug.Print and App.LogMode. It shouldn't be a surprise that those in the IDE run are slower in the checking code because 1) compiled code runs faster and 2) the code that doesn't exist in compiled mode such as Debug.Print does exists in the IDE and it takes time to run.

If for no other reason than visual styles, most of us start with Sub Main and we have general initialization code there where we can determine whether we are in the IDE or not and then save that setting for later checking. I use the 2nd technique because I don't have to set a compilation constant and because it performs just as fast in compiled code as technique #1. I do use vbAdvance for a lot of things, just not this.

----------


## hwoarang

Another one:



```

'in a module

Public gIde As Boolean

Private Declare Function GetCurrentProcessId Lib "kernel32" () As Long
Private Declare Function GetWindowThreadProcessId Lib "user32" (ByVal lhWnd As Long, lProcessId As Long) As Long

Private Sub Main()
    Dim x As Long
    GetWindowThreadProcessId FindWindowA("IDEOwner", vbNullString), x 'search for VB6 IDE window and get process identifier
    gIde = (GetCurrentProcessId = x)
End Sub
```

----------


## loquat

i have a test of the above method, should be all of them.

VB Code:
'modIDE.basPrivate m_bInIDE As Boolean    ' module level variable: Public Declare Function InIDE8 Lib "kernel32" Alias "GetModuleHandleA" (Optional ByVal lpModuleName As String = "vba6.dll") As Long Private Declare Function GetModuleFileNameA& Lib "kernel32" (ByVal hModule&, ByVal lpFileName$, ByVal nSize&)Private Declare Function GetModuleHandleA& Lib "kernel32" (ByVal lpModuleName$) Private Declare Function GetCurrentProcessId Lib "kernel32" () As LongPrivate Declare Function GetWindowThreadProcessId Lib "user32" (ByVal lhWnd As Long, lProcessId As Long) As LongPrivate Declare Function FindWindowA Lib "user32.dll" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long  Public Function InIDE1() As Boolean    Dim s As String    s = Space$(255)    Call GetModuleFileNameA(GetModuleHandleA(vbNullString), s, Len(s))    InIDE1 = (UCase$(Trim$(s)) Like "*VB6.EXE*")End Function Public Function InIDE2() As Boolean    Static counter As Variant    If IsEmpty(counter) Then        counter = 1        Debug.Assert InIDE2() Or True        counter = counter - 1    ElseIf counter = 1 Then        counter = 0    End If    InIDE2 = counterEnd Function  Public Property Get InIDE3() As Boolean   Debug.Assert (IsInIDE())   InIDE3 = m_bInIDEEnd PropertyPrivate Function IsInIDE() As Boolean   m_bInIDE = True   IsInIDE = m_bInIDEEnd Function Public Function InIDE4() As Boolean  On Error Resume Next  Debug.Print 1 / 0  InIDE4 = Err.NumberEnd Function  Public Function InIDE5() As Boolean    Static i As Byte    i = i + 1    If i = 1 Then Debug.Assert Not InIDE5()    InIDE5 = i = 0    i = 0End Function Public Function InIDE6() As Boolean    InIDE6 = CBool(App.LogMode = 0)End Function Public Function InIDE7() As Boolean    Dim x As Long    GetWindowThreadProcessId FindWindowA("IDEOwner", vbNullString), x 'search for VB6 IDE window and get process identifier    InIDE7 = (GetCurrentProcessId = x)End Function


VB Code:
'frmIDE.frmPrivate Sub Form_Load()    Me.AutoRedraw = True    testIDEEnd Sub Sub testIDE()    Dim i&, bool As Boolean    Const n As Long = 1000        mTimer = 0    For i = 1 To n        bool = InIDE1    Next i    Print 1 & vbTab & bool & vbTab & Round(mTimer, 3)     mTimer = 0    For i = 1 To n        bool = InIDE2    Next i    Print 2 & vbTab & bool & vbTab & Round(mTimer, 3)        mTimer = 0    For i = 1 To n        bool = InIDE3    Next i    Print 3 & vbTab & bool & vbTab & Round(mTimer, 3)        mTimer = 0    For i = 1 To n        bool = InIDE4    Next i    Print 4 & vbTab & bool & vbTab & Round(mTimer, 3)        mTimer = 0    For i = 1 To n        bool = InIDE5    Next i    Print 5 & vbTab & bool & vbTab & Round(mTimer, 3)     mTimer = 0    For i = 1 To n        bool = InIDE6    Next i    Print 6 & vbTab & bool & vbTab & Round(mTimer, 3)        For i = 1 To n        bool = InIDE7    Next i    Print 7 & vbTab & bool & vbTab & Round(mTimer, 3)     For i = 1 To n        bool = InIDE8    Next i    Print 8 & vbTab & bool & vbTab & Round(mTimer, 3)End Sub


VB Code:
'modTimingOption Explicit Private Declare Function QueryPerformanceCounter Lib "kernel32" (x As Currency) As BooleanPrivate Declare Function QueryPerformanceFrequency Lib "kernel32" (x As Currency) As Boolean Dim m_Time As Double          'Dim m_TimeStart As CurrencyDim curFreq As Currency      Dim m_TimeFreq As Double Public Property Get mTimer() As Double    Dim curTime As Currency    QueryPerformanceCounter curTime    'Debug.Print curTime; m_TimeStart    mTimer = 1000 * (curTime - m_TimeStart) * m_TimeFreq + m_Time    'minisectionsEnd Property Public Property Let mTimer(ByVal newValue As Double)    Dim curOverhead As Currency    m_Time = newValue    QueryPerformanceFrequency curFreq    m_TimeFreq = 1 / curFreq    QueryPerformanceCounter curOverhead    QueryPerformanceCounter m_TimeStart    m_TimeStart = m_TimeStart + (m_TimeStart - curOverhead)End Property



```
i have test 3 options in my computer:
1st: InIDE
1	True	18.83
2	True	.452
3	True	.378
4	True	2.029
5	True	.587
6	True	.523
7	True	40.376
8	True	42.668

2nd: InEXE with "Advanced optimization"
1	False	9.936
2	False	.262
3	False	.006
4	False	.287
5	False	.007
6	False	.438
7	False	38.77
8	False	40.839

3rd: InEXE without "Advanced optimization"
1	False	15.369
2	False	.3
3	False	.007
4	False	.32
5	False	.023
6	False	.505
7	False	52.38
8	False	54.775

it seems in my computer InIDE3 is the best option.
```

----------


## Arnoutdv

Performance is not really an issue when you cache the result in a global/local variable.
Set it at the start up of the application and then you only have a single boolean variable.

----------


## wqweto

InIDE3 FTW! 

You can even remove the "global" m_bInIDE altogether like this


thinBasic Code:
Public Property Get InIde() As Boolean
    Debug.Assert pvSetTrue(InIde)
End Property
 Private Function pvSetTrue(bValue As Boolean) As Boolean
    bValue = True
    pvSetTrue = True
End Function
cheers,
</wqw>

----------


## Eduardo-

I agree with Arnoutdv: it doesn't matter the method, you need to store the result in a valriable. I usually use a Static variable.



```
Public Function InIDE() As Boolean
    Static sValue As Long
    
    If sValue = 0 Then
        Err.Clear
        On Error Resume Next
        Debug.Print 1 / 0
        If Err.Number Then
            sValue = 1
        Else
            sValue = 2
        End If
        Err.Clear
    End If
    InIDE = (sValue = 1)
End Function
```

----------


## Elroy

This is the one I currently use:



```

Public Function InIDE(Optional ByRef b As Boolean = True) As Boolean
    ' NEVER specify the Optional b when calling.
    If b = True Then Debug.Assert Not InIDE(InIDE) Else b = True
End Function


```


It was inspired by something I saw The Trick do.  It's nice in that no disk I/O is performed.  And it's very fast and terse.  Also, it won't tamper with the Err object.  I've used maybe half-a-dozen through the years, and I think the above is best.

EDIT1:  I suppose you could add a Static to it to make it slightly faster, but it's pretty fast as it is.  I'll let loquat test if he likes.   :Smilie:

----------


## Victor Bravo VI

Prior art:




> ```
> 
> Private Function InIDE(Optional ByRef B As Boolean = True) As Boolean   'Very efficient function for testing whether
>     If B Then Debug.Assert Not InIDE(InIDE) Else B = True               'this code is running in the IDE or compiled
> End Function                                                            'Based on the original by Vesa Piittinen
> 
> ```

----------


## wqweto

You cannot make InIDE3 faster by adding a static as the single Debug.Assert eventually gets removed, so in compiled executable it gets reduced to a no-code function w/ no parameters. 

The only way to beat this is if you don't call anything at all I suppose :-))

cheers,
</wqw>

----------


## Eduardo-

> You cannot make InIDE3 faster by adding a static as the single Debug.Assert eventually gets removed, so in compiled executable it gets reduced to a no-code function w/ no parameters. 
> 
> The only way to beat this is if you don't call anything at all I suppose :-))
> 
> cheers,
> </wqw>


Compiled yours and Elroy's one are quite faster than mine.

Compiled, 100,000,000 iterations:



```
InIDE3               0.101
mine                 2.226    
Elroy's              0.156
global variable      0.046
```

Uncompiled, 100,000,000 iterations:



```

InIDE3               8.031
mine                 4.789
Elroy's              8.304
global variable      0.507
```

But if speed is really an issue, the best (of course) is to use just a variable and set it up when the program starts.

PS: I didn't test others.

----------

