21 de marzo de 2005

Números consecutivos para nuestras tablas

Muchas veces necesitamos crear números consecutivos para nuestras tablas, como ser Números de Facturas, Albaranes, Remitos, Clientes, Ordenes, etc. Una forma de hacerlo es tener una tabla con los últimos números generados, y una función que genere el siguiente número consecutivo para cada una de nuestras necesidades.

La tabla de números consecutivos (Ids) puede ser una tabla libre o una tabla incluida en nuestra base de datos, y solo contendrá dos campos, uno con el nombre de la tabla (cTabla C(30)) y el otro con el último número utilizado (cId I) y un índice por el campo cTabla.

La creación de la tabla y el índice lo realizamos por única vez con el siguiente código:
CREATE TABLE Ids ;
  (cTabla C(30) NOT NULL, ;
  nId I NOT NULL)
INDEX ON UPPER(cTabla) TAG cTabla
Por cada tabla que necesitemos llevar un número consecutivo, insertamos un registro con el nombre de la tabla e inicializamos el contador en 0 (cero):
INSERT INTO Ids (cTabla, nId) VALUES ("Facturas", 0)
INSERT INTO Ids (cTabla, nId) VALUES ("Albaranes", 0)
INSERT INTO Ids (cTabla, nId) VALUES ("Clientes", 0)
INSERT INTO Ids (cTabla, nId) VALUES ("Ciudades", 0)
La función que nos generará el nuevo número consecutivo (NuevoId()), puede estar ubicada en un archivo de procedimientos de nuestra aplicación, o puede ser un procedimiento almacenado de nuestra base de datos. El código de la función es el siguiente:
FUNCTION NuevoID(tcAlias)
  LOCAL lcAlias, lnId, lnAreaAnt, lcReprAnt
  lnId = 0
  lnAreaAnt = SELECT()
  lcReprAnt = SET('REPROCESS')
  SET REPROCESS TO AUTOMATIC
  lcAlias = UPPER(ALLTRIM(tcAlias))
  IF NOT USED("Ids")
    USE Ids IN 0
  ENDIF
  SELECT Ids
  IF SEEK(lcAlias, "Ids", "cTabla")
    IF RLOCK()
      REPLACE nId WITH nId + 1 IN Ids
      lnID = Ids.nId
      UNLOCK
    ENDIF
  ENDIF
  SELECT (lnAreaAnt)
  SET REPROCESS TO lcReprAnt
  RETURN lnID
ENDFUNC
Cada vez que necesitemos un nuevo número consecutivo de una tabla, invocamos la función pasando el nombre de la tabla o su alias como parámetro:
lnNuevoId = NuevoId("Facturas")
El valor retornado por la función NuevoId() es del tipo Entero. Si por ejemplo el código de cliente de nuestra tabla Clientes es del tipo caracter de 4 y justificado con 0s (ceros) a la izquierda, transformamos el número retornado de la siguiente manera:
lcCodCli = TRANSFORM(NuevoId("Clientes"), "@L 9999")
Espero que este breve código sea de utilidad para Uds.

Hasta la próxima.

Luis María Guayán

14 de marzo de 2005

Leyendo Servidores SQL Server con el API ODBC

Existen diversas formas de saber cuales son los Servidores SQL Server disponibles, una de ellas, es la que comento a continuación; utilizando el API del ODBC.

*
*********************************************************************************************
* Ejemplo básico, de como leer servidores disponibles de SQL Server por medio del ODBC API. *
*********************************************************************************************
*

* REFERENCIA GENERAL: MSDN ODBC Programmer's Reference
*
= ServidoresSQLDisponibles( )
*

PROCEDURE ServidoresSQLDisponibles( )
  *
  * Constantes.
  *
  #DEFINE V_SQL_HANDLE_ENV      1
  #DEFINE V_SQL_HANDLE_DBC     2
  #DEFINE V_SQL_ODBC_VERSION  200  #DEFINE V_SQL_ODBC3              3
  #DEFINE V_SQL_DATO                99  #DEFINE V_TRAMA_TAMANO        2048  #DEFINE V_SQL_DRIVER             "DRIVER=SQL SERVER"
  *
  **********************
  * Declaraciones API. *
  **********************
  *
  * REFERENCIA API:
http://msdn.microsoft.com/library/en-us/odbc/htm/odbcSQLBrowseConnect.asp
  *
  DECLARE SHORT SQLBrowseConnect IN ODBC32 ;
  INTEGER ConnectionHandle, ;
  STRING InConnectionString, ;
  INTEGER StringLength1, ;
  STRING @ OutConnectionString, ;
  INTEGER BufferLength, ;
  INTEGER @ StringLength2Ptr
  *
  * REFERENCIA API:
http://msdn.microsoft.com/library/en-us/odbc/htm/odbcsqlallochandle.asp
  *
  DECLARE SHORT SQLAllocHandle IN ODBC32 ;
  INTEGER HandleType, ;
  INTEGER InputHandle, ;
  INTEGER @ OutputHandlePtr
  *
  * REFERENCIA API:
http://msdn.microsoft.com/library/en-us/odbc/htm/odbcsqlfreehandle.asp
  *
  DECLARE SHORT SQLFreeHandle IN ODBC32 ;
  INTEGER HandleType, ;
  INTEGER Handle
  *
  * REFERENCIA API:
http://msdn.microsoft.com/library/en-us/odbc/htm/odbcsqlsetenvattr.asp
  *
  DECLARE SHORT SQLSetEnvAttr IN ODBC32 ;
  INTEGER EnvironmentHandle, ;
  INTEGER Attribute, ;
  INTEGER ValuePtr, ;
  INTEGER StringLength
  *
  **********************
  * CÓDIGO DE EJEMPLO. *
  **********************
  *
  LOCAL lnIndi, lnIOHandle, lnCX, lnLongitudSalida
  LOCAL lcEntrada, lcSalida
  LOCAL ARRAY laServidores[1]
  *
  STORE 0                                         TO lnIOHandle, lnCX, lnLongitudSalida
  STORE V_SQL_DRIVER                    TO lcEntrada
  STORE SPACE( V_TRAMA_TAMANO )TO lcSalida
  *
  TRY
    *
    IF SQLAllocHandle( V_SQL_HANDLE_ENV, lnIOHandle, @lnIOHandle ) == 0
      *
      IF ( SQLSetEnvAttr(lnIOHandle, V_SQL_ODBC_VERSION, V_SQL_ODBC3, 0 ) ) == 0
        *
        IF SQLAllocHandle( V_SQL_HANDLE_DBC, lnIOHandle, @lnCX ) == 0
          *
          IF ( SQLBrowseConnect( lnCX, @lcEntrada, LEN( lcEntrada ), @lcSalida, V_TRAMA_TAMANO, @lnLongitudSalida ) ) == V_SQL_DATO
            *
           FOR lnIndi = 1 TO ALINES( laServidores, STREXTRACT(lcSalida, '{', '}'), .T., ',' )
              *
              ?laServidores[ lnIndi ]
              *
            ENDFOR
            *
          ENDIF
          *
        ENDIF
        *
      ENDIF
      *
    ENDIF
   *
  CATCH TO loException
  FINALLY
    *
    IF lnCX <> 0
      *
      SQLFreeHandle( V_SQL_HANDLE_DBC, lnCX )
      *
    ENDIF
    *
    IF lnIOHandle <> 0
      *
      SQLFreeHandle( V_SQL_HANDLE_ENV, lnCX )
      *
    ENDIF
    *
  ENDTRY
  *
ENDPROC
*
REFERENCIA GENERAL: MSDN ODBC Programmer's Reference
 

Antonio Muñoz de Burgos y Caravaca
www.emans.com  (Web realizada en vFoxPro)
eMans AC (Administrador Corporativo para SQL Server 2000&2005)
Sevilla - España
Manifestando el apoyo a la comunidad de desarrolladores de MS Visual FoxPro.

3 de marzo de 2005

Dos formas de agregar un objeto a otro

Hay dos formas de agregar un objeto a otro: usando AddObject / NewObject o como propiedad...

Los métodos AddObject y NewObject de los objetos son para agregar nuevos objetos (y sólo objetos) a objetos existentes.

En cambio las asignaciones con "=" o con AddProperty se realizan como asignaciones de propiedades, aunque las mismas puedan contener objetos.

No sé si hay un motivo teórico para esta distinción entre agregar como objeto o como propiedad, pero hay varios motivos prácticos, cada uno con sus pros y contras:

AGREGAR UN OBJETO A OTRO OBJETO

usando AddObject o NewObject
  • Ventajas:
  • - Permite que el objeto interior (contenido) pueda referirse al objeto exterior (padre) usando la sintaxis THIS.PARENT - Permite a varios objetos setear u obtener datos entre sí en cualquier dirección (hijo a padre, padre a hijo, hijo a hermano, etc.) - Los objetos agregados forma parte de una colección dentro del padre, que puede recorrerse fácilmente por programa.
  • Desventajas:
  • - Hay objetos que pueden dar problemas con esta forma de juntar objetos, por ejemplo los basados en SESSION, ya que el objeto agregado (hijo) estará en la sesión del objeto padre. - Aumenta el acoplamiento, el padre puede acceder a la funcionalidad del hijo y el hijo puede acceder a la funcionalidad del padre
AGREGAR UN OBJETO A OTRO OBJETO COMO PROPIEDAD

usando AddProperty, "=" o STORE
  • Ventajas:
  • - Todos los objetos son compatibles con esta forma de agregación, incluyendo los basados en SESSION, ya que cada uno mantiene su sesión predeterminada - Disminuye el acoplamiento porque el objeto padre puede acceder al objeto hijo, pero el objeto hijo no puede acceder al objeto padre. Esto permite a que el objeto hijo sea funcionalmente independiente del objeto padre.
  • Desventajas:
  • - No permite que el objeto interior (contenido) pueda referirse al objeto exterior (padre) usando la sintaxis THIS.PARENT - Los objetos agregados no forman parte de ninguna colección dentro del padre, por lo que para recorrerlos hay que buscarlos primero.
Observaciones: - No hay diferencias de performance entre ambas formas de unir objetos - Elegir entre una forma u otra puede deberse a varios motivos, pero dos motivos mutuamente excluyentes son: Usar clases SESSION y querer la referencia THIS.PARENT

Fernando D. Bozzo

31 de enero de 2005

Conociendo un poco más WMI

La idea de este artículo, es para realizar un acercamiento más de WMI (Windows Management Instrumentation) y Visual FoxPro.



Conociendo un poco más WMI
(Windows Management Instrumentation)

Clases WMI-CIMv2-WIN32 y MS Visual FoxPro.

Manifestando el apoyo a la comunidad de desarrolladores de MS Visual FoxPro.
Antonio Muñoz de Burgos y Caravaca.
www.emans.com


Breve introducción

La idea de este artículo, es para realizar un acercamiento más de WMI y VFP, tener la información correspondiente, y poder aprovechar, lo que nos puede proporcionarWMI en la explotación del entorno administrativo, en algún caso o momento determinado.

WMI, no es más, que un componente del Sistema operativo MS Windows, que esta basado en la iniciativa WBEM (Web-Based Enterprise Management)

WMI, nos proporciona acceso a la información de los objetos del entorno administrativo, donde el abanico es realmente extenso, en este artículo me centraré en la sección de ClasesWMI y dentro de estas clases en la que hace referencia a las clases Win32.

El sub-apartado de clases Win32, nos representa el esquema de clases, que se obtiene a partir del espacio nombres (namespace) [rootcimv2]

La clase Win32 nos proporciona las siguientes categorías de clases:

Computer system hardware:
clase que representa los objetos relacionados con el hardware.
Operating system:
clase que representa los objetos relativos al sistema.
Installed applicaciones:
clase que representa los objetos relativos al software
WMI service management:
clases usadas por el administrador WMI.
Performance counters:
clase que representa la estructuración y actuación de datos.

Si miramos la infraestructura de WMI, encontramos WQL (WMI Query Language), donde WQL no es más que un subset de SQL (ANSI standard Structured Query Language (SQL) con sus especificaciones de extensión.

Debemos de tener en cuenta que WQL, es el lenguaje de consulta de WMI, pero de solo lectura, por lo tanto no es posible realizar inserciones, modificaciones, o borrados en el repositorio de datos WMI o en el proveedor que estemos actuando. Por medio de WQL solamente podremos recibir (explotar) la información.

Nota:
cuando menciono que es de "solo lectura" hago referencia exclusiva al sistema de consulta WQL, diferencia clara que tenemos con SQL,no confundir con la exposición e interacción con el modelo de objetos, puede ser de lectura y escritura.

Retomando el origen de este artículo, para la explotación de la información que nos proporciona WMI dentro la clase Win32, debemos de partir del siguiente (namespace) [rootCIMv2]

Para información detallada de CIM (Common Information Model)
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/common_information_model.asp

A continuación expongo la lista de las clases WMI que parte del (namespace - espacio de nombre) CIMv2.

En esta lista de clase WIN32, se acompaña cada una, con un ejemplo en VFP para ver su funcionamiento, consulta WQL y propiedades.
 

Entendiendo; como están expuestos los ejemplos de cada una las clase

 

Los ejemplos, están expuestos realizando la consulta WQL sin cláusula WHERE, con el fin de explotar todos los datos posibles, como es lógico; eso es para la representación del ejemplo, pero la aplicación de una cláusula WHERE es simple, ya que cada ejemplo va acompañado de sus correspondientes propiedades.
 

Detallemos un poco el caso:

La primera clase WMI dentro de nuestra lista (ordenada alfabéticamente) es: CMI_DataFile

Esta clase, nos proporciona, como su propio nombre nos indica, todos los ficheros del ordenador (PC) al que realizamos la solicitud.

En el ejemplo, que expongo sobre esta clase, como he comentado, no existe cláusula WHERE, esta es la sintaxis:


lcWQL = "SELECT * FROM CIM_DataFile"
Por lo tanto si ejecutamos el ejemplo, nos retornará toda la información que se encuentre en el PC.


Como aplicar una cláusula WHERE a cualquiera de los ejemplos que expongo, bien, la podemos aplicar por la propiedad desea, las propiedades están expuestas en todos los ejemplos.

Como podemos ver en el ejemplo de la clase:
CIM_DataFile, una de las propiedades es [Drive], si aplicamos esta propiedad como filtro para la consulta, la sintaxis sería la siguiente:


lcWQL = "SELECT * FROM CIM_DataFile WHERE Drive = 'E:' "

 


Otro ejemplo: utilicemos la clase : Win32_DiskDrive

Esta clase, nos proporciona, información de los discos duros (HHD) del ordenador (PC) al que realizamos la solicitud.

En el ejemplo que expongo, al igual que el caso comentado anteriormente, se retornará la información de todos los discos, con todas las propiedades correspondientes, que son las siguientes:

.Availability
.BytesPerSector
.Capabilities
.CapabilityDescriptions
.Caption
.CompressionMethod
.ConfigManagerErrorCode
.ConfigManagerUserConfig
.CreationClassName
.DefaultBlockSize
.Description
.DeviceID
.ErrorCleared
.ErrorDescription
.ErrorMethodology
.Index
.InstallDate
.InterfaceType
.LastErrorCode
.Manufacturer
.MaxBlockSize
.MaxMediaSize
.MediaLoaded
.MediaType
.MinBlockSize
.Model
.Name
.NeedsCleaning
.NumberOfMediaSupported
.Partitions
.PNPDeviceID
.PowerManagementCapabilities
.PowerManagementSupported
.SCSIBus
.SCSILogicalUnit
.SCSIPort
.SCSITargetId
.SectorsPerTrack
.Signature
.Size
.Status
.StatusInfo
.SystemCreationClassName
.SystemName
.TotalCylinders
.TotalHeads
.TotalSectors
.TotalTracks
.TracksPerCylinder

Como aplicar una cláusula WHERE en este caso, pues de igual forma que en el anterior, supongamos que deseamos filtrar por los disco que tenga el interface del tipo [IDE], para ello haremos uso de la propiedad : [InterfaceType]

lcWQL = "SELECT * FROM CIM_DataFile WHERE InterfaceType = 'IDE' "


Otro ejemplo: utilicemos la clase : Win32_NetworkConnection

Esta clase, nos proporciona, información sobre las conexiones de Red del ordenador (PC) al que realizamos la solicitud.

En el ejemplo que expongo, al igual que el los casos anteriores, se retornará la información de todos las conexiones.

Podemos aplicar una cláusula WHERE por alguna de sus propiedades, según se indican en el ejemplo, si filtramos por [localName] de la conexión, se corresponde con la [unidad], si lo hacemos por [Name] es el nombre del recurso compartido

lcWQL = "SELECT * FROM CIM_DataFile WHERE LocalName = 'Z:' "
lcWQL = "SELECT * FROM CIM_DataFile WHERE Name = '
ServidorRecurso_Compartido' "
Aquí aplicamos la nomenclatura UNC.

 


CONSIDERACIÓN IMPORTANTE:

La propiedades como es lógico, retornan valores de diferentes tipos, ya pueden ser de tipo "string", "fecha", "numérico", etc, pero si es importante tener en cuenta, que hay propiedades que retornan [ARRAY] u objetos, por supuesto eso no representa problema alguno, ya que lo podemos tratar según el caso de forma fácil con VFP.

Concretamente, en el ejemplo que he expuesto de la Clase: Win32_DiskDrive, tenemos una propiedad que nos retorna un [ARRAY], que es la propiedad ".Capabilities"

Tal como esta puesta en el ejemplo, dará un error de incompatibilidad de tipos, debería tener algo como esto:

FOR lnIndi = 1 TO ALEN( loItem.Capabilities )
    ?loItem.Capabilities( lnIndi )
ENDFOR

El realizar esta mención;
es porque en los ejemplos no hago tratamiento del tipo,
simplemente por comodidad efectuó la visualización de valor si es posible.

Para ello se debe anular la línea ON ERROR


Como os podéis dar cuenta, aquí lo importante y fundamental es:

(1) Saber, que existe una clase WMI que realiza una determinada acción.
(2) Saber, como realizar la consulta a la clase WMI con WQL.
(3) Saber las propiedades de la clase WMI.

A partir de ahí, el cambiar el código, para explotar una información concreta, ya no es un problema.


En esta publicación sobre WMI, las Clases WIN32 y VFP,
creo
se cumplen los tres puntos que he mencionado,
para poder aprovechar al máximo la información.
 


Para más detalles sobre los comandos y/o palabras (SQL for WMI)
 
SQL for WMI
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/wmisdk/wmi/sql_for_wmi.asp

 

NOTA

Cada clase referenciada aquí, tiene su ejemplo correspondiente.

Todas se encuentran en PortalFox, en el sistema
de programación de tareas.
Es decir, que se irán publicando día tras día dentro de la programación,
establecida por los SysOps.

Lo ejemplos también se encontrarán mi Web: www.emans.com

Exactamente en esta publicación se hace referencia
a [437] Clases WMI y sus [437] ejemplos.
Basado en el espacio de nombre (namespace) de CIMv2.

Donde, entran todas las categorías citadas:
Computer system hardware.
Operating system.
Installed applicaciones.
Performance counters.

 


 

Lista de Clases WMI a partir de CIMv2 (ordenadas alfabéticamente)

 

 
CMI_DataFile
CMI_DirectoryContainsFile
CMI_ProcessExecutable
CIM_VideoControllerResolution
Msft_Providers
Msft_WmiProvider_Counters
NetDiagnostics
Win32_1394Controller
Win32_1394ControllerDevice
Win32_AccountSID
Win32_ActionCheck
Win32_ActiveRoute
Win32_AllocatedResource
Win32_ApplicationCommandLine
Win32_ApplicationService
Win32_AssociatedBattery
Win32_AssociatedProcessorMemory
Win32_AutochkSetting
Win32_BaseBoard
Win32_Battery
Win32_Binary
Win32_BindImageAction
Win32_BIOS
Win32_BootConfiguration
Win32_Bus Win32_CacheMemory
Win32_CDROMDrive
Win32_CheckCheck
Win32_CIMLogicalDeviceCIMDataFile
Win32_ClassicCOMApplicationClasses
Win32_ClassicCOMClass
Win32_ClassicCOMClassSetting
Win32_ClassicCOMClassSettings
Win32_ClassInforAction
Win32_ClientApplicationSetting
Win32_CodecFile
Win32_COMApplicationSettings
Win32_COMClassAutoEmulator
Win32_ComClassEmulator
Win32_CommandLineAccess
Win32_ComponentCategory
Win32_ComputerSystem
Win32_ComputerSystemProcessor
Win32_ComputerSystemProduct
Win32_ComputerSystemWindowsProductActivationSetting
Win32_Condition
Win32_ConnectionShare
Win32_ControllerHastHub
Win32_CreateFolderAction
Win32_CurrentProbe
Win32_DCOMApplication
Win32_DCOMApplicationAccessAllowedSetting
Win32_DCOMApplicationLaunchAllowedSetting
Win32_DCOMApplicationSetting
Win32_DependentService
Win32_Desktop
Win32_DesktopMonitor
Win32_DeviceBus
Win32_DeviceMemoryAddress
Win32_Directory
Win32_DirectorySpecification
Win32_DiskDrive
Win32_DiskDrivePhysicalMedia
Win32_DiskDriveToDiskPartition
Win32_DiskPartition
Win32_DiskQuota
Win32_DisplayConfiguration
Win32_DisplayControllerConfiguration
Win32_DMAChanner
Win32_DriverForDevice
Win32_DriverVXD
Win32_DuplicateFileAction
Win32_Environment
Win32_EnvironmentSpecification
Win32_ExtensionInfoAction
Win32_Fan
Win32_FileSpecification
Win32_FloppyController
Win32_FloppyDrive
Win32_FontInfoAction
Win32_Group
Win32_GroupDomain
Win32_GroupUser
Win32_HeatPipe
Win32_IDEController
Win32_IDEControllerDevice
Win32_ImplementedCategory
Win32_InfraredDevice
Win32_IniFileSpecification
Win32_InstalledSoftwareElement
Win32_IP4PersistedRouteTable
Win32_IP4RouteTable
Win32_IRQResource
Win32_Keyboard
Win32_LaunchCondition
Win32_LoadOrderGroup
Win32_LoadOrderGroupServiceDependencies
Win32_LoadOrderGroupServiceMembers
Win32_LocalTime
Win32_LoggedOnUser
Win32_LogicalDisk
Win32_LogicalDiskRootDirectory
Win32_LogicalDiskToPartition
Win32_LogicalFileAccess
Win32_LogicalFileAuditing
Win32_LogicalFileGroup
Win32_LogicalFileOwner
Win32_LogicalFileSecuritySetting
Win32_LogicalMemoryConfiguration
Win32_LogicalProgramGroup
Win32_LogicalProgramGroupDirectory
Win32_LogicalProgramGroupItem
Win32_LogicalProgramGroupItemDataFile
Win32_LogicalShareAccess
Win32_LogicalShareAuditing
Win32_LogicalShareSecuritySetting
Win32_LogonSession
Win32_LogonSessionMappedDisk
Win32_MappedLogicalDisk
Win32_MemoryArray
Win32_MemoryArrayLocation
Win32_MemoryDevice
Win32_MemoryDeviceArray
Win32_MemoryDeviceLocation
Win32_MIMEInfoAction
Win32_MotherboardDevice
Win32_MoveFileAction
Win32_NamedJobObject
Win32_NamedJobObjectActgInfo
Win32_NamedJobObjectLimit
Win32_NamedJobObjectLimitSetting
Win32_NamedJobObjectProcess
Win32_NamedJobObjectSecLimit
Win32_NamedJobObjectSecLimitSetting
Win32_NamedJobObjectStatistics
Win32_NetworkAdapter
Win32_NetworkAdapterConfiguration
Win32_NetworkAdapterSetting
Win32_NetworkClient
Win32_NetworkConnection
Win32_NetworkLoginProfile
Win32_NetworkProtocol
Win32_NTDomain
Win32_NTEventlogFile
Win32_NTLogEvent
Win32_NTLogEventComputer
Win32_NTLogEvnetLog
Win32_NTLogEventUser
Win32_ODBCAttribute
Win32_ODBCDataSourceAttribute
Win32_ODBCDataSourceSpecification
Win32_ODBCDriverAttribute
Win32_ODBCDriverSoftwareElement
Win32_ODBCDriverSpecification
Win32_ODBCSourceAttribute
Win32_ODBCTranslatorSpecification
Win32_OnBoardDevice
Win32_OperatingSystem
Win32_OperatingSystemAutochkSetting
Win32_OperatingSystemQFE
Win32_OSRecoveryConfiguración
Win32_PageFile
Win32_PageFileElementSetting
Win32_PageFileSetting
Win32_PageFileUsage
Win32_ParallelPort
Win32_Patch
Win32_PatchFile
Win32_PatchPackage
Win32_PCMCIAControler
Win32_PerfFormattedData_ASP_ActiveServerPages
Win32_PerfFormattedData_ASPNET_114322_ASPNETAppsv114322
Win32_PerfFormattedData_ASPNET_114322_ASPNETv114322
Win32_PerfFormattedData_ASPNET_2040607_ASPNETAppsv2040607
Win32_PerfFormattedData_ASPNET_2040607_ASPNETv2040607
Win32_PerfFormattedData_ASPNET_ASPNET
Win32_PerfFormattedData_ASPNET_ASPNETApplications
Win32_PerfFormattedData_aspnet_state_ASPNETStateService
Win32_PerfFormattedData_ContentFilter_IndexingServiceFilter
Win32_PerfFormattedData_ContentIndex_IndexingService
Win32_PerfFormattedData_DTSPipeline_SQLServerDTSPipeline
Win32_PerfFormattedData_Fax_FaxServices
Win32_PerfFormattedData_InetInfo_InternetInformationServicesGlobal
Win32_PerfFormattedData_ISAPISearch_HttpIndexingService
Win32_PerfFormattedData_MSDTC_DistributedTransactionCoordinator
Win32_PerfFormattedData_NETCLRData_NETCLRData
Win32_PerfFormattedData_NETCLRNetworking_NETCLRNetworking
Win32_PerfFormattedData_NETDataProviderforOracle_NETCLRData
Win32_PerfFormattedData_NETDataProviderforSqlServer_NETDataProviderforSqlServer
Win32_PerfFormattedData_NETFramework_NETCLRExceptions
Win32_PerfFormattedData_NETFramework_NETCLRInterop
Win32_PerfFormattedData_NETFramework_NETCLRJit
Win32_PerfFormattedData_NETFramework_NETCLRLoading
Win32_PerfFormattedData_NETFramework_NETCLRLocksAndThreads
Win32_PerfFormattedData_NETFramework_NETCLRMemory
Win32_PerfFormattedData_NETFramework_NETCLRRemoting
Win32_PerfFormattedData_NETFramework_NETCLRSecurity
Win32_PerfFormattedData_NTFSDRV_ControladordealmacenamientoNTFSdeSMTP
Win32_PerfFormattedData_Outlook_Outlook
Win32_PerfFormattedData_PerfDisk_LogicalDisk
Win32_PerfFormattedData_PerfDisk_PhysicalDisk
Win32_PerfFormattedData_PerfNet_Browser
Win32_PerfFormattedData_PerfNet_Redirector
Win32_PerfFormattedData_PerfNet_Server
Win32_PerfFormattedData_PerfNet_ServerWorkQueues
Win32_PerfFormattedData_PerfOS_Cache
Win32_PerfFormattedData_PerfOS_Memory
Win32_PerfFormattedData_PerfOS_Objects
Win32_PerfFormattedData_PerfOS_PagingFile
Win32_PerfFormattedData_PerfOS_Processor
Win32_PerfFormattedData_PerfOS_System
Win32_PerfFormattedData_PerfProc_FullImage_Costly
Win32_PerfFormattedData_PerfProc_Image_Costly
Win32_PerfFormattedData_PerfProc_JobObject
Win32_PerfFormattedData_PerfProc_JobObjectDetails
Win32_PerfFormattedData_PerfProc_Process
Win32_PerfFormattedData_PerfProc_ProcessAddressSpace_Costly
Win32_PerfFormattedData_PerfProc_Thread
Win32_PerfFormattedData_PerfProc_ThreadDetails_Costly
Win32_PerfFormattedData_RemoteAccess_RASPort
Win32_PerfFormattedData_RemoteAccess_RASTotal
Win32_PerfFormattedData_RSVP_RSVPInterfaces
Win32_PerfFormattedData_RSVP_RSVPService
Win32_PerfFormattedData_Spooler_PrintQueue
Win32_PerfFormattedData_TapiSrv_Telephony
Win32_PerfFormattedData_Tcpip_ICMP
Win32_PerfFormattedData_Tcpip_IP
Win32_PerfFormattedData_Tcpip_NBTConnection
Win32_PerfFormattedData_Tcpip_NetworkInterface
Win32_PerfFormattedData_Tcpip_TCP
Win32_PerfFormattedData_Tcpip_UDP
Win32_PerfFormattedData_TermService_TerminalServices
Win32_PerfFormattedData_TermService_TerminalServicesSession
Win32_PerfFormattedData_W3SVC_WebService
Win32_PerfRawData_ASP_ActiveServerPages
Win32_PerfRawData_ASPNET_114322_ASPNETAppsv114322
Win32_PerfRawData_ASPNET_114322_ASPNETv114322
Win32_PerfRawData_ASPNET_2040607_ASPNETAppsv2040607
Win32_PerfRawData_ASPNET_2040607_ASPNETv2040607
Win32_PerfRawData_ASPNET_ASPNET
Win32_PerfRawData_ASPNET_ASPNETApplications
Win32_PerfRawData_aspnet_state_ASPNETStateService
Win32_PerfRawData_ContentFilter_IndexingServiceFilter
Win32_PerfRawData_ContentIndex_IndexingService
Win32_PerfRawData_DTSPipeline_SQLServerDTSPipeline
Win32_PerfRawData_Fax_FaxServices
Win32_PerfRawData_InetInfo_InternetInformationServicesGlobal
Win32_PerfRawData_ISAPISearch_HttpIndexingService
Win32_PerfRawData_MSDTC_DistributedTransactionCoordinator
Win32_PerfRawData_NETCLRData_NETCLRData
Win32_PerfRawData_NETCLRNetworking_NETCLRNetworking
Win32_PerfRawData_NETDataProviderforOracle_NETCLRData
Win32_PerfRawData_NETDataProviderforSqlServer_NETDataProviderforSqlServer
Win32_PerfRawData_NETFramework_NETCLRExceptions
Win32_PerfRawData_NETFramework_NETCLRInterop
Win32_PerfRawData_NETFramework_NETCLRJit
Win32_PerfRawData_NETFramework_NETCLRLoading
Win32_PerfRawData_NETFramework_NETCLRLocksAndThreads
Win32_PerfRawData_NETFramework_NETCLRMemory
Win32_PerfRawData_NETFramework_NETCLRRemoting
Win32_PerfRawData_NETFramework_NETCLRSecurity
Win32_PerfRawData_NTFSDRV_ControladordealmacenamientoNTFSdeSMTP
Win32_PerfRawData_Outlook_Outlook
Win32_PerfRawData_PerfDisk_LogicalDisk
Win32_PerfRawData_PerfDisk_PhysicalDisk
Win32_PerfRawData_PerfNet_Browser
Win32_PerfRawData_PerfNet_Redirector
Win32_PerfRawData_PerfNet_Server
Win32_PerfRawData_PerfNet_ServerWorkQueues
Win32_PerfRawData_PerfOS_Cache
Win32_PerfRawData_PerfOS_Memory
Win32_PerfRawData_PerfOS_Objects
Win32_PerfRawData_PerfOS_PagingFile
Win32_PerfRawData_PerfOS_Processor
Win32_PerfRawData_PerfOS_System
Win32_PerfRawData_PerfProc_FullImage_Costly
Win32_PerfRawData_PerfProc_Image_Costly
Win32_PerfRawData_PerfProc_JobObject
Win32_PerfRawData_PerfProc_JobObjectDetails
Win32_PerfRawData_PerfProc_Process
Win32_PerfRawData_PerfProc_ProcessAddressSpace_Costly
Win32_PerfRawData_PerfProc_Thread
Win32_PerfRawData_PerfProc_ThreadDetails_Costly
Win32_PerfRawData_RemoteAccess_RASPort
Win32_PerfRawData_RemoteAccess_RASTotal
Win32_PerfRawData_RSVP_RSVPInterfaces
Win32_PerfRawData_RSVP_RSVPService
Win32_PerfRawData_Spooler_PrintQueue
Win32_PerfRawData_TapiSrv_Telephony
Win32_PerfRawData_Tcpip_ICMP
Win32_PerfRawData_Tcpip_IP
Win32_PerfRawData_Tcpip_NBTConnection
Win32_PerfRawData_Tcpip_NetworkInterface
Win32_PerfRawData_Tcpip_TCP
Win32_PerfRawData_Tcpip_UDP
Win32_PerfRawData_TermService_TerminalServices
Win32_PerfRawData_TermService_TerminalServicesSession
Win32_PerfRawData_W3SVC_WebService
Win32_PhysicalMedia
Win32_PhysicalMemory
Win32_PhysicalMemoryArray
Win32_PhysicalMemoryLocation
Win32_PingStatus
Win32_PNPAllocatedResource
Win32_PnPDevice
Win32_PnPEntity
Win32_PnPSignedDriver
Win32_PnPSignedDriverCIMDataFile
Win32_PointingDevice
Win32_PortableBattery
Win32_PortConnector
Win32_PortResource
Win32_POTSModem
Win32_POTSModemToSerialPort
Win32_Printer
Win32_PrinterConfiguration
Win32_PrinterController
Win32_PrinterDriver
Win32_PrinterDriverDll
Win32_PrinterSetting
Win32_PrinterShare
Win32_PrintJob
Win32_Process
Win32_Processor
Win32_Product
Win32_ProductCheck
Win32_ProductResource
Win32_ProductSoftwareFeatures
Win32_ProgIDSpecification
Win32_ProgramGroup
Win32_ProgramGroupContents
Win32_Property
Win32_ProtocolBinding
Win32_Proxy
Win32_PublishComponentAction
Win32_QuickFixEngineering
Win32_QuotaSetting
Win32_Refrigeration
Win32_Registry
Win32_RegistryAction
Win32_RemoveFileAction
Win32_RemoveIniAction
Win32_ReserveCost
Win32_ScheduledJob
Win32_SCSIController
Win32_SCSIControllerDevice
Win32_SecuritySettingOfLogicalFile
Win32_SecuritySettingOfLogicalShare
Win32_SelfRegModuleAction
Win32_SerialPort
Win32_SerialPortConfiguration
Win32_SerialPortSetting
Win32_ServerConnection
Win32_ServerSession
Win32_Service
Win32_ServiceControl
Win32_ServiceSpecification
Win32_ServiceSpecificationService
Win32_SessionConnection
Win32_SessionProcess
Win32_Share
Win32_ShareToDirectory
Win32_ShortcutAction
Win32_ShortcutFile
Win32_ShortcutSAP
Win32_SID
Win32_SoftwareElement
Win32_SoftwareElementAction
Win32_SoftwareElementCheck
Win32_SoftwareElementCondition
Win32_SoftwareElementResource
Win32_SoftwareFeature
Win32_SoftwareFeatureAction
Win32_SoftwareFeatureCheck
Win32_SoftwareFeatureParent
Win32_SoftwareFeatureSoftwareElements
Win32_SoundDevice
Win32_StartupCommand
Win32_SubDirectory
Win32_SystemAccount
Win32_SystemBIOS
Win32_SystemBootConfiguration
Win32_SystemDesktop
Win32_SystemDevices
Win32_SystemDriver
Win32_SystemDriverPNPEntity
Win32_SystemEnclosure
Win32_SystemLoadOrderGroups
Win32_SystemLogicalMemoryConfiguration
Win32_SystemNetworkConnections
Win32_SystemOperatingSystem
Win32_SystemPartitions
Win32_SystemProcesses
Win32_SystemProgramGroups
Win32_SystemResources
Win32_SystemServices
Win32_SystemSlot
Win32_SystemSystemDriver
Win32_SystemTimeZone
Win32_SystemUsers
Win32_TapeDrive
Win32_TCPIPPrinterPort
Win32_TemperatureProbe
Win32_Terminal
Win32_TerminalService
Win32_TerminalServiceSetting
Win32_TerminalServiceToSetting
Win32_TerminalTerminalSetting
Win32_Thread
Win32_TimeZone
Win32_TSAccount
Win32_TSClientSetting
Win32_TSEnvironmentSetting
Win32_TSGeneralSetting
Win32_TSLogonSetting
Win32_TSNetworkAdapterListSetting
Win32_TSNetworkAdapterSetting
Win32_TSPermissionsSetting
Win32_TSRemoteControlSetting
Win32_TSSessionDirectory
Win32_TSSessionDirectorySetting
Win32_TSSessionSetting
Win32_TypeLibraryAction
Win32_UninterruptiblePowerSupply
Win32_USBController
Win32_USBControllerDevice
Win32_USBHub
Win32_UserAccount
Win32_UserDesktop
Win32_UserInDomain
Win32_UTCTime
Win32_VideoController
Win32_VideoSettings
Win32_VoltageProbe
Win32_VolumeQuotaSetting
Win32_WindowsProductActivation
Win32_WMIElementSetting
Win32_WMISetting
 

 
 

Requerimientos mínimos, en cuando a la disponibilidad en el Sistema Operativo y componentes WMI

 
 
WMI, se encuentra incluido en MS Windows 2000 o superior, MS Windows XP, y MS Windows Millenniun Edition (Me).
Para MS Windows 95 (OSR2), MS Windows 98 o MS Windows NT 4.0, puedes realizar la descarga de la siguiente URL:
 
Windows Management Instrumentation (WMI) CORE 1.5 (Windows 95/98)
http://www.microsoft.com/downloads/details.aspx?FamilyId=98A4C5BA-337B-4E92-8C18-A63847760EA5&displaylang=en
 
 

Zona de descarga en la Web de Microsoft

 
Management (WMI) Extensions for Visual Studio .NET 2003 Server Explorer
http://www.microsoft.com/downloads/details.aspx?FamilyID=62d91a63-1253-4ea6-8599-68fb3ef77de1&DisplayLang=en
 
Management (WMI) Extensions for Visual Studio .NET 2002 Server Explorer (RTM)
http://www.microsoft.com/downloads/details.aspx?FamilyId=EF7594D3-4907-4AF6-B7D8-6E22115FFAF0&displaylang=en
 
WMI Administrative Tools
http://www.microsoft.com/downloads/details.aspx?FamilyId=6430F853-1120-48DB-8CC5-F2ABDC3ED314&displaylang=en
 
Windows Management Instrumentation Tutorial
http://www.microsoft.com/downloads/details.aspx?FamilyId=720F0CAE-64A7-457F-BB95-E4F33E0CBC55&displaylang=en
 
 
Windows Management Instrumentation (WMI) SNMP Provider 1.5 Build 1085.0005 (Windows NT 4.0 and 2000)
http://www.microsoft.com/downloads/details.aspx?FamilyId=C6B30755-6D20-4107-82C5-089E3DFE4FEE&displaylang=en
 
 
● Información detallada de WMI en la plataforma [SDK: Windows Management Instrumentation]

  

Antonio Muñoz de Burgos y Caravaca
www.emans.com  (Web realizada en vFoxPro)
Sevilla - España
Manifestando el apoyo a la comunidad de desarrolladores de MS Visual FoxPro.
 

Todas las marcas aquí mencionadas, están registradas por sus respectivos fabricantes.

24 de enero de 2005

El nuevo tipo de datos BLOB en VFP 9.0

Introducción

Visual FoxPro 9.0 incluye un nuevo tipo de datos llamado BLOB (Binary Large OBject). Este tipo de datos sirve para almacenar datos binarios de cualquier tipo y de longitud variable, como por ejemplo un archivo ejecutable, archivos de imágenes, cadenas de bytes, etc. El tipo de datos Blob es particularmente útil para almacenar imágenes desde un SQL Server.

En el siguiente ejemplo para Visual FoxPro 9, lo utilizaremos en un cursor con un campo tipo Blob, en el cual almacenaremos archivos de imágenes. Este ejemplo es solo ilustrativo e intenta simular un cursor que puede haber sido creado por una cláusula SELECT a una tabla de SQL Server, o bien por un comando XMLTOCURSOR() con datos recibidos de una fuente externa como un Servicio Web.

Conceptos previos

Estos son algunos conceptos que debemos tener en cuenta al utilizar el nuevo tipo de datos Blob:
  • Los datos tipos Blob se pueden utilizar en contenedores de bases de datos, tablas libres, cursores y vistas.
  • Puede haber múltiples campos de tipo Blob en una misma tabla.
  • Los valores Blob se almacenan en un archivo Memo (.ftp).
  • En los campos de tipo Blob no se realiza ninguna traducción del código de página.
  • El límite de un campo Blob esta dado por la memoria disponible y/o por el límite de 2 GB en el tamaño del archivo.
  • Se puede visualizar el contenido de un campo Blob con el control Cuadro de Edición (EditBox), Cuadro de Texto (TextBox) en una Cuadrícula (Grid) o con el comando MODIFY MEMO <CampoBlob>. En todos los casos los valores son de Solo Lectura.
  • En los Cuadros de Edición, los valores Blob se muestran como valores hexadecimales sin el prefijo "0h".
  • En las Cuadrículas, los valores Blob se muestran con la cadena "blob" si el campo está vacío, o con la cadena "Blob" si el campo contiene datos. Con un doble click en el campo de la cuadrícula se puede visualizar su contenido en una ventana de edición de solo lectura.
  • No están soportadas las claves de índices sobre campos de tipo Blob.
El formulario de ejemplo

En el formulario del ejemplo, en el método Init creamos un cursor Alumnos con un campo Blob en el que almacenaremos las imágenes que se encuentran en la carpeta Samples\Data\Graphics del directorio raíz de la instalación de Visual FoxPro 9.0. (Figura 1)


Figura 1: Imagenes de la carpeta "Samples\Data\Graphics\"

El formulario contiene un control Cuadrícula con todos los campos del cursor Alumnos, un control Cuadro de Edición con el contenido del campo Blob, y un control Imagen en el que configuramos la propiedad PictureVal (nueva en VFP 9.0) con el contenido del campo Blob cada vez que nos movemos de registro en el control Cuadrícula. (Figura 2)


Figura 2: Vista del formulario del ejemplo

Este formulario de ejemplo se puede descargar desde el siguiente enlace:blob.zip (2,87 KB)

A continuación se expone el código del formulario, para correrlo se debe copiar el código en un archivo .PRG y ejecutarlo desde Visual FoxPro 9.0.

PUBLIC oMiForm
oMiForm = NEWOBJECT("MiForm")
oMiForm.SHOW
RETURN

DEFINE CLASS MiForm AS FORM
  HEIGHT = 336
  WIDTH = 728
  DOCREATE = .T.
  AUTOCENTER = .T.
  CAPTION = "Ejemplo de un campo Blob"
  BINDCONTROLS = .F.
  NAME = "MiForm"

  ADD OBJECT edtFoto AS EDITBOX WITH ;
    COMMENT = "", ;
    HEIGHT = 216, ;
    LEFT = 296, ;
    TABINDEX = 2, ;
    TOP = 8, ;
    WIDTH = 216, ;
    CONTROLSOURCE = "Alumnos.Foto", ;
    NAME = "edtFoto"

  ADD OBJECT imgFoto AS IMAGE WITH ;
    STRETCH = 1, ;
    HEIGHT = 216, ;
    LEFT = 520, ;
    TOP = 8, ;
    WIDTH = 192, ;
    NAME = "imgFoto"

  ADD OBJECT grdAlumnos AS MiGrid

  ADD OBJECT lblgrid AS LABEL WITH ;
    WORDWRAP = .T., ;
    BACKSTYLE = 0, ;
    CAPTION = [Cursor con un campo Blob. Con "Doble Click" en el campo Blob ] +;
    [visualizamos el contenido en una ventana de edición de solo lectura.'], ;
    HEIGHT = 72, ;
    LEFT = 32, ;
    TOP = 232, ;
    WIDTH = 232, ;
    FORECOLOR = RGB(0,0,0), ;
    NAME = "lblGrid"

  ADD OBJECT lbleditbox AS LABEL WITH ;
    WORDWRAP = .T., ;
    BACKSTYLE = 0, ;
    CAPTION = [Cuadro de Edición de solo lectura con el contenido del campo Blob.], ;
    HEIGHT = 72, ;
    LEFT = 304, ;
    TOP = 232, ;
    WIDTH = 192, ;
    FORECOLOR = RGB(0,0,255), ;
    NAME = "lblEditBox"

  ADD OBJECT lblimage AS LABEL WITH ;
    WORDWRAP = .T., ;
    BACKSTYLE = 0, ;
    CAPTION = [Control Imagen con la propiedad PictureVal configurada con ] +;
    [el contenido del campo Blob.] , ;
    HEIGHT = 72, ;
    LEFT = 528, ;
    TOP = 232, ;
    WIDTH = 176, ;
    FORECOLOR = RGB(255,0,0), ;
    NAME = "lblImage"

  ADD OBJECT cmdmodifymemo AS COMMANDBUTTON WITH ;
    TOP = 304, ;
    LEFT = 48, ;
    HEIGHT = 24, ;
    WIDTH = 216, ;
    CAPTION = "MODIFY MEMO <CampoBlob>", ;
    NAME = "cmdModifyMemo"

  ADD OBJECT label1 AS LABEL WITH ;
    WORDWRAP = .T., ;
    BACKSTYLE = 0, ;
    CAPTION = "Botón con el cláusula MODIFY MEMO Alumnos.Foto", ;
    HEIGHT = 16, ;
    LEFT = 272, ;
    TOP = 310, ;
    WIDTH = 408, ;
    FORECOLOR = RGB(0,128,0), ;
    NAME = "Label1"

  PROCEDURE INIT
    LOCAL lcRuta, lcFoto, ln
    *-- Creo el cursor Alumnos
    CREATE CURSOR Alumnos (Numero i, Nombre c(10), Foto w)
    *-- Recorro las imágenes de SAMPLES\DATA\GRAPHICS
    lcRuta = HOME(2) + "DATA\GRAPHICS\"
    lcFoto = SYS(2000,lcRuta + "*.GIF")
    ln = 1
    DO WHILE NOT EMPTY(lcFoto)
      INSERT INTO Alumnos (Numero, Nombre, Foto) ;
        VALUES (ln, JUSTSTEM(lcFoto), FILETOSTR(lcRuta + lcFoto))
      lcFoto = SYS(2000, lcRuta + "*.GIF", 1)
      ln = ln + 1
    ENDDO
    GO TOP IN Alumnos
    *-- Enlazo los controles
    THISFORM.BINDCONTROLS = .T.
  ENDPROC

  PROCEDURE grdAlumnos.AFTERROWCOLCHANGE
    LPARAMETERS nColIndex
    THISFORM.imgFoto.PICTUREVAL = Alumnos.Foto
    THISFORM.edtFoto.REFRESH
  ENDPROC

  PROCEDURE cmdmodifymemo.CLICK
    MODIFY MEMO Alumnos.Foto
  ENDPROC

ENDDEFINE

DEFINE CLASS MiGrid AS GRID
  COLUMNCOUNT = 3
  DELETEMARK = .F.
  HEIGHT = 216
  LEFT = 16
  PANEL = 1
  READONLY = .T.
  RECORDSOURCE = "Alumnos"
  RECORDSOURCETYPE = 1
  SCROLLBARS = 2
  TABINDEX = 1
  TOP = 8
  WIDTH = 272
  HIGHLIGHTSTYLE = 2
  NAME = "grdAlumnos"
  Column1.CONTROLSOURCE = "Alumnos.numero"
  Column1.WIDTH = 75
  Column1.READONLY = .T.
  Column1.VISIBLE = .T.
  Column1.NAME = "Column1"
  Column2.CONTROLSOURCE = "Alumnos.Nombre"
  Column2.WIDTH = 111
  Column2.READONLY = .T.
  Column2.VISIBLE = .T.
  Column2.NAME = "Column2"
  Column3.CONTROLSOURCE = "Alumnos.Foto"
  Column3.WIDTH = 53
  Column3.READONLY = .T.
  Column3.NAME = "Column3"

  PROCEDURE INIT
    THIS.Column1.Header1.ALIGNMENT = 2
    THIS.Column1.Header1.CAPTION = "Numero"
    THIS.Column1.Header1.NAME = "Header1"
    THIS.Column2.Header1.ALIGNMENT = 2
    THIS.Column2.Header1.CAPTION = "Nombre"
    THIS.Column2.Header1.NAME = "Header1"
    THIS.Column3.Header1.ALIGNMENT = 2
    THIS.Column3.Header1.CAPTION = "Blob"
    THIS.Column3.Header1.NAME = "Header1"
  ENDPROC

ENDDEFINE

Comentarios

Como enunciamos al comienzo, esto es solo un simple ejemplo que ilustra una de las tantas utilidades que podemos darle a este nuevo tipo de datos en Visual FoxPro 9.0.

Hasta la próxima.

Luis María Guayán