Read System Variables in Windows

Windows specific questions.
Posts: 63
Joined: Jul 15, 2009 12:41

Read System Variables in Windows

Postby geminis4941 » Nov 01, 2016 19:51

I have probed to read system variables in windows 7 , but it only retrieve system variable value when the program compiles with:
C:\FreeBASIC-0-90\fbc -s console "FbTemp.bas".
It dont work when compiles with:
C:\FreeBASIC-0-90\fbc -s gui "GetEnvironmentvarwin32.bas"
Anyone knows what happens or how I can read system variables in GUI mode.

Code: Select all

   Dim envvar As String  ' receives the value of the environment variable
   Dim vname As String
   Dim slength As Long  ' length of the string copied into envvar
   Dim retval As Long  ' return value
   envvar = Space(256)
   vname = "resources"
   slength = GetEnvironmentVariable(vname, envvar, Len(envvar))
   If slength = 0 Then
      'Print "The environment variable does not exist on this system."
      envvar = Left(envvar, slength)      
      Print vname ;"="; envvar
   End If
Posts: 3500
Joined: May 16, 2006 22:34
Location: USA

Re: Read System Variables in Windows

Postby MichaelW » Nov 02, 2016 19:22

GetEnvironmentVariable works the same from a Windows GUI app as it does from a console app. The problem is with trying to display the variable value with Print, which needs a console to display on. One easy way around this problem is to build the Windows GUI app as a console app, so in addition to the GUI, the app also has a console (this method also works well for debugging a Windows GUI app that cannot otherwise display diagnostic information).

The following example when compiled as a GUI app will display the environment variable value (or an error message if the variable is not found) in a MessageBox. When compiled as a console app it will display the environment variable value (or an error message if the variable is not found) in a MessageBox and on the console.

Note that the example uses the SetClientSize procedure simply because I created the example from existing code, to save time.

Edit: Forgot to deallocate the environment variable buffer in two places, now corrected.

Code: Select all

#include ""
#define CLIENTWIDTH 400
#define CLIENTHEIGHT 300

'' This procedure sizes the specified window so the client area is the
'' specified width and height and optionally centers the window on the
'' the screen. Unlike AdjustWindowRect and AdjustWindowRectEx, this
'' procedure can handle a window with the WS_OVERLAPPED style.

sub SetClientSize( hwnd as HWND, pixelWidth as integer, _
                   pixelHeight as integer, bCenter as BOOL )

    dim as integer x, y, w, h
    dim as RECT rcc, rcw

    GetClientRect( hwnd, @rcc )
    GetWindowRect( hwnd, @rcw )

    w = (rcw.right - rcw.left) - (rcc.right - pixelWidth) - 1
    h = (rcw.bottom - - (rcc.bottom - pixelHeight) - 1

    if bCenter then
        x = (GetSystemMetrics( SM_CXSCREEN ) / 2) - w / 2
        y = (GetSystemMetrics( SM_CYSCREEN ) / 2) - h / 2
        x = rcw.left
        y =
    end if

    MoveWindow( hwnd, x, y, w, h, TRUE )

end sub


function WindowProc( hwnd as HWND, uMsg as UINT, _
                     wParam as WPARAM, lParam as LPARAM) as LRESULT
    static as zstring ptr p
    select case uMsg

        case WM_CREATE

            SetClientSize( hwnd, CLIENTWIDTH, CLIENTHEIGHT, TRUE )
            dim as integer size           
            size = GetEnvironmentVariable( "ComSpec", 0, 0 )
            p = callocate(size)
            if GetEnvironmentVariable( "ComSpec", p, size ) = 0 then
                print "NOT FOUND"
                MessageBox( 0, "NOT FOUND", "ComSpec", 0 )               
                print *p
                MessageBox( 0, p, "ComSpec", 0 )
            end if

        case WM_COMMAND

            if wParam = IDCANCEL then           
                deallocate( p )               
            end if 
        case WM_CLOSE

            DestroyWindow( hwnd )           
            deallocate( p )

        case WM_DESTROY

            PostQuitMessage( 0 )

        case else

            return DefWindowProc( hwnd, uMsg, wParam, lParam )

    end select

end function


dim as HWND hwnd
dim as MSG msg
dim as WNDCLASSEX wcx

wcx.cbSize = sizeof(WNDCLASSEX) = 0
wcx.lpfnWndProc = @WindowProc
wcx.cbClsExtra = 0
wcx.cbWndExtra = 0
wcx.hInstance = GetModuleHandle( NULL )
wcx.hIcon = LoadIcon( NULL, IDI_APPLICATION )
wcx.hCursor = LoadCursor( NULL, IDC_ARROW )
wcx.hbrBackground = GetStockObject( WHITE_BRUSH )
wcx.lpszMenuName = NULL
wcx.lpszClassName = strptr("test")
wcx.hIconSm = 0

RegisterClassEx( @wcx )

hwnd = CreateWindowEx( 0, "test", "Test", WS_OVERLAPPED or WS_SYSMENU, _
                       0, 0, 0, 0, NULL, NULL, NULL, NULL )

ShowWindow( hwnd, SW_SHOWNORMAL )
UpdateWindow( hwnd )

do while GetMessage( @msg, NULL, 0, 0 ) > 0
    if IsDialogMessage(hwnd, @msg ) = 0 then
        TranslateMessage( @msg )
        DispatchMessage( @msg )
    end if

Return to “Windows”

Who is online

Users browsing this forum: No registered users and 1 guest