DOCUMENT:Q190217 07-AUG-1998 [vbwin] TITLE :HOWTO: Get Free System Resources in 32-Bit Visual Basic PRODUCT :Microsoft Visual Basic for Windows PROD/VER:WINDOWS:4.0,5.0,6.0 OPER/SYS:WINDOWS KEYWORDS: ====================================================================== --------------------------------------------------------------------- The information in this article applies to: - Microsoft Visual Basic for Windows Learning, Professional, and Enterprise Editions, versions 5.0, 6.0 - Microsoft Visual Basic Standard, Professional, and Enterprise Editions, 16-bit and 32-bit, for Windows, version 4.0 --------------------------------------------------------------------- SUMMARY ======= In 16-bit versions of Visual Basic, you can determine free system resources by calling the GetFreeSystemResources Windows API function. For 32-bit versions of Visual Basic, there is no Win32 API function that provides that information. To determine free system resources in a 32-bit Visual Basic application, you must call a 16-bit application. This article includes instructions to: 1. Create a 16-bit Visual Basic 4.0 OLE server that determines free system resources and provides that information to OLE clients. 2. Call the 16-bit OLE server from a 32-bit version of Visual Basic and get free system resources from it. MORE INFORMATION ================ If your Visual Basic application loads a very large number of certain controls, such as ComboBoxes, you may run out of system resources, which will result in an "out of memory" error (error #7), and may cause Windows to stop responding. You can monitor system resources with the 16-bit Windows API function GetFreeSystemResources. In Windows 95 and Windows 98, GetFreeSystemResources checks the percentage of free memory in the following five resource heaps: 1. The 16-bit User heap (64K). 2. The 32-bit User window heap (2MB). 3. The 32-bit User menu heap (2MB). 4. The 16-bit GDI heap (64K). 5. The 32-bit GDI heap (2MB). First, it finds the lowest of the three User heaps, and the lowest of the two GDI heaps. The 16-bit, 64K heaps are almost always the lowest. Next, for each of the two lowest, it divides the percentage free by the percentage that was free when Windows was started. Finally, it returns the lowest of the two. For example, suppose the five heaps had the following percentages free at the time Windows started: Heap Percentage Free ============================= =============== 16-bit User heap (64K) 80% 32-bit User window heap (2MB) 99% 32-bit User menu heap (2MB) 99% 16-bit GDI heap (64K) 75% 32-bit GDI heap (2MB) 99% Later, with some applications running, suppose the free memory in the five heaps had dropped to these percentages: Heap Percentage Free ============================= =============== 16-bit User heap (64K) 40% 32-bit User window heap (2MB) 98% 32-bit User menu heap (2MB) 98% 16-bit GDI heap (64K) 25% 32-bit GDI heap (2MB) 98% GetFreeSystemResources starts by finding the lowest of the three User heaps (40%), and the lowest of the two GDI heaps (25%). In both cases, the 16- bit, 64K heap is lowest. Next, GetFreeSystemResources divides the percentage free by the percentage that was free when Windows was started. For the User heap, that's 40%/80% = 50%. For the GDI heap, it calculates 25%/75% = 33%. Finally, it returns the lowest of the two, 33%. Note, this behavior is different than GetFreeSystemResources in Windows 3.1 in two ways: 1. The three 2MB heaps did not exist in Windows 3.1. 2. It did not divide the percentage free from the percentage that was free at the time Windows started. As a result, it returned a lower percentage. In the example above, GetFreeSystemResources in Windows 3.1 would have returned 25% instead of 33%. There is no 32-bit version of GetFreeSystemResources. In Windows 95, 98, and NT, GetFreeSystemResources has been replaced by GlobalMemoryStatus, which returns the amount of free global memory. Because Windows 95, 98 and NT handle system resources more efficiently than Windows 3.x, system resources are usually less of a concern and free global memory is usually more relevant. GlobalMemoryStatus is sometimes confused as being equivalent to GetFreeSystemResources, but in fact it is designed to return entirely different information. While GetFreeSystemResources returns the free percentage of the GDI and User heaps, GlobalMemoryStatus returns the amount of free global memory. In Windows 3.x, 95, and 98, Windows allocates a fixed amount of memory to each of the GDI and User heaps at startup, and can never allocate any more to them no matter how much global memory is free. As a result, it is possible to run out of free system resources while there is still abundant free memory. Because GlobalMemoryStatus does not return information about the GDI and User heaps, it is not appropriate to use GlobalMemoryStatus to monitor these system resources. To determine free system resources in a 32-bit Visual Basic application, you must create and call a 16-Bit application that calls GetFreeSystemResources and exposes the information to other applications. Note that Windows NT (all versions) is designed to dynamically allocate memory to the GDI and User heaps as needed. GetFreeSystemResources always returns 90% on Windows NT. Unlike other versions of Windows, Windows NT does not run out of system resources and stop responding. It is highly unlikely that your Visual Basic application will have any need to monitor system resources on Windows NT. Also note that Windows 95 and 98 manage system resources considerably more efficiently than Windows 3.x. Many items formerly stored in the 64K User and GDI heaps in Windows 3.x are now stored in the three 2MB heaps in Windows 95 and 98. See the REFERENCES section below for more information. The following steps show how to create a 16-bit Visual Basic 4.0 OLE server that determines free system resources and provides that information to OLE clients, and to call the 16-bit OLE server from a 32-bit version of Visual Basic and get free system resources from it. Note, the OLE Server must be created with 16-bit Visual Basic 4.0; it cannot be created with Visual Basic 5.0 or later, or with 32-bit Visual Basic 4.0. If you do not have Visual Basic 4.0, but do have Visual Basic 1.0 for Windows, 2.0, or 3.0, you can use DDE (Dynamic Data Exchange) rather than OLE to provide the information to 32-bit applications. In Visual Basic 3.0, see chapter 21 in the Visual Basic Programmer's Guide, "Communicating with Other Applications." If you are a C programmer, you can create a "flat thunking" DLL to provide the information on Windows 95 and 98. You cannot do flat thunking directly in Visual Basic, because it requires calling functions given only pointers to their addresses in memory. See the REFERENCES section below for where to find more information. Step-by-Step Example -------------------- 1. Start 16-bit Visual Basic 4.0. Note this will not work with 32-bit Visual Basic 4.0, or with Visual Basic 5.0 or later. 2. Create a new project. Form1 is added by default. 3. Choose Module from the Insert menu to add a standard module, and add the following code to it: Declare Function GetFreeSystemResources Lib "User" _ (ByVal fuSysResource As Integer) As Integer Const GFSR_SYSTEMRESOURCES = &H0 Sub Main() 'Stub only. End Sub 4. Choose Class Module from the Insert menu to add a class module, and add the following code to it: Public Function SystemResources() SystemResources = GetFreeSystemResources _ (GFSR_SYSTEMRESOURCES) End Function 5. Change the Name property of the class module to clsSR. 6. Change the Instancing property of the class module to Createable SingleUse. 7. Change the Public property of the class module to True. 8. Alternate click on Form1 in the Project window, and choose "Remove File" to remove the default form. 9. Choose Options from the Tools menu, and select the Project tab. Change the project name to prjSR, and then change StartMode to "OLE Server." 10. From the File menu, save the project, and make the EXE. 11. Start a 32-bit version of Visual Basic, such as Visual Basic 4.0 32-bit, or version 5.0 or later. 12. Create a new project. Form1 is added by default. 13. Choose References from the Project menu (in 32-bit Visual Basic 4.0, choose References from the Tools menu), and check prjSR. Click OK. 14. Double-click on Form1, and add the following code to the Form_Load event: Dim oSR As New prjSR.clsSR MsgBox oSR.SystemResources & _ "% of system resources are free." Set oSR = Nothing 15. Run the project. The Message Box will show the percentage of free system resources. REFERENCES ========== "Windows 95 System Programming Secrets," by Matt Pietrek, IDG Books For more information on improvements in system resources handling in Windows 95 and 98, please see the following article in the Microsoft Knowledge Base: ARTICLE-ID: Q117744 TITLE : Explanation of System Resources in Windows 95 http://support.microsoft.com/support/kb/articles/q117/7/44.asp. For information on creating flat thunking DLLs in C, please see the following article in the Microsoft Knowledge Base: ARTICLE-ID: Q155763 TITLE : HOWTO: Call 16-bit Code from 32-bit Code on Windows 95 http://support.microsoft.com/support/kb/articles/q155/7/63.asp Additional query words: kbDSupport kbDSD kbAutomation KbClientServer kbVBp kbVBp300 kbVBp400 kbVBp500 kbVBp600 ====================================================================== Version : WINDOWS:4.0,5.0,6.0 Platform : WINDOWS Issue type : kbhowto ============================================================================= THE INFORMATION PROVIDED IN THE MICROSOFT KNOWLEDGE BASE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND. MICROSOFT DISCLAIMS ALL WARRANTIES, EITHER EXPRESS OR IMPLIED, INCLUDING THE WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL MICROSOFT CORPORATION OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER INCLUDING DIRECT, INDIRECT, INCIDENTAL, CONSEQUENTIAL, LOSS OF BUSINESS PROFITS OR SPECIAL DAMAGES, EVEN IF MICROSOFT CORPORATION OR ITS SUPPLIERS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. SOME STATES DO NOT ALLOW THE EXCLUSION OR LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES SO THE FOREGOING LIMITATION MAY NOT APPLY. Copyright Microsoft Corporation 1998.