Announcement

Collapse
No announcement yet.

Machine name

Collapse
X
 
  • Filter
  • Time
  • Show
Clear All
new posts

  • Machine name

    Anyone have a routine that works under
    all versions of 32-bit Windows to get
    the machine name?
    How long is an idea? Write it down.

  • #2
    API GetComputerName
    The GetComputerName function retrieves the NetBIOS name of the local computer. This name is established at system startup, when the system reads it from the registry.

    If the local computer is a node in a cluster, GetComputerName returns the name of the node.



    ------------------

    Comment


    • #3
      Code:
      'This has only been tested using Windows 98SE
      FUNCTION ComputerName$
        DIM lpBuffer AS  ASCIIZ * 128  'should be long enough
        DIM nSize AS LONG
        nSize = 128
        DIM RetCode AS LONG
        RetCode = GetComputerName(lpBuffer,nSize)
        ComputerName = lpBuffer
      END FUNCTION

      [This message has been edited by Mike Doty (edited May 31, 2000).]
      How long is an idea? Write it down.

      Comment


      • #4
        Initialize nSize.
        ie. nSize = LEN(lpBuffer)
        Otherwise it assumes the buffer length is 0.

        Regards,

        ------------------
        [email protected]
        :) IRC :)

        Comment


        • #5
          I don't think len(lpBuffer) should be used.
          It will be 0.

          Mike

          ------------------
          How long is an idea? Write it down.

          Comment


          • #6
            You'd want to use SIZEOF not LEN. LEN returns the length of the current value of the string (which would be zero until you have assigned a value to it) and SIZEOF tells you the size of the actual ASCIIZ buffer without regard to its current contents.

            But I usually do it like this:

            Code:
            FUNCTION ComputerName$
                %BufferSize = 128
                DIM lpBuffer AS  ASCIIZ * %BufferSize
                DIM nSize AS LONG
                DIM RetCode AS LONG
                RetCode = GetComputerName(lpBuffer,%BufferSize)
                ComputerName = lpBuffer
            END FUNCTION
            That avoids all runtime calculation, so it is more efficient than LEN or SIZEOF.

            -- Eric



            ------------------
            Perfect Sync: Perfect Sync Development Tools
            Email: mailto:[email protected][email protected]</A>

            "Not my circus, not my monkeys."

            Comment


            • #7
              ...Or, if you want to avoid the overhead of an ASCIIZ buffer (ASCIIZ strings can never really be "released" even if they are LOCAL) you can create a string buffer dynamically. This is the technique I use most often...

              Code:
              FUNCTION ComputerName AS STRING
                  %BufferSize = 128
                  DIM sBuffer AS LOCAL STRING
                  sBuffer = STRING$(%BufferSize,0)
                  GetComputerName sBuffer,%BufferSize
                  FUNCTION = sBuffer
              END FUNCTION
              Since you're ignoring the return value of the GetComputerName API, you may as well not use the RetVal variable.

              -- Eric


              ------------------
              Perfect Sync: Perfect Sync Development Tools
              Email: mailto:[email protected][email protected]</A>

              "Not my circus, not my monkeys."

              Comment


              • #8
                Guys, are you not forgetting something here?
                Mike Dotys suggestion is correct.
                nSize should be passed ByRef to receive the length
                of the returned computername.
                Or am I totaly out in the dark again..?
                lpnSize
                [in/out] On input, specifies the size, in TCHARs, of the buffer. On output, receives the number of TCHARs copied to the destination buffer, not including the terminating null character.
                ------------------
                Fred
                mailto:[email protected][email protected]</A>
                http://www.oxenby.se



                [This message has been edited by Fred Oxenby (edited May 31, 2000).]
                Fred
                mailto:[email protected][email protected]</A>
                http://www.oxenby.se

                Comment


                • #9
                  Fred --

                  Yes, you can get the length of the returned string that way, but it isn't really necessary because using EXTRACT$ will produce exactly the same results. And Mike Doty pointed out to me (by email) that I'd made an error in my code that would require WIN32API.INC to be changed, so here is an improved version (i.e. one that will actually work )...

                  Code:
                  FUNCTION ComputerName AS STRING
                      DIM sBuffer AS LOCAL STRING
                      %BufferSize = 17  'MAX_COMPUTERNAME_LENGTH = 16, plus 1
                      sBuffer = STRING$(%BufferSize,0)
                      GetComputerName BYVAL STRPTR(sBuffer),%BufferSize
                      FUNCTION = EXTRACT$(sBuffer,CHR$(0))
                  END FUNCTION
                  The use of BYVAL STRPTR (which passes a pointer to the location of a string) allows the use of a "normal" string where the API declaration calls for an ASCIIZ string. A very useful trick...

                  -- Eric


                  ------------------
                  Perfect Sync: Perfect Sync Development Tools
                  Email: mailto:[email protected][email protected]</A>



                  [This message has been edited by Eric Pearson (edited May 31, 2000).]
                  "Not my circus, not my monkeys."

                  Comment


                  • #10
                    Guys, are you not forgetting something here?
                    Mike Dotys suggestion is correct.
                    nSize should be passed ByRef to receive the length
                    of the returned computername.
                    Or am I totaly out in the dark again..?
                    No, you're correct. Also, you have to match or exceed MAX_COMPUTERNAME_LENGTH + 1 for the size of the buffer. According to MSDN:

                    Windows 95/98: GetComputerName fails if the input size is less than MAX_COMPUTERNAME_LENGTH + 1

                    MAX_COMPUTERNAME_LENGTH is defined as 15 in Winbase.h; I didn't see it defined in win32api.inc. Just define it as 15 and include an extra byte for the null in the buffer.

                    Considering that the NetBIOS computername is "just another" NetBIOS field, it's automatically limited to 15 characters (NetBIOS uses the 16th byte as an identifier for the name type, i.e. domain controller, host name, workgroup name, domain name, etc.)

                    So, reserving lengths longer than 16 is wasted space. (And I should know... I'm the master of wasting space!)



                    ------------------
                    Troy King
                    [email protected]
                    Troy King
                    katravax at yahoo dot com

                    Comment


                    • #11
                      Code:
                      ' Any suggestions welcome
                      ' How about this one.
                      '
                      #COMPILE EXE
                      #REGISTER NONE
                      'DECLARE FUNCTION GetComputerName LIB "KERNEL32.DLL" ALIAS "GetComputerNameA" _
                      '(lpBuffer AS ASCIIZ, nSize AS LONG) AS LONG
                      DECLARE FUNCTION ComputerName AS STRING
                      #INCLUDE "WIN32API.INC"
                      FUNCTION PBMAIN AS LONG
                        MSGBOX ComputerName
                      END FUNCTION
                         
                      FUNCTION ComputerName AS STRING
                        %MAX_COMPUTERNAME_LENGTH = 15    'not in Win32Api.inc
                        DIM RetCode AS LONG
                        DIM lpBuffer AS  ASCIIZ * %MAX_COMPUTERNAME_LENGTH + 1
                        DIM nSize AS LONG
                        nSize = %MAX_COMPUTERNAME_LENGTH + 1      'nSize returns
                        RetCode = GetComputerName(lpBuffer,nSize) 'name length
                        FUNCTION = lpBuffer
                      END FUNCTION
                      ------------------
                      How long is an idea? Write it down.

                      Comment


                      • #12
                        Looking on Mike's code, I remembered old general question about Asciiz input parameters in similar functions.
                        Resulting length doesn't include the terminating null character.
                        But which maximum size it's necessary to specify ? Including or excluding null character ?
                        I use first variant, but sometimes doubt, because in some programs I see n - 1.

                        The same about width/height of windows.
                        .nRight - n.Left (like I use) or .nRight - .nLeft + 1 ?

                        ------------------

                        Comment


                        • #13
                          Looking on Mike's code, I remembered old general question about Asciiz input parameters in similar functions.
                          Resulting length doesn't include the terminating null character.
                          In this case the addition of 1 to %MAX_COMPUTERNAME_LENGTH accounts for the extra NUL character required by NULL-terminated strings.

                          I use first variant, but sometimes doubt, because in some programs I see n - 1.
                          The same about width/height of windows.
                          .nRight - n.Left (like I use) or .nRight - .nLeft + 1 ?
                          This is a different subject altogether... it is because most of the RECT-orientated GDI functions deal with the "absolute" coordinates of a RECT structure, so to calculate the *width* of the RECT structure you have to add 1 pixel to the (Rect.nRight - Rect.nLeft) expression. Ditto for the height.
                          Then there are some exceptions to complicate this subject further. For example, the Rectangle() API draws a rectangle that is 1 pixel narrower and shorter than the RECT structure passed to it.

                          API programming is sure fun!

                          ------------------
                          Lance
                          PowerBASIC Support
                          mailto:[email protected][email protected]</A>
                          Lance
                          mailto:[email protected]

                          Comment


                          • #14
                            Lance --
                            1) NUL character.
                            With Mike's case all is clear, I ask about functions similar GetModuleFileName.
                            lpFileName - Pointer to a buffer that receives the path and file name of the specified module.
                            If I declared lpFileName As Asciiz * 256, which value I should pass as limit (nSize) - 256 or 255 ?

                            2) About + 1.
                            I tested under Windows-2000 following
                            Code:
                               #Compile Exe
                               #Dim All
                               #Register None
                               #Include "Win32Api.Inc"
                            
                               CallBack Function DlgProc
                                Select Case CbMsg
                                   Case %WM_INITDIALOG
                                      SetWindowPos CbHndl, 0, 50, 150, 300, 400, 0
                                      Dim rc As Rect
                                      GetWindowRect CbHndl, rc
                                      MsgBox "R-L W" + Str$(rc.nRight - rc.nLeft), , Str$(rc.nRight) + Str$(rc.nLeft)
                                      MsgBox "B-T W" + Str$(rc.nBottom - rc.nTop), , Str$(rc.nBottom) + Str$(rc.nTop)
                                   End Select
                                End Function
                            
                                Function PbMain()
                                   Dim hDlg As Long
                                   Dialog New 0, "", , , 0, 0 To hDlg
                                   Dialog Show Modal hDlg Call DlgProc
                                End Function
                            According results, it's not necessary to add 1
                            rc.nRight - rc.nLeft = 300 = cx for SetWindowPos

                            At the same time I saw enough programs with adding and w/o adding 1. This situation confuses me.

                            ------------------

                            Comment


                            • #15
                              If I declared lpFileName As Asciiz * 256, which value I should pass as limit (nSize) - 256 or 255 ?
                              String handling functions that use ASCIIZ strings use the terminating CHR$(0) to indicate the end (therefore the length) of the string.
                              '
                              This value should be large enough to contain MAX_COMPUTERNAME_LENGTH + 1 characters.
                              '
                              According to this excerpt from WinHelp on GetComputerName, nSize should indicate the TRUE length of the buffer it is pointing to.
                              '
                              In other cases, when the input buffer length is not required, the length of the input buffer should be - the Maximum Input Length + 1 - in order to allow for the terminating CHR$(0).
                              '
                              Clear as mud?
                              '
                              (PS) sorry about LEN instead of SIZEOF. I'm still getting used to Win programming.
                              '
                              Regards,

                              ------------------
                              [email protected]
                              :) IRC :)

                              Comment


                              • #16
                                Actually, 256 if not correct for a path+filename buffer - you should be using %MAX_PATH which is 260 bytes.

                                As your example sets the explicit width of the dialog to 300 pixels (SetWindowPos() uses a width value, not coordinates, the subtraction applied to the results of GetWindowRect() should match - it would be crazy if it did not!

                                Therefore the dialog would start in the 50th pixel column and the rightmost pixel of the dialog would be in the 349th column.

                                These sort of questions really highlight that the developers of Windows did not always remain 100% consistent in their approach and design guidelines... Just look at some of the API naming conventions used in the API and you'll get the idea!


                                ------------------
                                Lance
                                PowerBASIC Support
                                mailto:[email protected][email protected]</A>
                                Lance
                                mailto:[email protected]

                                Comment


                                • #17
                                  Or you could be really lazy and use your existing Registry code to retrieve the following:

                                  HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\ComputerName\ActiveComputerName

                                  Grab "localhost"


                                  Here's my function however, right out of the Shutdown! app I wrote (Initiates NT system shutdown etc etc, crash recovery etc)..

                                  Global g_Result as long

                                  'Netbios name = 16 chars, 15 useable max, add one for Asciiz Null

                                  Global lpMachineName As Asciiz * 17

                                  Local wUser As Asciiz * 50 'Local to Winmain function

                                  g_Result = GetUserName(wUser, SizeOf(wUser))
                                  g_Result = GetComputerName(lpMachineName, SizeOf(lpMachineName))




                                  ------------------
                                  Scott
                                  mailto:[email protected][email protected]</A>
                                  MCSE, MCP+Internet
                                  Scott Turchin
                                  MCSE, MCP+I
                                  http://www.tngbbs.com
                                  ----------------------
                                  True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                                  Comment


                                  • #18
                                    ' Thank you, Scott.
                                    '
                                    Code:
                                    #REGISTER NONE
                                    #COMPILE EXE
                                    #DIM ALL
                                    DECLARE FUNCTION NetUserName$
                                    DECLARE FUNCTION NetMachineName$
                                    #INCLUDE "WIN32API.INC"
                                    FUNCTION PBMAIN AS LONG
                                    #IF %DEF(%pb_cc32)
                                        PRINT  "USER NAME: "; NetUserName
                                        PRINT  "MACHINE NAME: "; NetMachineName
                                        PRINT  "Press any key"
                                        WAITKEY$
                                    #ELSE
                                        MSGBOX "USER NAME: " + NetUserName + $CRLF _
                                             + "MACHINE NAME: " + NetMachineName
                                        NetMachineName
                                    #ENDIF
                                    END FUNCTION
                                    
                                    FUNCTION NetUserName AS STRING
                                        DIM wUser AS ASCIIZ * 50
                                        DIM g_Result AS LONG
                                        g_Result = GetUserName(wUser, SIZEOF(wUser))
                                        FUNCTION = wUser
                                    END FUNCTION
                                    
                                    FUNCTION NetMachineName AS STRING
                                       'Netbios name = 16 chars, 15 useable max, add one for Asciiz Null
                                        DIM g_Result AS LONG
                                        DIM lpMachineName AS ASCIIZ * 17
                                        g_Result = GetComputerName(lpMachineName, SIZEOF(lpMachineName))
                                        FUNCTION = lpMachineName
                                    END FUNCTION
                                    ------------------
                                    How long is an idea? Write it down.

                                    Comment


                                    • #19
                                      Huh? If the usable space is 15 characters plus 1 for the NUL byte, why do you allocate 17 bytes? Does this need a double NUL termination?

                                      ------------------
                                      Lance
                                      PowerBASIC Support
                                      mailto:[email protected][email protected]</A>
                                      Lance
                                      mailto:[email protected]

                                      Comment


                                      • #20
                                        That's a good question Lance.
                                        I'll find out more later, my book is at work....You may be right in that you may only need to use 16, so long as Windows never strips that null off, shouldnt' be a problem..

                                        Unfortunately most of my machine names are only 6 bytes...




                                        [This message has been edited by Scott Turchin (edited June 02, 2000).]
                                        Scott Turchin
                                        MCSE, MCP+I
                                        http://www.tngbbs.com
                                        ----------------------
                                        True Karate-do is this: that in daily life, one's mind and body be trained and developed in a spirit of humility; and that in critical times, one be devoted utterly to the cause of justice. -Gichin Funakoshi

                                        Comment

                                        Working...
                                        X