Rutinas para obtener:
- Las IPs (todas de todas las LAN) de una máquina.
- Las direcciones MAC (de todas las LAN) de una máquina. (esta vez directamente desde VFP sin crear una FLL como publique anteriomente)
- Obtener un Global Unique IDentifier
CLEAR
?
? 'Enjoy it, by Alexandre Hedreville'
?
? 'MAC Address'
? '-----------'
? MACAddress()
?
? 'IP Address'
? '-----------'
? IPAddress()
?
? 'GUID'
? '-----------'
? GetGuid()
*!* Windows Sockets
#DEFINE WS_VERSION_REQD 257
#DEFINE WS_VERSION_MAJOR 1
#DEFINE WS_VERSION_MINOR 1
#DEFINE MIN_SOCKETS_REQD 1
#DEFINE SOCKET_ERROR -1
#DEFINE WSADESCRIPTION_LEN 256
#DEFINE WSASYS_STATUS_LEN 128
*!* Windows NetBIOS
#DEFINE NCBENUM 55
#DEFINE NCBASTAT 51
#DEFINE NCBNAMSZ 16
#DEFINE HEAP_ZERO_MEMORY 8
#DEFINE HEAP_GENERATE_EXCEPTIONS 4
#DEFINE NCBRESET 50
*!* Devuelve las direcciones MAC
*!* Sintaxis: MACAddress()
*!* Valor devuelto: lcRetVal
*!* lcRetVal viene expresado como una cadena con el formato: 00-04-76-A4-73-3A, 00-04-76-A4-72-13, ...
FUNCTION MACAddress
LOCAL lcNBC, lcAdapter, lnAdapter, lcSource, lnSource, lcRetVal, lnLength, lnLEnum, lcLEnum
*!* Instrucciones DECLARE DLL para manipular NetBIOS
DECLARE INTEGER GetProcessHeap IN Win32API
DECLARE INTEGER Netbios IN Netapi32.DLL STRING @lpNBC
DECLARE INTEGER HeapFree IN Win32API INTEGER hHeap, INTEGER dwFlags, STRING @lpMem
DECLARE INTEGER HeapAlloc IN Win32API INTEGER hHeap, INTEGER dwFlags, INTEGER dwBytes
DECLARE INTEGER RtlMoveMemory IN Win32API STRING @lpDestination, INTEGER nSource, INTEGER nBytes
*!* Valores
lcRetVal = ''
lcNBC = REPLICATE(CHR(0), 64)
lcLEnum = REPLICATE(CHR(0), 256)
lcAdapter = REPLICATE(CHR(0), 600)
*!* Reservar buffer memoria
lnLEnum = HeapAlloc(GetProcessHeap(), BITOR(HEAP_GENERATE_EXCEPTIONS, HEAP_ZERO_MEMORY), 256)
IF lnLEnum <> 0
*!* Valores
lcNBC = CHR(NCBENUM) + REPLICATE(CHR(0), 3) + LongToStr(lnLEnum) + ;
IntToStr(256) + SUBSTR(lcNBC, 11, 544)
*!* Enum LAN´s
IF Netbios(@lcNBC) = 0
*!* Leer buffer memoria
lnSource = lnLEnum
RtlMoveMemory(@lcLEnum, lnSource, 256)
*!* Valores
lnLength = ASC(SUBSTR(lcLEnum, 1, 1))
*!* Examinar LAN`s
FOR lnCnt = 1 TO lnLength
*!* Valores
lcAdapter = REPLICATE(CHR(0), 600)
lcNBC = CHR(NCBRESET) + REPLICATE(CHR(0), 47) + ;
SUBSTR(lcLEnum, lnCnt+1, 1) + REPLICATE(CHR(0), 15)
*!* Reset LAN
IF Netbios(@lcNBC) = 0
*!* Reservar buffer memoria
lnAdapter = HeapAlloc(GetProcessHeap(), ;
BITOR(HEAP_GENERATE_EXCEPTIONS, HEAP_ZERO_MEMORY), 600)
IF lnAdapter <> 0
*!* Valores
lcNBC = CHR(NCBASTAT) + REPLICATE(CHR(0), 3) + LongToStr(lnAdapter) + ;
IntToStr(600) + '* ' + REPLICATE(CHR(0), 22) + ;
SUBSTR(lcLEnum, lnCnt+1, 1) + REPLICATE(CHR(0), 15)
*!* Status LAN
IF Netbios(@lcNBC) = 0
*!* Leer buffer memoria
lnSource = lnAdapter
RtlMoveMemory(@lcAdapter, lnSource, 600)
*!* Componer cadena MAC con guiones y separar multiples MAC`s con comas
lcRetVal = lcRetVal + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 1, 1))), 2) + ;
'-' + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 2, 1))), 2) + ;
'-' + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 3, 1))), 2) + ;
'-' + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 4, 1))), 2) + ;
'-' + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 5, 1))), 2) + ;
'-' + RIGHT(DecToHex(ASC(SUBSTR(lcAdapter, 6, 1))), 2) + ;
IIF(lnCnt = lnLength, '', ',')
ENDIF
*!* Liberar buffer memoria
lcSource = LongToStr(lnAdapter)
HeapFree(GetProcessHeap(), 0, @lcSource)
ENDIF
ENDIF
ENDFOR
ENDIF
*!* Liberar buffer memoria
lcSource = LongToStr(lnLEnum)
HeapFree(GetProcessHeap(), 0, @lcSource)
ENDIF
*!* Retorno
RETURN lcRetVal
ENDFUNC
*!* Devuelve las direcciones IP
*!* Sintaxis: IPAddress()
*!* Valor devuelto: lcRetVal
*!* lcRetVal viene expresado como una cadena con el formato: 192.100.100.100, 192.100.100.101, ...
FUNCTION IPAddress
LOCAL lnCnt, lpWSAData, lpWSHostEnt, lpHostName, lcRetVal, lpHostIp_Addr, ;
lpHostEnt_Addr, lnHostEnt_Lenght, lnHostEnt_AddrList
*!* Instrucciones DECLARE DLL para manipular Windows Sockets
DECLARE INTEGER WSAGetLastError IN WSock32.DLL
DECLARE INTEGER WSAStartup IN WSock32.DLL INTEGER wVersionRequested , STRING @lpWSAData
DECLARE INTEGER WSACleanup IN WSock32.DLL
DECLARE INTEGER gethostname IN WSock32.DLL STRING @lpHostName, INTEGER iHostNameLenght
DECLARE INTEGER gethostbyname IN WSock32.DLL STRING lpHostName
DECLARE RtlMoveMemory IN Win32API STRING @lpDest, INTEGER nSource, INTEGER nBytes
*!* Valores
lcRetVal = ''
lpHostName = SPACE(256)
lnHostEnt_Addr = 0
lnHostEnt_Lenght = 0
lnHostEnt_AddrList = 0
lnHostIp_Addr = 0
lpTempIp_Addr = CHR(0)
lpHostIp_Addr = REPLICATE(CHR(0), 4)
lpWSHostEnt = REPLICATE(CHR(0), 4 +4 +2 +2 +4)
lpWSAData = REPLICATE(CHR(0), 2 +2 + ;
WSADESCRIPTION_LEN +1 +WSASYS_STATUS_LEN +1 +2 +2 +4)
*!* Iniciar Windows Sockets
IF WSAStartup(WS_VERSION_REQD, @lpWSAData) = 0
*!* Valores
lnVersion = StrToInt(SUBSTR(lpWSAData, 1, 2))
lnMaxSockets = StrToInt(SUBSTR(lpWSAData, 391, 2))
*!* Determinar si Windows Sockets responde
IF gethostname(@lpHostName, 256) <> SOCKET_ERROR
*!* Valores
lpHostName = ALLTRIM(lpHostName)
lnHostEnt_Addr = gethostbyname(lpHostName)
*!* Determinar si Windows Sockets no dio error
IF lnHostEnt_Addr <> 0
*!* Mover bloques de memoria
RtlMoveMemory(@lpWSHostEnt, lnHostEnt_Addr, 16)
*!* Valores
lnHostEnt_AddrList = StrToLong(SUBSTR(lpWSHostEnt, 13, 4))
lnHostEnt_Lenght = StrToInt(SUBSTR(lpWSHostEnt, 11, 2))
*!* Obtener todas las direcciones IP de la máquina
DO WHILE .T.
*!* Mover bloques de memoria
RtlMoveMemory(@lpHostIp_Addr, lnHostEnt_AddrList, 4)
*!* Valores
lnHostIp_Addr = StrToLong(lpHostIp_Addr)
*!* No hay o no quedan más direcciones validas
IF lnHostIp_Addr = 0
EXIT
ELSE
*!* Separar multiples IP`s con comas
lcRetVal = lcRetVal + IIF(EMPTY(lcRetVal), '', ',')
ENDIF
lpTempIp_Addr = REPLICATE(CHR(0), lnHostEnt_Lenght)
*!* Mover bloques de memoria
RtlMoveMemory(@lpTempIp_Addr, lnHostIp_Addr, lnHostEnt_Lenght)
*!* Componer cadena IP con puntos
FOR lnCnt = 1 TO lnHostEnt_Lenght
lcRetVal = lcRetVal + TRANSFORM(ASC(SUBSTR(lpTempIp_Addr, lnCnt, 1))) + ;
IIF(lnCnt = lnHostEnt_Lenght, '', '.')
ENDFOR
*!* Continuar con la siguiente direccion
lnHostEnt_AddrList = lnHostEnt_AddrList + 4
ENDDO
ENDIF
ENDIF
ENDIF
*!* Parar Windows Sockets
IF WSACleanup() <> 0
lcRetVal = ''
ENDIF
*!* Retorno
RETURN lcRetVal
ENDFUNC
*!* Obtiene un GUID en formato {nnnnnnnn-nnnn-nnnn-nnnn-nnnnnnnnnnnn}
*!* Sintaxis: GetGuid()
*!* Valor devuelto: lcGuid
FUNCTION GetGuid
LOCAL lnCnt, lcGuid, lcData1, lcData2, lcData3, lcData4, lcData5
*!* Instrucciones DECLARE DLL para manipular obtener un GUID
DECLARE INTEGER CoCreateGuid IN Ole32.DLL STRING @lpGuid
*!* Valores
lnCnt = 0
lcGuid = ''
lcData1 = ''
lcData2 = ''
lcData3 = ''
lcData4 = ''
lcData5 = ''
lpGuid = REPLICATE(CHR(0), 17)
*!* Obtener el GUID
IF CoCreateGuid(@lpGuid) = 0
*!* Valores
lcData1 = RIGHT(TRANSFORM(StrToLong(LEFT(lpGuid, 4)), '@0'), 8) && Los 8 primeros digitos
lcData2 = RIGHT(TRANSFORM(StrToLong(SUBSTR(lpGuid, 5, 2)), '@0'), 4) && Los 4 segundos digitos
lcData3 = RIGHT(TRANSFORM(StrToLong(SUBSTR(lpGuid, 7, 2)), '@0'), 4) && Los 4 terceros digitos
lcData4 = RIGHT(TRANSFORM(StrToLong(SUBSTR(lpGuid, 9, 1)), '@0'), 2) + ;
RIGHT(TRANSFORM(StrToLong(SUBSTR(lpGuid, 10, 1)), '@0'), 2) && Los 4 cuartos digitos
lcData5 = ''
*!* Los 12 digitos finales
FOR lnCnt = 1 TO 6
lcData5 = lcData5 + RIGHT(TRANSFORM(StrToLong(SUBSTR(lpGuid, 10 + lnCnt, 1))), 2)
ENDFOR
*!* Verifica la longitud de los 12 digitos finales. Si son menores de 12 es que el resto son 0
IF LEN(lcData5) < 12
lcData5 = lcData5 + REPLICATE('0', 12 - LEN(lcData5))
ENDIF
*!* Valores
lcGuid = '{' + lcData1 + '-' + lcData2 + '-' + lcData3 + '-' + lcData4 + '-' + lcData5 + '}'
ENDIF
*!* Retorno
RETURN lcGuid
ENDFUNC
********************************************************************************
** Libreria de funciones de conversion de tipo **
********************************************************************************
*!* Convierte un long integer a un 4-byte character string
*!* Sintaxis: LongToStr(tnLongVal)
*!* Valor devuelto: lcRetStr
*!* Argumentos: tnLongVal
*!* lnLongVal especifica el long integer a convertir
FUNCTION LongToStr
LPARAMETERS tnLongVal
LOCAL lnCnt, lcRetStr, lnLongVal
*!* Valores
lcRetStr = ''
lnLongVal = IIF(EMPTY(tnLongVal), 0, tnLongVal)
*!* Convertir
FOR lnCnt = 24 TO 0 STEP -8
lcRetStr = CHR(INT(lnLongVal/(2^lnCnt))) + lcRetStr
lnLongVal = MOD(lnLongVal, (2^lnCnt))
NEXT
*!* Retorno
RETURN lcRetStr
ENDFUNC
*!* Convierte un 4-byte character string a un long integer
*!* Sintaxis: StrToLong(tcLongStr)
*!* Valor devuelto: lnRetval
*!* Argumentos: tcLongStr
*!* tcLongStr especifica el 4-byte character string a convertir
FUNCTION StrToLong
LPARAMETERS tcLongStr
LOCAL lnCnt, lnRetVal, lcLongStr
*!* Valores
lnRetVal = 0
lcLongStr = IIF(EMPTY(tcLongStr), '', tcLongStr)
*!* Convertir
FOR lnCnt = 0 TO 24 STEP 8
lnRetVal = lnRetVal + (ASC(lcLongStr) * (2^lnCnt))
lcLongStr = RIGHT(lcLongStr, LEN(lcLongStr) - 1)
NEXT
*!* Retorno
RETURN lnRetVal
ENDFUNC
*!* Convierte un integer a un 2-byte character string
*!* Sintaxis: IntToStr(tnIntVal)
*!* Valor devuelto: lcRetStr
*!* Argumentos: tnIntVal
*!* lnIntVal especifica el integer a convertir
FUNCTION IntToStr
LPARAMETERS tnIntVal
LOCAL lnCnt, lcRetStr, lnIntVal
*!* Valores
lcRetStr = ''
lnIntVal = IIF(EMPTY(tnIntVal), 0, tnIntVal)
*!* Convertir
FOR lnCnt = 8 TO 0 STEP -8
lcRetStr = CHR(INT(lnIntVal/(2^lnCnt))) + lcRetStr
lnIntVal = MOD(lnIntVal, (2^lnCnt))
NEXT
*!* Retorno
RETURN lcRetStr
ENDFUNC
*!* Convierte un 2-byte character string a un integer
*!* Sintaxis: StrToInt(tcIntStr)
*!* Valor devuelto: lnRetval
*!* Argumentos: tcIntStr
*!* tcIntStr especifica el 2-byte character string a convertir
FUNCTION StrToInt
LPARAMETERS tcIntStr
LOCAL lnCnt, lnRetVal, lcIntStr
*!* Valores
lnRetVal = 0
lcIntStr = IIF(EMPTY(tcIntStr), '', tcIntStr)
*!* Convertir
FOR lnCnt = 0 TO 8 STEP 8
lnRetVal = lnRetVal + (ASC(lcIntStr) * (2^lnCnt))
lcIntStr = RIGHT(lcIntStr, LEN(lcIntStr) - 1)
NEXT
*!* Retorno
RETURN lnRetVal
ENDFUNC
*!* Convierte un numero decimal a una hex character string
*!* Sintaxis: DecToHex(tnDecNumber)
*!* Valor devuelto: lcHexNumber
*!* Argumentos: tnDecNumber
*!* tnDecNumber especifica el numero decimal a convertir
FUNCTION DecToHex
LPARAMETERS tnDecNumber
LOCAL lnLength, lnTempHex, lcHexNumber, lnDecNumber
*!* Valores
lcHexNumber = ''
lnDecNumber = IIF(EMPTY(tnDecNumber), 0, tnDecNumber)
*!* Convertir
DO CASE
CASE lnDecNumber = 0
lcHexNumber = '0x00000000'
CASE lnDecNumber > 0
lcHexNumber = TRANSFORM(lnDecNumber, '@0')
OTHERWISE
lcHexNumber = TRANSFORM(ABS(lnDecNumber), '@0')
lnLength = IIF(SUBSTR(lcHexNumber, 3, 1) = ;
'0', LEN(SUBSTR(lcHexNumber, NotAt('0', lcHexNumber, 2))), ;
LEN(TRANSFORM(ABS(lnDecNumber), '@0')) - 2)
lnTempHex = 0xFFFFFFFF
lcHexNumber = TRANSFORM(lnTempHex - ABS(lnDecNumber) + 1, '@0')
ENDCASE
*!* Retorno
RETURN lcHexNumber
ENDFUNC
Alexandre Hedreville
Muy buen aporte... probaré a ver si funcionan... saludos
ResponderBorrarExcelente aporte!!! Funciona perfecto... Gracias!!
ResponderBorrarSi funciona, es el único que entendió lo que se quiere cuando se necesita la IP de un equipo en la red.
ResponderBorrarSi funciona pero da un error de compilación dice que falta o desconocido NotAt, se encuentra en la función DecToHex copio la instrucción, yq que desconozco si se trata de una función que falta
ResponderBorrar"lnLength = IIF(SUBSTR(lcHexNumber, 3, 1) = ;
'0', LEN(SUBSTR(lcHexNumber, NotAt('0', lcHexNumber, 2))), ;
LEN(TRANSFORM(ABS(lnDecNumber), '@0')) - 2)"
Espero información gracias
Un error de tipéo.
BorrarEs cuestión de separar la instrucción.
Not At(...
que buen aporte... muchas gracias Alejandro.
ResponderBorrar