Category Archives: Api/Operating System

Code and posts related to the Windows API and Operating System.

Getting the Computers Windows Directory using VB and Visual Basic.NET

This little article will show you how to get the Windows directory/folder using both classic vb and For some reason Microsoft didn’t add built-in support for getting the path of the users windows directory until .NET 4.0. It is located under the: Environment.SpecialFolders feature. Otherwise I will show a way to get the windows path in the earlier versions of VB.NET and a way to get the directory path using VB 6.0 and Visual Basic.NET.

Both VB6.0 and Visual Basic NET

This is a simple API call that will give you the windows installed directory for the computer. You just need to create a string buffer and the api function will set the information you want in that buffer.

'Visual Basic 6.0 Declare

  Private Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Long) As Long
'Visual Basic.NET Declare

 Private Declare Function GetWindowsDirectory Lib "kernel32" Alias "GetWindowsDirectoryA" (ByVal lpBuffer As String, ByVal nSize As Int32) As Int32

Remaining code for API Method for All VB’s below…

'For both VB and VB.NET. This variable is for receiving the path from the API call.

    Dim winDir As String

 'Create a simple string buffer that will be passed to the api call to receive the directory for windows.

     winDir = Space$(255)

  'The winDir variable will get the value from the api call.

      GetWindowsDirectory winDir, Len(winDir)

'Trim the end of the value to remove the unused whitespaces from the string buffer.

      winDir = RTrim(winDir)

'This should throw a message box displaying the windows directory for the target computer.


When executing the code above, you should get a messagebox with the target computers Windows directory. It could be something similar to: “C:\Windows”

.NET based only using MY. below

Like I mentioned earlier Microsoft failed to include the Windows Directory as a Special Folder until .NET 4.0. But there is a another easy way to do it if you don’t want to use the API method.

This first way will actually use the Special Folder feature in .NET but will target the Environment.SystemDirectory. Since the System32 directory is always located under the base windows folder all you have to do is get the parent path of the SystemDirectory.


The code above will throw a message with the parent path for the System32 directory. In my case is returned ‘c:\Windows’ just like the API version did.

There are other ways to get the windows direcory like checking a environment variable that I might add later on. The API version works great for both VB 6.0 and VB.NET, and the System32 method works just fine for .NET.  Remember Microsoft included the WindowsDirectory as a SpecialFolder in Visual Basic 2010 so you should use that method if possible. Anyways, thats all!


Revised: 2015

Counters/Timers for the Visual Basic and VB.NET programmer

This article can be applied to all versions of VB including 6.0. Any code that may be posted here is originally set up for the .NET, but codes should be compatible with VB 6.0 by changing the variables and the declares to the right type and format. Example: If something is set to type Integer for .NET, the equivalent in VB 6.0 is Long. Otherwise, most of the .NET code should work fine in 6.0. The only trouble you may have is using 64 Bit Integers, which Classic VB doesn’t quite support. A work-around it using the Currency type (Which is technically a 64 Bit type) and converting it to a string while removing the decimal point. Check out this page for how to use the 64-bit Currency type in VB 6.0

Timers/Counters Info

This question on what timers are available using Visual Basic has a somewhat simple answer. Well, depending on the resolution you need to have.

GetTickCount – The “GetTickCount” function has a resolution of about 15-16(ms). IT returns the amount of milli-seconds that has elasped since your Windows OS has started.

    'Provides about a 16(ms) resolution.
    Private Declare Function getTickCount Lib "kernel32" Alias "GetTickCount" () As Integer

timeGetTime – If you need better accuracy, then you can try the multi-media timer: “timeGetTime” function, which can have a resolution of about 1(ms). It likewise returns the number of milli-seconds that has elasped since your Windows OS was started. But is has a much better resolution compared to the tick count function.

    'Provides a resolution of 1(ms).
    Private Declare Function timeGetTime Lib "winmm.dll" () As Integer

QueryPerformanceCounter – But, what if you need even better accuracy/resolution? The next option would be to use the computers high “Performance Timers”. (To check if the target computer actually supports this hardware timer, you would call either of the performance functions and look at its Return Value. If the return value is “0”(Zero), then the computer doesn’t support the hardware counter/timer feature. Not much more to say about this except you won’t be able to use this option.)

These functions are: ‘QueryPerformanceCounter’ and ‘QueryPerformanceFrequency’. With these functions its possible to get Sub-Millisecond accuracy/resolution. These timers could use a very small chip on your computers motherboard, which usually has a frequency of about: 3.6 Mhz. In some probably rare accurances these functions will actually use the RDTSC timestamp of your computers Processor. This would obviously have the highest resolution of all the timers in the computer. You can measure time in actual CPU Cycles. But i’ve rarely had this timer use that processor feature. In fact, I only witnessed it one time using my CPUs ReaDTimeStampCounter register. This would vary from computer to computer though. Microsoft says these functions could use either of these counters. * To determine which feature this counter/timer is using, you can use the function: QueryPerformanceFrequency function. This function returns the TickPerSeconds for the Performance Counter. Probably the most common value would be: 3579545. Which means that every second, this timer ticks 3,579,545 times, or around 3.6 million cycles per second. IF you have a 2ghz cpu/processor, and it is using your cpu’s rdtsc register, then the return value would be around the clockspeed of your processor.

    'Gives you the current tick counts for the cpu since the computer has been running.
    'You could get very high resolutions in the Sub-Millisecond range with this counter/timer.
    Private Declare Function QueryPerformanceCounter Lib "kernel32" (ByRef counts As Long) As Integer
    'Returns the frequency of the performanceCounter in counts-per-second.
    Private Declare Function QueryPerformanceFrequency Lib "kernel32" (ByRef frequency As Long) As Integer

RDTSC Register – This is a feature of all modern AMD/Intel CPUs/Processors since the original Pentium 1 was released. This timer ‘Ticks’ every time your Processor completes a ‘Cycle’. As you can probably discern, you can have some major high resolution timing available. But the big problem for getting to this timer if that its pretty much not possible to access this register on the CPU with the high level languages of Visual Basic and C#. But, if you can do a somewhat simple C++ DLL application, you can access this register and create a function in the .dll that will return the value of that timer when Visual Basic calls that .dll function. This is actually what I did with my: csRDTSC.dll I made with C++. IF you would like to use this .dll, just goto my main: webpage and under either the Classic or DotNET controls section page you can download and use it. The zip file includes the actual .DLL and a text file with the available functions.

Reference Information

Here is some reference links here that are related to these timer functions that would be more helpful.

QueryPerformanceCounter Reference…

Overview: QueryPerformanceCounter Function

How To: Time Managed Code Using QueryPerformanceCounter and QueryPerformanceFrequency

timeGetTime Reference

Multimedia Timer Reference – Overview of the timeGetTime related timers as
timeGetTime – The timeGetTime function retrieves the system time, in milliseconds. The system time is the time elapsed since Windows was started.

GetTickCount Reference…

GetTickCount Function

GetTickCount64 Function

How To – Retrieve Elapsed Time Since Windows Started


I really do hope you can get something useful from this small and brief article. I have many examples on my main webpage at: which shows how to use these timers. I even have a VB.NET – Example that compares the 3x most common timers that I outlined above. I also have a example for all of the Visual Basic versions (including Visual Basic.NET) that shows how to use my csRDTSC.DLL to get the time stamp value from the cpu and to calculate your processors clockspeed. Anyways, have fun 🙂


Minor Revision: 2015

Auto Complete Support in Textbox and Combobox Controls using VB 6.0 and VB.NET

Autocomplete is a very useful feature that Microsoft added with the release of Internet Explorer 5.0 and therefore Internet Explorer 5.0 or higher needs to be installed on the target computer. Adding autocomplete to your applications can be a real benefit to the user and is a easy feature to implement.

Note: Visual Basic 2005 and Visual Basic 2008 already has Autocomplete capabilities in the Textbox and Combobox controls by default.

There are a few different locations you can get the autocomplete data from…

  • File System
  • History List
  • URLs Recently Used
  • ALL URLs
  • ALL System Sources

There are likewise a few different options available to set the way you want AutoComplete to react.

  • Append
  • Suggest
  • Append & Suggest

Visual Basic.NET

    'The API call that enables the autoComplete feature to your combo or textbox controls.
    Private Declare Sub SHAutoComplete Lib "shlwapi.dll" (ByVal controlHandle As Int32, ByVal _
        completeFlags As Int32)

Visual Basic 6.0

    'The API call that enables the autoComplete feature to your combo or textbox controls.
    Private Declare Sub SHAutoComplete Lib "shlwapi.dll" (ByVal controlHandle As Long, ByVal _
        completeFlags As Long)

The SHAutoComplete API Sub is easy to use. The first parameter is the Handle to the Edit (Combobox/Textbox) control you want to enable Auto Complete too. The second Parameter is how you want your Autocomplete to react and display.


    'Various Flags you can set to be the source.
    Private Const Defaults = &H0

    Private Const Filesystem = &H1

    Private Const HistoryList = &H2

    Private Const URLRecentlyUsedList = &H4

    Private Const AllURLs = (HistoryList Or URLRecentlyUsedList)

    Private Const AllSystemsSources = AllURLs Or FileSystem

The flags below are used to specify how you want your autocomplete feature to react.

    'Flags you can use to specify how your want autocomplete to react.
    Private Const append = &H40000000 Or &H20000000

    Private Const suggest = &H10000000 Or &H80000000

    Private Const suggestAppend = &H40000000 Or &H10000000

Now that the API based codes are out of the way, you can setup the edit based controls (Like Textbox and Combobox) to have Autocomplete capabilities. Below is a simple example of adding autocomplete to a textbox control that I named txt.

        'Set autocomplete to the textbox using the system defaults.
        SHAutoComplete(txt.hWnd, Defaults)

        'You can also specify how it will react and what it will display.
        SHAutoComplete(txt.hWnd, suggest Or AllURLs)

If your using .NET, just change txt.hWnd to txt.Handle.ToInt32.

Unfortunately adding this feature to a Combobox isn’t as straight forward. Thats because when you use the Handle/Hwnd Property for the Combobox it returns the Main Window Portion of the control and NOT the Edit Window portion. There are a couple ways to get around this though. One way it to use the GetComboBoxInfo API or to use the FindWindowEx API call. I chose to go ahead and use the FindWindowEx API.

Visual Basic.NET

    'API Function used to get the Edit window of a combobox control.
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal hWnd1 As  _
        Int32, ByVal hwndChildAfter As Int32, ByVal lpszClass As String, ByVal lpszWindow As String) As Int32

Visual Basic 6.0

    'API Function used to get the Edit window of a combobox control.
    Private Declare Function FindWindowEx Lib "user32" Alias "FindWindowExA" (ByVal handle As _
        Long, ByVal hwndChildAfter As Long, ByVal lpszClass As String, ByVal lpszWindow As String) As Long

Now you just need to use the FindWindowEx Function using the 1st and 3rd parameter. And once you call the FindWindow function, simply pass its return value to the SHAutoComplete Method.

        'Simply change this variable type to a Integer if your using VB.NET.
        Dim cmbHandle As Long

        'Retrieve the handle to the ‘Edit’ Window of the combobox. I named my Combobox control cmb.
        cmbHandle = FindWindowEx(cmb.hWnd, 0, "Edit", vbNullString)

        'Activate Autocomplete to the combobox edit window.
        SHAutoComplete(cmb.hWnd, Defaults)

Tip: Here is how you can specify exactly how to react and display….

        'You can also specify how it will react and what it will display.
        SHAutoComplete(cmb.hWnd, suggest Or AllURLs)

Again, change cmb.hWnd to cmb.Handle.ToInt32 if your using Visual Basic.NET.

Thats all there is to it! Depending on your application, you or your apps user will really appreciate you putting that feature in your program. Well, I guess there is nothing more to add. Have fun!


Detecting if the User is Active or Idle – SystemWide using VB 6.0 and VB.NET

There are times when you want to know not only if your user is interacting with your application but actually interacting anywhere on the computer. Especially if you are waiting for somekind of user Input. Microsoft thankfully made it easy as I found a API call on and I converted it from C++ to work with Visual Basic (Works for .NET, VB 2008/2010, VB 2013, and 2015). I actually have a VB 6.0 Example for doing this at my website. Below is the little API call…

Visual Basic 6.0

    'The actual API call to use.
    Private Declare Function GetLastInputInfo Lib "user32.dll" (ByRef inputStructure As inputInfo) As Boolean
    Private Type inputInfo

        structSize As Long

        tickCount As Long

    End Type

Visual Basic.NET Version…

    'The actual API call to use.
    Private Declare Function GetLastInputInfo Lib "user32.dll" (ByRef inputStructure As inputInfo) As Boolean
    Private Structure inputInfo

        Dim structSize As Int32

        Dim tickCount As Int32

    End Structure

Now that the APIs are out of the way, you only need to setup and use the codes. The code below will work for ALL VBs with just some minor changes…

Visual Basic 6.0

        'The variable that will be passed to the API call and receive the activity report.
        Private info As inputInfo
        'Visual Basic 5.0/6.0…
        Dim firstTick As Long
        Dim lastTick As Long

Visual Basic.NET…

        'The variable that will be passed to the API call and receive the activity report.
        Private info As inputInfo
        'Visual Basic.NET…
        Dim firstTick As Int32
        Dim lastTick As Int32

All I did next was use the code in a Timer control and set the Interval to 1000ms (1 Second) which will update the lblTime Label Control the Last time of day the user was active. The InputInfo structure will actually give you the tickcount for when the user was last active if you want to use that. I decided to simply get the actual time they were last active

        'This timer will fire every 1000ms(One Second) or so displaying the last time the user was active.
        'The size of the structure for the API call.
        info.structSize = Len(info)
        'Call the API.
        'Compare the tickcount values to determine if activity has occurred or not.
        If firstTick <> info.tickCount Then
            'Display the current time of the users last activity.
            'Change lblTime.Caption to lblTime.Text if using .NET and likewise change Time
            'to Now instead.
            lblTime.Caption = "Last Active: " & Time
            'Get the new tick value.
            firstTick = info.tickCount

        End If

The example program wth the code in action

As I mentioned already, I put that code above in a Timer control, then I set to enable and disable the timer in Two Button controls.

Now your application will know when the user was last active on the computer. But remember, just because it says they are Not active doesn’t mean that they are not reading a document, a website, or some other task that doesn’t require user input. Have fun!


Revised: 2015

Readymade Options for Playback of Music/Audio Files in VB and VB.NET – 1 of 2

This article and Part Two are to show some options available for Audio/Music playback if your not interested in making your own control or library. I do have an article on how to do basic music playback at this link with some quick and simple source code. But if you want more advanced features and don’t want to create the bulk of the playback code, then the content in these articles should help you out. This first article is on using some libraries I made around the MCISendString Windows API function and doesn’t have 3rd party dependency.

Note: You can now check out part two at this link on two 3rd party controls named Bass.dll and FMod.dll.

Visual Basic 6.0

For VB 6.0 is Music Module v2.2 that I made with Visual Basic 6.0 and contains the main features that a music player usually needs. It supports the most popular music formats like Wave, MIDI, and MP3 files. Some other features are calculating the MP3’s overall Bitrate, getting the Playing Position in various formats, Left/Right Volume Control with Muting, etc. While the class module is old, it still does the job well and does not rely on any 3rd Party .DLL’s or Resources. You can download the Class Module with Example at this link.

Visual Basic.NET 2002/2003

This option is basically for VB.NET 2002/2003 and would recommend you use it for those versions only. This library is called csMusicLibrary v1.0 Professional. This class contains more features than the VB 6 library.  The class has all of the features required for a normal music player and some extra features like basic playlist support, setting the music playback rate, setting the playing position and more. IF your interested in this option you can download the compiled class with example at this link.

Visual Basic 2005/2008/2010, and Higher

This next library definitely has the most features out of the options in this article. It is a major overhaul of the original csMusicLibrary. It is csMusicLibrary v3.1 – The Professional Series and made with Visual Basic 2005. It is completely XML commented with explanations about the Subs/Functions and Properties along with remarks. There are many options available and is easy to use and understand. Besides your normal playback features it can give your applications some basic recording capabilities, extract MP3 Tag v1.1 information, get the music playback status, and much more. Like the other options outlined above, this library does not rely on any 3rd party controls or resources. If you don’t need any super advanced features like visualizations, data manipulation, or sound effects, etc. then this library should work just fine for making a fully featured music application. You can download the compiled class with example at this link.

All these options should be fine for making a nice featured application. But you may be wanting more advanced features like FFT’s, Data Manipulation, Sound FX, and so on. That is where the next article will come in. Click this link to read part two about some third party controls. Have fun 🙂


Revised: 2014

Why Simply Calling ExitWindowsEx won’t Shutdown or Restart Windows XP, Vista, 7, and Newer

Simply executing the ExitWindowsEx API function works fine using older versions of Windows like Windows 98 or ME. You only needed to call the ExitWindowsEx with the desired parameters and it was good to go. But with the regular consumer family of Windows starting with Windows XP, Microsoft based the OS on NT/2000 which is a very different Kernel and Architecture. That includes Windows Vista, Windows 7, 8/8.1, and 10 as well. Your programs are now required to have ‘special privileges’ before it will grant your application’s request to shutdown/restart/logoff the device. Visual C++ has these Privileges by default, but not any of the VBs unfortunately. So the first step you must do is request your application be granted the required privileges. The source code below was originally in VB 6.0 code from Microsoft that I converted to Visual Basic .NET. The code here will work with all versions of .NET including 2005, 2008, plus Visual Basic 2010, and newer. There are only minor changes needed to make it work with Visual Basic 6.0, mainly the variable/parameter types like changing the Integers to Long types. I went ahead and put the VB.NET source code in this post.

Note: If you are wanting to get the original VB 6.0 privilege codes then click on this link and/or click this link as well.

Need to first get some structures for the APIs.

    Private Structure LUID

        Dim UsedPart As Integer

        Dim IgnoredForNowHigh32BitPart As Integer

    End Structure

    Private Structure TOKEN_PRIVILEGES

        Dim PrivilegeCount As Integer

        Dim TheLuid As LUID

        Dim Attributes As Integer

    End Structure

Next you can go ahead and add the needed API methods to execute the privilege requests.

    'The API functions below are all used to give the application the proper privilege so the OS will allow the app to Shutdown Windows.
    Private Declare Function OpenProcessToken Lib "advapi32" (ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As Integer) As Integer

    Private Declare Function LookupPrivilegeValue Lib "advapi32" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LUID) As Integer

    Private Declare Function AdjustTokenPrivileges Lib "advapi32" (ByVal TokenHandle As Integer, ByVal DisableAllPrivileges As Boolean, ByRef NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Integer, ByRef PreviousState As TOKEN_PRIVILEGES, ByRef ReturnLength As Integer) As Integer

Now to setup and create a Sub that will do all the work to set your privileges.

    'This sub will do all of the work of setting up your apps process using the APIs posted above to get the
    'proper privileges to shutdown the OS.
    'I originally got this function from msdn and converted it from VB 6.0 to VB.Net and did a tweak here and there.
    Private Sub AdjustToken()

        Const TOKEN_ADJUST_PRIVILEGES As Int32 = &H20

        Const TOKEN_QUERY As Int32 = &H8

        Const SE_PRIVILEGE_ENABLED As Int32 = &H2

        Dim hdlProcessHandle As IntPtr

        Dim hdlTokenHandle As Int32

        Dim tmpLuid As LUID

        Dim tkp As TOKEN_PRIVILEGES

        Dim tkpNewButIgnored As TOKEN_PRIVILEGES

        Dim lBufferNeeded As Int32

        hdlProcessHandle = Process.GetCurrentProcess.Handle

        OpenProcessToken(hdlProcessHandle, (TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY), hdlTokenHandle)

        'Get the LUID for shutdown privilege.
        LookupPrivilegeValue("", "SeShutdownPrivilege", tmpLuid)

        tkp.PrivilegeCount = 1 'One privilege to set

        tkp.TheLuid = tmpLuid

        tkp.Attributes = SE_PRIVILEGE_ENABLED

        'Enable the shutdown privilege in the access token of this process.
        AdjustTokenPrivileges(hdlTokenHandle, False, tkp, Len(tkpNewButIgnored), tkpNewButIgnored, lBufferNeeded)

    End Sub

Now that the main Privilege codes are done, you just need one more API Function.

Below is the API call you execute to perform the actual shutdown/restart/logoff command on the computer.

    'The function used to actually send the request to shutdown windows. Set the ‘shutdownTypes’ parameter to whether you want windows to “shutdown, reboot, logOff, ect…” You can get those at MSDN or download one of my examples from my website.
    Private Declare Function ExitWindowsEx Lib "user32" (ByVal shutdownType As Integer, ByVal dwReserved As Integer) As Integer

Edit: As per Garry’s comment below, I included some relevant flags you can use with the ExitWindowsEx function.

        Private Const EWX_LOGOFF As Integer = &H0
        Private Const EWX_SHUTDOWN As Integer = &H1
        Private Const EWX_REBOOT As Integer = &H2
        Private Const EWX_FORCE As Integer = &H4
        Private Const EWX_POWEROFF As Integer = &H8
        Private Const EWX_FORCEIFHUNG As Integer = &H10 '2000/XP only

OK, now you first need to call the AdjustToken()  Sub and then the ExitWindowsEx Function. This example code will Log Off the user.


        'Calls the function to begin executing.
        ExitWindowsEx(EWX_LOGOFF, Nothing)

That’s all there is to it! OK, it Is a lot of code to get the ExitWindowsEx API to work with Windows 2000/XP/Vista/7/8/8.1/10.0. To bad Microsoft doesn’t give Visual Basic these Privileges by default like they do with C++. Oh well, don’t have much of a choice.

Remember, its possible to get these codes to work with Visual Basic 6.0 as well. You need to change the types (Especially Integers to Longs, and Structures to Types) plus process info then it should be ok. Or click on this link to the original code

I have pre-made Class Libraries and Examples for Visual Basic.NET, VB 2005/2008/2010/2012, and Visual Basic 2013. I also have an Example of doing this in Visual Basic 6.0 at my Visual Basic Code Source website.

Well that’s all for now. Have Fun!


Revisited: 2015

FREE eBook – Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET

This is another resource that how been around for awhile but is still plenty useful and helpful. Especially if your a Visual Basic 5.0/6.0  developer making the move to Visual Basic.NET. It is pretty large and covers a wide range of areas taking up TwentyOne(21x) Chapters. It goes over The differences between VB Classic and .NET to Resolving Upgrade Issues and Preparing your Applications for the Upgrade. Below is a small excerpt…


Upgrading Microsoft Visual Basic 6.0 to Microsoft Visual Basic .NET is the complete technical guide to upgrading Visual Basic 6 applications to Visual Basic .NET, covering all upgrade topics from APIs to ZOrders. It shows how to fix upgrade issues with forms, language, data access, and COM+ Services, and how to upgrade applications with XML Web services, ADO.NET, and .NET remoting. It also provides big-picture architectural advice, a reference of function and object model changes, hundreds of before-and-after code samples, and a CD packed with useful examples.

If you are interested in this resource, then click this link to check it out. Try this link as well. Have fun 🙂


How to Easily Play Wave Files with Visual Basic.NET and Newer

It’s actually quite easy to play wave files (.wav waveform based sound files) using just alittle code in some cases. The .NET Framework 2.0, 3.5, 4.0, and higher has a managed wrapper around the PlaySound API.

The easiest way to play wave files with Visual Basic 2005, VB 2008, VB 2010, and newer is as shown below…

    'Play a wave sound file from a specified location.

    'Stop the file from playing.

    'Play a Windows system sound.

The code above simply used the MY Interface for quick access to the Audio class to play a file, stop the playback, and then playback a system sound.

What about playing wave sound files with Visual Basic.NET 2002 and Visual Basic.NET 2003?

Continue reading