Nuevos lanzamientos de “1C: Trade Management”: actualización sin desarrollo. La contabilidad operativa se regula


Esto se debe a algunas peculiaridades de la función de contexto global ConnectExternalComponent().

A menudo, los programadores tienen problemas para conectar componentes externos (por ejemplo, controladores para equipos comerciales) cuando los usuarios trabajan con 1C, conectándose al servidor a través de un terminal.

En este caso, los usuarios ven, por ejemplo, esta imagen:

Mientras que cuando se trabaja desde computadoras locales no hay problemas para conectar componentes externos.

¿Con qué está conectado esto? Esto se debe a que cuando los usuarios trabajan a través de un servidor terminal, tienen menos derechos que cuando trabajan en una computadora local.

Puede verificar esto fácilmente si inicia sesión en el servidor de terminal con una cuenta con derechos administrativos.

La razón de esta diferencia es que 1C no puede registrar un componente externo en el registro cuando el usuario está trabajando en el terminal con derechos normales, porque un usuario normal no tiene permiso para escribir en la rama del registro del sistema HKEY_CLASSES_ROOT.

Las publicaciones sobre el tema de la conexión de componentes externos en el terminal ofrecen diversos métodos para solucionar este problema.

Por ejemplo, estos:

1. Inicie 1C por primera vez con derechos administrativos.

Esta opción no siempre funciona. Explicaré por qué a continuación.

2. Otorgue permiso a los usuarios normales de la terminal para escribir en la rama del registro del sistema. HKEY_CLASSES_ROOT.

Los usuarios no suficientemente avanzados no deberían hacer esto, de lo contrario pueden surgir problemas.

3. Utilizando varios dispositivos, registre VK en nombre de un usuario con todos los derechos.

Tampoco es bueno.

Entonces, ¿cuál es la mejor manera de salir de esta situación?

Ofrezco mi solución a este problema. En mi opinión, sencillo y bonito.

Mientras investigaba este problema, me hice la pregunta: ¿por qué 1C intenta siquiera registrar VK utilizando una nueva ruta? Después de todo, ella ya está registrada en el sistema.

La cuestión resultó ser que en las configuraciones típicas de 1C (por ejemplo, "Gestión comercial") se utiliza la siguiente sintaxis para el método de contexto global Conectar componente externo():

ConnectExternalComponent("Directorio.ConnectedEquipment.Layout.DriverATOLBarcodeScanner", "ATOLScanner");

Como puede ver, el controlador VC se conecta desde el diseño "ATOLBarcode Scanner Driver" del directorio "Equipo conectado".

¿Qué pasa entonces?

1C guarda el componente en la carpeta temporal del usuario, por ejemplo "C:\Documentos y configuraciones\Usuario\Configuración local\Temp\1032\v8_4_12.tmp"

e intenta registrarlo en la sucursal de registro HKEY_CLASSES_ROOT exactamente por este camino.

En el terminal, los usuarios normales no tienen derecho a cambiar esta rama del registro, por lo que el componente no se conecta a ellos.

Ahora hablemos de cómo salir de esta situación.

El método de contexto global ConnectExternalComponent() tiene varias opciones de sintaxis. Esto es lo que usaremos.

Entonces, paso a paso:

1. Registre el componente externo usando la utilidad regsvr32.exe en el servidor terminal en la carpeta C:\WINDOWS\SYSTEM32 para un sistema operativo de 32 bits o en la carpeta C:\WINDOWS\SYSWOW64 para un sistema operativo de 64 bits.

2. Utilice una de las dos opciones de sintaxis adicionales para el método ConnectExternalComponent():

Opción 1:

ConnectExternalComponent("C:\WINDOWS\SysWOW64\Scaner1C.dll", "ATOLScanner", ExternalComponentType.COM);

DriverObject = Nuevo("AddIn.ATOLScanner.Scaner45");

Opcion 2:

ProgID = "AddIn.Scaner45";

ConectarComponenteExterno(ProgID);

DriverObject = Nuevo (ProgID);

En mi opinión, es preferible la opción número 2.

Al mismo tiempo, 1C no intenta volver a registrar el VK utilizando una nueva ruta en el registro y así se resuelven todos los problemas.

Bueno eso es todo. ¡Buena suerte en el trabajo!

[debes registrarte para ver el enlace]

Pregunta: Componente externo Native Api en C++ para Linux (Ubuntu x64) en 1C 8.3


Estoy escribiendo a VK, pero no puedo conectarme a 1c en ubuntu. Incluso el ejecutable de 1c no se conecta. Entonces una pregunta al respecto:

1) Estoy intentando conectar VK desde el ejemplo de VNCOMPS que figura en el artículo.

(el enlace se puede encontrar al final: “Copiando”).
Hay un archivo MAKE dentro del proyecto NativeApi. Con su ayuda estoy construyendo una biblioteca .so en Ununtu.
Pero cuando "Conectar componente externo" 1c falla.
Del mismo modo, si construyo usando "build.sh" (en la raíz del proyecto).

En el propio archivo MAKE cambio la bandera de m32 a m64, porque 1c y el propio sistema x64. (con el parámetro m32 no se conecta de todos modos)
Aquí hay un ejemplo de cómo llamar a VK desde 1C 8.3:
Conexión realizada = Conectar componente externo("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); Hay un artículo solo sobre este tema.
Pero, por lo que veo, todos estos puntos ya se han tenido en cuenta y corregidos en el ejemplo de VNCOMPS.

Pero esencialmente es una cuestión de parámetros de compilación. Un componente externo MB de 32 bits se conecta normalmente a un 1c de 32 bits, pero lo implementé en Ubuntu x64 1c Enterprise83 8.3.5-1486 AMD64. Y quiero conectarme con ella en VK.

¿Alguien tiene alguna idea sobre cómo resolver este problema?)
El ejemplo de VNCOMPS debería funcionar, pero es necesario ajustar los parámetros de compilación o la plataforma en la que estoy probando es incorrecta.

Respuesta: Me pregunto, ¿es posible escribir un componente externo en Java?

Pregunta: El componente externo (nativo) no se puede conectar


Compilé un ejemplo con ITS, para sistemas de 64 y 32 bits.

Me conecto así:
Resultado de la conexión = ConnectExternalComponent(KDLLPath, "Comp", ExternalComponentType.Native); La conexión funciona en una PC, pero no en la otra. Hay una diferencia en el sistema operativo. Donde se realiza la conexión, está Win7, donde no hay Win10. Al mismo tiempo, en la PC donde mi componente no funciona, funcionan los componentes estándar.

Probado en diferentes plataformas (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).

¿Cómo puedo entender por qué no se conecta?

Respuesta: vc_redist ¿lo olvidó?

Pregunta: 1C8 y un componente externo de tipo Nativo


Buenas tardes.
Tengo una configuración BP 3.0.50.12 y deseo implementar el pesaje de la empresa Vesy-Soft utilizando UniServerAuto.
Los desarrolladores compilaron el componente en Native para Windows 32 y 64 y lo archivaron con el archivo maifest. También hay un ejemplo para 1C de cómo se puede calcular el peso. En él, utilizando un diseño con datos binarios, se indica este archivo, según tengo entendido. En el ejemplo, todo está bien: el componente está instalado, conectado, luego se establece la conexión y se lee el peso.
Pero tan pronto como comienzas a transferirlo a 1C, no se lee el peso. Todo parece estar escrito de forma sencilla, pero no entiendo dónde está el rastrillo.
Quien tenga un poco de tiempo, ayude, mire con un ojo, tal vez la solución esté en la superficie, pero voy a algún lugar equivocado y hago lo incorrecto. Nunca antes había tenido que trabajar con tecnología nativa...

Y en el archivo adjunto está mi texto de procesamiento.

Respuesta:

Bueno tengo noticias...
Simplemente comencé a ver paso a paso en qué punto empezaría a fallar. Para hacer esto, creé una base de datos vacía y la procesé con el comando. Por analogía con el ejemplo del proveedor, transfirí el diseño a una nueva configuración: funciona la segunda vez. Aquellos. La primera vez no, pero la segunda vez sí. De esto surgió la idea de que en nuestro procesamiento todavía sería necesario separar la conexión del componente y el objeto según diferentes procedimientos.
Luego lo transferí a mi base de datos con la conexión del diseño: funciona. Uf, eso es bueno.... Pero me gustaría sin hacer cambios en la configuración, así que sigamos adelante.

Estoy intentando agregar el diseño al procesamiento. Su tamaño aumenta inmediatamente de 10kb a 3mb y se nota una ralentización significativa en el funcionamiento: no es adecuado. Estoy empezando a profundizar en la conexión de componentes mediante dll. Aquellos. esencialmente lo mismo que donde comencé. Pero hay un "PERO": al buscar el nombre del dll en la carpeta del usuario, noté que este dll se encuentra donde (según tengo entendido) se suman los dll registrados en 1C:
C:\Usuarios\USUARIO\AppData\Roaming\1C\1cv8\ExtCompT
En consecuencia, no es necesario utilizar la ruta completa al dll, simplemente puede ingresar su nombre:
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

Lo intento... dice malas palabras al registrarse, pero devuelve el resultado del pesaje. Resulta que la dll ya está registrada y eso significa que sólo necesitas conectarla. Lo quito y todo funciona.
En resumen:
1. En el procesamiento de pesaje, el procedimiento AtOpening incluía la conexión de un componente externo y una conexión a un objeto.
2. Ruta al dll No lo escribí, solo indiqué su nombre.

Ahora estoy sentado y pensando, ¿cuándo se instaló el dll en 1C? ¿En el momento de la instalación del software? Difícilmente... Al momento de iniciar la configuración de desarrollador de este dll, ¿dónde se instala cuando se abre el formulario? No lo sé, pero me parece cercano... ¿Qué opinas?
Y segundo, en un lugar nuevo, cuando es necesario instalar el mismo terminal, ¿qué hay que hacer para que todo funcione? ¿Debo instalar el software por completo, ejecutar la configuración del proveedor para verificar el funcionamiento y luego (en teoría) debería funcionar mi procesamiento? Algo es algo complicado... ¿O debería instalar el componente externo una vez en mi procesamiento después de instalar el software?

Me gustaría escuchar tu opinión sobre este asunto...

Pregunta: Componente externo.dll


Buenas tardes a todos.
Una pregunta.
Un componente dll que funciona muy bien en 1C 7.7
1s 8.1 no quiere arrancar en absoluto...
Intenté pegarlo en C:\Program Files\1cv81\bin\cache1c.dll
Intenté registrarme usando regsvr32 "C:\Program Files\1cv81\bin\cache1c.dll"
Se registra sin problemas.
Cuando quiero acceder me sale un mensaje de error:

¡Error al cargar el componente externo! caché1c.dll
Procedimiento BotónEjecutarPresionar(Botón) Intento de cargar componente externo( "C:\Archivos de programa\1cv81\bin\cache1c.dll"); Informe de excepciones( "¡Error al cargar el componente externo!"+ "cache1c.dll"); intento final; Intento // Obtener el objeto componente. // m = Nuevo ("cache1c.GTMcmd"); m = Nuevo COMObject("cache1c.GTMcmd"); Informe de excepciones(); intento final; Procedimiento final

Respuesta: Es banal hasta el punto de la imposibilidad...
Necesitas hacer una pausa entre llamadas (milisegundos)...
Procedimiento ButtonExecutePress(Button) Intento // Obtener un objeto componente. m = Nuevo COMObject("cache1c.GTMcmd"); Informe de excepciones( "Error al crear el objeto de componente externo"); intento final; m.RemoteHost = "192.168.1.101"; m.RemotePort = 6330; m.Conectar(); m.Pausa(100); ...... etc
Para 1c 7.7, esto no es necesario, resulta que el manejo es más rápido.

Pregunta: Trabajar con un componente externo con un servidor 1C...


Buenas tardes,

Existe un componente externo escrito en C++, cuya tarea es obtener información de una base de datos externa y devolver el resultado de la consulta en forma de Tabla de Valores en 1C.
Para generar una tabla de valores en el momento actual se utiliza la interfaz IDispatch* pBackConnection, recibida como parámetro en la función Init(). A continuación, simplemente uso funciones 1C para crear una tabla de valores, la completo y la devuelvo al segundo parámetro en CallAsFunc(...).
Los problemas comenzaron con la transición a clientes ligeros 1C. En el lado del servidor, el componente externo realmente no se inicia. Puede ejecutarlo en el lado del cliente, pero todo parece muletas y se sale de la lógica general "cliente-servidor" en 1C. Por ejemplo, el cliente no entiende qué es una tabla de valores, problemas con variables “globales”, sesiones, etc.
NativeAPI es aún más limitado a este respecto.
Bailar con una pandereta me llevó al hecho de que pude ejecutar un componente externo en el servidor 1C, PERO el trabajo continúa hasta que se intenta llamar a Invoke en pBackConnection. La versión de 64 bits del servidor 8.2 intenta hacer algo hasta que se agota el tiempo de espera, la versión de 32 bits (VK naturalmente también es de 32 bits) simplemente se cae inmediatamente.
Supongo que el servidor 1C no admite este modo de funcionamiento.
En consecuencia, surgen preguntas: ¿es esto temporal o la lógica de 1C se reduce a cancelar este esquema de trabajo? Si es imposible crear estructuras internas 1C (una tabla de valores) de esta manera, ¿existe, en principio, una descripción de qué es una tabla de valores a nivel del sistema para intentar crearla en C++? ¿Rellénelo y luego simplemente deslícelo en 1C como parámetro de retorno? Me gustaría al menos saber en qué dirección excavar.

Gracias.

Respuesta:

Escribes una cosa y quieres decir otra.
En el entorno 1C, declarar variables que serán visibles en diferentes sesiones ahora no es imposible, y antes no existía tal posibilidad. Otra sesión es un proceso físicamente diferente.
Una sesión es una sesión que se conecta a una base de datos, es decir. sesión de usuario. ¿O estás poniendo algo tuyo en este concepto?

Dentro de una sesión era posible, y ahora es posible, declarar variables en el módulo de sesión que vivirán y serán visibles dentro de la sesión desde diferentes lugares... en realidad, hay 4 de ellas.
- Módulo de sesión;
- Módulo de solicitud regular;
- Módulo de aplicación gestionado;
- Módulo de conexión externo.

Bueno, por supuesto, debes recordar el contexto. No se puede acceder directamente al contexto del servidor desde el lado del cliente y viceversa.

De hecho, la arquitectura 1C estipula que el intercambio de datos se realizará de la siguiente manera:
- mediante parámetros/devoluciones de procedimientos/funciones;
- mediante los llamados parámetros de sesión (no pueden ser objetos, pero sí visibles en la paleta).

Una tabla en el formulario... ¿está conectada a alguna tabla de objetos (procesamiento, por ejemplo)? O no. En caso afirmativo, entonces está disponible en el servidor (&OnServer) y se puede editar allí...

Y sin embargo, sí, la Tabla de Valores no está disponible en la UV del lado del cliente. Bueno, eso es lo que decidió 1C.

¡Vamos! Funciona con Excel, funciona con FSO y muchas otras cosas, pero no funciona aquí. Detecta el error y analiza....

Intentar
...
Tus acciones
...
Excepción
str = DescripciónError();
intento final;

Con las capacidades del hardware moderno, esto no es un argumento en absoluto.

Puramente tu opinión personal. No tiene nada que ver con la realidad. De ninguna manera. Repito una vez más, 1C funciona muy bien con COM. Tanto con proceso in-proc como out-proc.

Proporcione el código que utiliza para descargar y comunicarse con VK.

Por cierto, VK... en tu caso, ¿es COM o API nativa?
Si es COM, entonces lo registra como... mediante regsvr32... ¿cómo “resuelve” entonces el problema de la profundidad de bits?

Pregunta: Instalación de un componente externo


Por favor dígame cómo instalar un componente externo. Al ejecutar el siguiente código, se genera un error. En el diseño, busque NameDecl.dll

Intentando SetExternalComponent("GeneralLayout.Layout"); Excepción FinIntento;
Error: ¡Falló la instalación del componente externo!

Respuesta: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native) devuelve FALSO.
Nuevo("AddIn.NameDecl.CNameDecl", Indefinido) = (()): Tipo indefinido (AddIn.NameDecl.NameDecl)

Pregunta: La DLL nativa no se conecta a 1c 8.1 (fptrwin32_fz54_9_11_0_5549.dll)


Hola.
1C actualizó el dll para cajas registradoras en línea atol para ffd 1.05 (incluido en el procesamiento de mantenimiento fptrwin32_fz54_9_11_0_5549.dll).
Tengo un viejo 1C 8.1. A diferencia de 8.2, no admite trabajar con equipos externos de la misma manera que 8.2, por lo que primero debe registrar el dll en Windows y luego solo conectarlo a 1C.

ProgID = "AddIn.IntegrationComponent.ATOL_KKT_1C83_V9"; LoadExternalComponent("C:\fptrwin32_fz54_9_11_0_5549.dll"); ConnectExternalComponent(progID); Controlador = Nuevo (ProgID);

Sin embargo, el procesamiento anterior se escribió en "tecnología" com y el nuevo es nativo. En consecuencia, al registrar regsvr32 aparece un error:
El módulo está cargado, pero no se encuentra el punto de entrada de DllRegisterServer. Y sugiere verificar que este archivo sea el archivo dll u OCX correcto.
¿Alguien se ha encontrado con una situación similar y cómo salió? Entiendo que 7.7 tendrá un problema similar.
Código 8.2:

Diseño = GetLayout("Componente de integración"); Dirección = PlaceInTemporaryStorage(Diseño); ConnectExternalComponent(Dirección, "Componente de integración", Tipo de componente externo.Nativo); Controlador = Nuevo("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

1C 8.2:
Conectar componente externo (<Местоположение>, <Имя>, <Тип>)
1C 8.1:
Conectar componente externo (<Идентификатор объекта>)
Opciones:
<Идентификатор объекта>(requerido)
Tipo: Cuerda. ProgID (Identificador programático) del objeto del componente externo. Debe corresponder a la información de la base de datos de registro del sistema (Registro).
Descripción:
Conecta objetos de componentes externos a 1C:Enterprise.
No disponible en el servidor 1C:Enterprise. No se utiliza en el módulo de conexión externo.
Nota:
Los componentes externos son compatibles con los componentes 1C:Enterprise 7.7.
Ejemplo:
Intentar
ConnectExternalComponent("AddinObject.Scanner");
Report("Se ha cargado el componente para el escáner de código de barras");
Excepción
Report("El componente para el escáner de código de barras no está cargado");
Intento final

¿Hay alguna forma de conectar este dll a 8.1 o no?

¡Gracias!

Respuesta:

También encontré recientemente este problema. No fue posible convertir a una versión posterior de 1c porque... dll con el que funciona esta configuración simplemente dejó de funcionar y 1c falló con un error.
Resolví el problema de la siguiente manera:
Creé una base de datos 8.3 vacía en la que procesé la inicialización del componente y luego desde 8.1 a través de una conexión COM accedí a la base de datos creada previamente e inicialicé el componente allí. Luego, ya en 8.1, llamé a los métodos de este componente.
Por supuesto que esto es una muleta, pero todavía no he encontrado otra salida(

Ejemplo de código 8.3:
Exportación de controladores variables;
Función ConexiónComponentesKKT() Exportar
Intentar

Diseño = GetLayout("Componente de integración");
Dirección = PlaceInTemporaryStorage(Diseño);
ConnectExternalComponent(Dirección, "Componente de integración", Tipo de componente externo.Nativo);
Controlador = Nuevo("AddIn.IntegrationComponent.SMDrvFR1C20");
Resultado = Verdadero;​

Excepción

Resultado = Falso;​

intento final;
Resultado de retorno
Función final

Ejemplo de código 8.1

Función CreateDriverObject(Driver) Exportar

Resultado = Verdadero;

Intentar

ConnectionString="File="""Ruta a la base de datos""";
ComObject = Nuevo COMObject("V83.ComConnector");
Conectar = ComObject.Connect(ConnectionString);

Procesamiento = Connect.Processing.ConnectExternalComponent.Create();
Resultado de la conexión = Processing.ConnectionCCPComponents();
Si el resultado de la conexión es entonces
Controlador = Procesamiento.Controlador;
FinSi;​

Excepción
Cualquiera que haya hecho esto o se haya encontrado con sentencias similares, explique el principio en sí con un ejemplo sencillo. Parece que todo está claro a la hora de conectar componentes externos.

// Ejemplo de llenado de la tabla de valores TK.Borrar(); Solicitud = Nueva Solicitud; Query.Text = "SELECCIONAR | Nomenclatura.Enlace CÓMO Nomenclatura |DESDE | Directory.Nomenclature AS Nomenclature"; Solicitar resultado = Request.Execute(); Selección = Solicitar resultado.Select(); Mientras que Selection.Next() Ciclo Página = TK.Add(); CompletePropertyValues(Página, Selección); EndCycle;
¿Podrías utilizar este ejemplo para explicar qué parte del código se suele eliminar? Sería lógico eliminar la parte con la solicitud, pero entonces ¿cómo podemos acceder a la base de datos desde el componente externo, sin pasar por la plataforma? No tiene sentido sacar el texto. O sacar la propia formación de la parte tabular. Comparte tu experiencia con cualquiera que haya encontrado esto.

Respuesta:¿Y que la palabra “Incompatible” siempre significa la palabra “Malo”? Sí, me parece que si llamara a mi estilo “1C: ¡La peor programación en este motor de scripting que existe en la naturaleza (traducida al lenguaje literario)!” Y probablemente habrá gente que quiera ver a esta bestia. Y parece un clásico: "¡No he leído a Pasternak, pero estoy completamente en desacuerdo con él!"

Pregunta: Conexión de un componente externo en 1s 8.3.6 y Win8


Debe conectar el componente externo vk_rs232.dll a la configuración escrita por usted mismo. Parece haber sido registrado a través de regsvr32.exe. "Parece" porque recibí un mensaje que decía "el componente está registrado, pero hay algún problema con el firewall". Basándome en la primera mitad del mensaje, escribo el código en 1C
AfterConnecting = Nueva descripción de alerta ("AfterConnectingVK", ThisForm); StartInstallingExternalComponents(,"C:\Controller\vk_rs232.dll"); Iniciar conexión de componentes externos (después de conectar, "C:\Controller\vk_rs232.dll", "DLL_Scales");
y me sale el error que
"¡La instalación de un componente externo falló! ¡Es posible que falte un componente para la aplicación cliente que está utilizando!".

Y ahora no entiendo:
1. Quizás el componente no esté registrado en el registro. ¿Cómo puedo comprobarlo allí?
2. Quizás su “versión” no funcione en Win8, aunque yo la tengo de 32 bits.
3. Quizás 1C en sí sea demasiado nuevo, es decir. En consecuencia, ¿no puede funcionar con este dll?
4. Bueno, es trivial: estoy escribiendo algo mal.

Respuesta: Y todo esto me llevó al siguiente problema. VneshComp está instalado, ahora necesitas conectarlo. Y aquí están ambas opciones.
ConnectExternalComponent("C:\Controller\vk_rs232.dll","Libra")
ConnectExternalComponent("GeneralLayout.Layout","Libra")

Opción de sintaxis: Por nombre y ubicación

Sintaxis:

Conectar componente externo (<Местоположение>, <Имя>, <Тип>)
Opciones:

<Местоположение>(requerido)

Tipo: Cuerda.
La ubicación del componente externo.
La ubicación se puede utilizar:
ruta al archivo del componente externo en el sistema de archivos (no disponible en el cliente web), no un archivo ZIP;
el nombre completo del diseño que almacena los datos binarios o el archivo ZIP;
La URL del componente externo, como datos binarios o un archivo ZIP, en un formato similar a GetNavigationLink.
<Имя>(requerido)

Tipo: Cuerda.
El nombre simbólico del componente externo que se va a conectar.
El nombre debe seguir las convenciones de nomenclatura del lenguaje integrado.
<Тип>(opcional)

Tipo: Tipo de componente externo.
Tipo de componente externo a conectar.
No se utiliza si el componente está empaquetado en un archivo ZIP.
Descripción de la opción del método:

Conecta componentes fabricados con tecnología nativa y COM.
El componente se puede almacenar en la base de datos o en el diseño de configuración como datos binarios o en un archivo ZIP.
Para los modos de inicio "Cliente ligero" y "Cliente web", el componente primero debe instalarse utilizando el método Instalar componente externo.
Opción de sintaxis: Por ID

Sintaxis:

Conectar componente externo (<ИдентификаторОбъекта>)
Opciones:

<ИдентификаторОбъекта>(requerido)

Tipo: Cuerda.
Identificador del objeto componente externo en forma de ProgID (Identificador programático) del registro de MS Windows (por ejemplo: "AddIn.Scanner").
Debe corresponder a la información de la base de datos de registro del sistema (Registro).
Descripción de la opción del método:

El componente debe implementarse utilizando tecnología COM y registrarse en el registro de MS Windows.
Estos componentes son compatibles con los componentes 1C:Enterprise 7.7.
¡Atención! La opción del método no funciona en el servidor ni en la conexión externa.
Valor de retorno:

Tipo: Booleano.
Verdadero: la conexión se realizó correctamente.
Descripción:

Conecta un componente externo a 1C:Enterprise.
Los componentes externos se pueden almacenar en una base de datos o en diseños de configuración como un archivo ZIP o como datos binarios, o en un archivo del sistema de archivos.
Cuando se trabaja en un cliente ligero y un cliente web, el componente debe estar preinstalado.

Disponibilidad:

Cliente ligero, cliente web, servidor, conexión externa.
Nota:

Los componentes externos se pueden implementar utilizando API nativa o tecnología COM. Los componentes fabricados con tecnología COM son compatibles con los componentes 1C:Enterprise 7.7.
El cliente web solo puede trabajar con componentes de la base de datos que estén empaquetados en un archivo.
El cliente ligero puede trabajar con componentes de la base de datos empaquetados en un archivo y componentes ubicados en el sistema de archivos.
El cliente pesado puede manejar todas las opciones de almacenamiento de componentes. En este caso, si un componente se instala mediante el método Instalar componente externo, entonces se utiliza el componente instalado y, si no está instalado, el componente se recibirá en el momento de la conexión.
El servidor puede funcionar con todos los componentes. El componente se almacena en caché por sesión del servidor.
Ejemplo:

Si ConnectExternalComponent ("AddinObject.Scanner") Entonces
Report("Componente para escáner de código de barras cargado");
De lo contrario
Report("El componente para el escáner de código de barras no está cargado");
terminara si;

  • Tutorial

Introducción

Este artículo da una idea de cómo funcionan los componentes externos en el sistema 1C: Enterprise.
Se mostrará el proceso de desarrollo de un componente externo para el sistema 1C: Enterprise versión 8.2, que se ejecuta en el sistema operativo Windows con un modo de operación de archivo. Esta opción se utiliza en la mayoría de las soluciones diseñadas para pequeñas empresas. VK se implementará en el lenguaje de programación C++.

Componentes externos "1C: Enterprise"

"1C: Enterprise" es un sistema extensible. Para ampliar la funcionalidad del sistema, se utilizan componentes externos (EC). Desde el punto de vista del desarrollador, un VC es un objeto externo que tiene propiedades y métodos, y también puede generar eventos para su procesamiento por el sistema 1C: Enterprise.
Los componentes externos se pueden utilizar para resolver una clase de problemas que son difíciles o incluso imposibles de implementar en el lenguaje de programación integrado en 1C: Enterprise. En particular, esta clase incluye tareas que requieren una interacción de bajo nivel con el sistema operativo, por ejemplo, trabajar con equipos específicos.
El sistema 1C: Enterprise utiliza dos tecnologías para crear componentes externos:
  • usando API nativa
  • utilizando tecnología COM
Dadas las restricciones dadas, la diferencia entre las dos tecnologías mencionadas anteriormente es insignificante, por lo que consideraremos el desarrollo de videojuegos utilizando la API nativa. Si es necesario, los desarrollos implementados se pueden aplicar al desarrollo de software informático utilizando tecnología COM y también, con modificaciones menores, para su uso en el sistema 1C: Enterprise con otras opciones operativas distintas al modo de operación de archivos.
estructura VK
El componente externo del sistema 1C: Enterprise se presenta como una biblioteca DLL. El código de la biblioteca describe la clase descendiente IComponentBase. La clase creada debe definir métodos responsables de implementar las funciones del componente externo. Los métodos anulados se describirán con más detalle a continuación a medida que se presente el material.

Lanzar una demostración VK

Tarea:
  1. Ensamble un componente externo suministrado con una suscripción ITS y destinado a demostrar las capacidades principales del mecanismo del componente externo en 1C
  2. Conecte el componente de demostración a la configuración 1C
  3. Asegúrese de que las funciones declaradas funcionen correctamente
Compilacion
La demostración VK se encuentra en el disco de suscripción ITS en el directorio “/VNCOMP82/example/NativeAPI”.
Para crear el VC de demostración usaremos Microsoft Visual Studio 2008. Otras versiones de este producto no admiten el formato de proyecto de Visual Studio utilizado.


Abra el proyecto AddInNative. En la configuración del proyecto, incluimos el directorio con los archivos de encabezado necesarios para construir el proyecto. De forma predeterminada, se encuentran en el disco ITS en el directorio /VNCOMP82/incluir.
El resultado de la construcción es el archivo. /bind/AddInNative.dll. Esta es la biblioteca compilada para conectarse a la configuración 1C.
Conexión de VK a la configuración 1C
Creemos una configuración 1C vacía.
A continuación se muestra el código para el módulo de aplicación administrada.
variable DemoComp; Procedimiento cuando se inicia el sistema() Conecte el componente externo("...\bind\AddInNative.dll", "DemoVK", Tipo de componente externo.Native); DemoComp = Nuevo("AddIn.DemoVK.AddInNativeExtension"); Procedimiento final
Si no se informó ningún error al iniciar la configuración 1C, entonces el VK se conectó correctamente.
Como resultado de ejecutar el código anterior, aparece un objeto en la visibilidad global de la configuración. DemoComp, que tiene propiedades y métodos que están definidos en el código del componente externo.
Demostración de la funcionalidad integrada.
Comprobemos la funcionalidad de la demostración VK. Para hacer esto, intentemos configurar y leer algunas propiedades, llamar a algunos métodos VK y también recibir y procesar el mensaje VK.
La documentación proporcionada en el disco ITS indica la siguiente funcionalidad del VC de demostración:
  1. Gestión del estado del objeto componente
    Métodos: Encender, Apagar
    Propiedades: Incluido
  2. Gestión del temporizador
    Cada segundo, el componente envía un mensaje al sistema 1C: Enterprise con parámetros Componente, Temporizador y una línea de contador de reloj del sistema.
    Métodos: Temporizador de inicio, Detener el temporizador
    Propiedades: Hay un temporizador
  3. Método Mostrar línea de estado, que muestra en la línea de estado el texto pasado al método como parámetros
  4. Método Subir foto. Carga una imagen del archivo especificado y la transfiere al sistema 1C: Enterprise en forma de datos binarios.
Asegurémonos de que estas funciones funcionen. Para hacer esto, ejecute el siguiente código:
variable DemoComp; Procedimiento cuando se inicia el sistema() ConnectExternalComponent(...); DemoComp = Nuevo("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Informe (DemoComp.Enabled); DemoComp.Enable(); Informe (DemoComp.Enabled); DemoComp.StartTimer(); Fin del procedimiento Procedimiento Procesamiento de eventos externos (Fuente, Evento, Datos) Informe (Fuente + " " + Evento + " " + Datos); Procedimiento final
El resultado de ejecutar la configuración se muestra en la imagen.


El panel "Mensajes" muestra los resultados de las llamadas a métodos. DemoComp.Disable() Y Demo.Comp.Enable(). Las líneas siguientes en el mismo panel contienen los resultados del procesamiento de mensajes recibidos de VK - Fuente, Evento Y Datos respectivamente.

Nombre de componente externo personalizado

Tarea: cambiar el nombre del componente externo por uno arbitrario.
La sección anterior utilizó el identificador. AddInNativeExtension, cuyo significado no fue explicado. En este caso AddInNativeExtension- este es el nombre de la extensión.
El código VK define un método. RegistrarExtensiónComo, devolviendo el nombre al sistema 1C: Enterprise, que es necesario para el registro posterior del VK en el sistema. Se recomienda especificar un identificador que revele en cierta medida la esencia del componente externo.
Aquí está el código completo del método. RegistrarExtensiónComo con el nombre de la extensión cambiado:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory) ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) devuelve falso;
En el ejemplo dado, el nombre de VK se cambia a algún nombre. Luego, al conectar VK, debes especificar un nuevo nombre:
DemoComp = Nuevo("AddIn.DemoVK.SomeName");

Ampliando la lista de propiedades VK

Tarea:
  1. Estudiar la implementación de las propiedades VK.
  2. Agregue una propiedad de lectura/escritura de tipo cadena
  3. Agregue una propiedad de cadena de lectura/escritura que almacene el tipo de datos de la última propiedad establecida. No se realiza ninguna acción al establecer el valor de la propiedad

Para determinar las propiedades del componente que se está creando, el desarrollador debe implementar los siguientes métodos en el código de la biblioteca AddInNative.cpp:
Obtener NProps
Devuelve el número de propiedades de esta extensión, 0 si no hay propiedades
BuscarProp
Devuelve el número de serie de la propiedad cuyo nombre se pasa en los parámetros.
Obtener nombre de propiedad
Devuelve el nombre de la propiedad por su número de serie y por el identificador de idioma pasado.
ObtenerPropVal
Devuelve el valor de la propiedad con el número ordinal especificado
Establecer valor de propiedad
Establece el valor de la propiedad con el número ordinal especificado.
EsPropReadable
Devuelve el indicador de legibilidad de la propiedad con el número de secuencia especificado
EsPropWritable
Devuelve el indicador de capacidad de escritura de la propiedad con el número de secuencia especificado


Consideremos la implementación de los métodos de clase anteriores. CAAddInNativo.
En el VC de demostración, se definen 2 propiedades: Incluido Y Hay un temporizador (Está habilitado Y IsTimerPresente).
En el alcance global del código de la biblioteca, se definen dos matrices:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Habilitado", L"Hay un temporizador");
que almacenan nombres de propiedades en ruso e inglés. En el archivo de encabezado ComplementoNativo.h la enumeración se define:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Siempre último);
ePropIsEnabled Y ePropIsTimerPresente, que tienen respectivamente los valores 0 y 1, se utilizan para reemplazar los números de serie de las propiedades con identificadores significativos. ePropLast, que tiene un valor de 2, se utiliza para obtener el número de propiedades (utilizando el método GetNProps). Estos nombres se utilizan únicamente dentro del código del componente y no están disponibles desde el exterior.
Los métodos FindProp y GetPropName realizan búsquedas en matrices. g_PropNames Y g_PropNamesRu.
Para almacenar los valores de los campos en el módulo de la biblioteca, la clase CAddInNative tiene propiedades que almacenan el valor de las propiedades del componente. Métodos ObtenerPropVal Y Establecer valor de propiedad return y establezca el valor de estas propiedades en consecuencia.
Métodos EsPropReadable Y EsPropWritable y volver verdadero o FALSO, dependiendo del número ordinal pasado de la propiedad de acuerdo con la lógica de la aplicación.
Para agregar una propiedad personalizada, necesita:

  1. Agregue el nombre de la propiedad que se agrega a las matrices g_PropNames Y g_PropNamesRu(archivo AddInNative.cpp)
  2. Listar Accesorios(archivo ComplementoNativo.h) antes ePropÚltimo agregue un nombre que identifique de forma única la propiedad que se está agregando
  3. Organice la memoria para almacenar valores de propiedades (cree campos de componentes del módulo que almacenen los valores correspondientes)
  4. Realizar cambios en los métodos. ObtenerPropVal Y Establecer valor de propiedad para interactuar con la memoria asignada en el paso anterior
  5. De acuerdo con la lógica de la aplicación, realice cambios en los métodos. EsPropReadable Y EsPropWritable
Los puntos 1, 2, 5 no necesitan explicación. Los detalles de la implementación de estos pasos se pueden encontrar estudiando el apéndice del artículo.
Démosle nombres a las propiedades de prueba. Prueba Y Tipo de verificación respectivamente. Entonces, como resultado del paso 1, tenemos:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Prueba", L"TestType"); static wchar_t *g_PropNamesRu = (L"Habilitado", L"Hay un temporizador", L"Prueba", L"Verificación de tipo");
Transferir Accesorios se vera como:
enum Props (ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Siempre último);
Para simplificar significativamente el código, usaremos STL C++. En particular, para trabajar con cuerdas. WCHAR, conectemos la biblioteca cuerda.
Para guardar el valor de un método Prueba, definimos en la clase CAAddInNativo en el ámbito de un ámbito privado:
prueba de cadena1;
Para transferir parámetros de cadena entre 1C: Enterprise y componentes externos, se utiliza el administrador de memoria 1C: Enterprise. Echemos un vistazo más de cerca a su trabajo. Las funciones se utilizan para asignar y liberar memoria respectivamente. AllocMemoria Y Memoria libre definido en el archivo ImemoryManager.h. Si es necesario pasar un parámetro de cadena al sistema 1C: Enterprise, el componente externo debe asignarle memoria llamando a la función AllocMemoria. Su prototipo se ve así:
virtual bool ADDIN_API AllocMemory (void** pMemory, ulCountByte largo sin firmar) = 0;
Dónde pMemoria- la dirección del puntero en el que se colocará la dirección del área de memoria asignada,
ulCountByte- tamaño del área de memoria asignada.
Un ejemplo de asignación de memoria para una cadena:
WCHAR_T *t1 = NULL, *prueba = L"TEST_STRING"; int iActualSize = wcslen(prueba1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, prueba1, iActualSize);
Para facilitar el trabajo con tipos de datos de cadena, describiremos la función wstring_to_p. Recibe una cadena wstring como parámetro. El resultado de la función es una estructura llena. variante t. Código de función:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( char* t1; TV_VT(val) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * tamaño de (WCHAR_T)); memcpy (t1, str.c_str(), (str.length()+1) * tamaño de (WCHAR_T)); val -> pstrVal = t1; devolver verdadero)
Luego, la sección de caso correspondiente de la declaración de cambio del método ObtenerPropVal tomará la forma:
caso ePropTest1: wstring_to_p(test1, pvarPropVal); romper;
Método Establecer valor de propiedad:
caso ePropTest1: si (TV_VT(varPropVal)!= VTYPE_PWSTR) devuelve falso; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); romper;
Para implementar la segunda propiedad, definimos un campo de clase CaddInNativo
uint8_t último_tipo;
en el cual guardaremos el tipo del último valor transferido. Para hacer esto, agregue el comando al método CaddInNative::SetPropVal:
último_tipo = TV_VT(varPropVal);
Ahora, al solicitar leer el valor de la segunda propiedad, devolveremos el valor último_tipo, lo que requiere la tarea designada.
Comprobemos la funcionalidad de los cambios realizados.
Para hacer esto, presentemos la apariencia de la configuración 1C de la siguiente manera:
variable DemoComp; Procedimiento cuando se inicia el sistema() Conecte el componente externo("...", "DemoVK", Tipo de componente externo.Nativo); DemoComp = Nuevo("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Informe(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Informe(Cadena(DemoComp.Test)); DemoComp.Test = "Petya"; Informe(Cadena(DemoComp.Test)); Informe(String(DemoComp.TypeCheck)); Procedimiento final
Como resultado del lanzamiento, recibiremos una secuencia de mensajes:
3
Vasya
Pedro
22

El segundo y tercer mensaje son el resultado de leer la propiedad establecida en el paso anterior. El primer y segundo mensaje contienen el código de tipo de la última propiedad establecida. 3 corresponde a un valor entero, 22 a un valor de cadena. La correspondencia de tipos y sus códigos se establece en el fichero. tipos.h, que se encuentra en el disco ITS.

Ampliando la lista de métodos.

Tarea:
  1. Amplíe la funcionalidad del componente externo con la siguiente funcionalidad:
  2. Explore formas de implementar métodos de componentes externos
  3. Agregar un método de función Función1, que toma dos cadenas (“Parámetro1” y “Parámetro2”) como parámetro. El resultado es una cadena como: “Comprobando. Parámetro1, Parámetro2"
  4. Asegúrese de que los cambios que realice funcionen.

Para definir los métodos del componente que se está creando, el desarrollador debe implementar los siguientes métodos en el código de la biblioteca AddInNative:
ObtenerNMétodos, Método de búsqueda, Obtener nombre del método
Diseñado para obtener el número correspondiente de métodos, busque el número y nombre del método. Similar a los métodos correspondientes para propiedades.
ObtenerNParams
Devuelve el número de parámetros del método con el número de secuencia especificado; si un método con este número está ausente o no tiene parámetros, devuelve 0
ObtenerParamDefValue
Devuelve el valor predeterminado del parámetro especificado del método especificado
HasRetVal
Devuelve la bandera de si el método con el valor de retorno ordinal especificado tiene un valor de retorno: verdadero para métodos con un valor de retorno y FALSO de lo contrario
llamadaAsProc
FALSO, se produce un error de tiempo de ejecución y se finaliza la ejecución del módulo 1C: Enterprise. La memoria para la matriz de parámetros la asigna y libera 1C: Enterprise.
llamada como función
Ejecuta el método con el número de secuencia especificado. Si el método regresa FALSO, se produce un error de tiempo de ejecución y se finaliza la ejecución del módulo 1C: Enterprise. La memoria para la matriz de parámetros la asigna 1C: Enterprise. Si el valor de retorno es una cadena o un tipo de datos binarios, el componente asigna memoria con la función AllocMemoria administrador de memoria, escribe datos allí y almacena esta dirección en el campo correspondiente de la estructura. 1C: La empresa liberará esta memoria llamando Memoria libre.
Una descripción completa de los métodos, incluida una lista de parámetros, se describe en detalle en la documentación suministrada en el disco ITS.
Consideremos la implementación de los métodos descritos anteriormente.
En el código del componente, se definen dos matrices:
static wchar_t *g_MethodNames = (L"Activar", L"Desactivar", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Activar", L"Desactivar", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
y enumeración:
Métodos enum (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Siempre último);
Se utilizan en funciones. ObtenerNMétodos, Método de búsqueda Y Obtener nombre del método, por analogía con la descripción de propiedades.
Métodos ObtenerNParams, ObtenerParamDefValue, HasRetVal implemente el interruptor, dependiendo de los parámetros pasados ​​y la lógica de la aplicación, devuelva el valor requerido. Método HasRetVal en su código tiene una lista de los únicos métodos que pueden devolver un resultado. Por ellos regresa verdadero. Para todos los métodos de acero devoluciones FALSO.
Métodos llamadaAsProc Y llamada como función contener código directamente ejecutable del método.
Para agregar un método que solo se puede llamar como una función, debe realizar los siguientes cambios en el código fuente del componente externo:
  1. Agregar nombre de método a matrices g_Nombresdemétodos Y g_MethodNamesRu(archivo AddInNative.cpp)
  2. Agregue un identificador de método significativo a la enumeración de Métodos (archivo ComplementoNativo.h)
  3. Realizar cambios en el código de función. ObtenerNParams según la lógica del programa
  4. Si es necesario, realice cambios en el código del método. ObtenerParamDefValue, si desea utilizar los valores predeterminados de los parámetros del método.
  5. Realizar cambios en la función. HasRetVal
  6. Realizar cambios en la lógica de las funciones. llamadaAsProc o llamada como función, colocando allí el código directamente ejecutable del método
Presentemos las matrices. g_Nombresdemétodos Y g_MethodNamesRu, además de enumerar Métodos a la forma:
static wchar_t *g_MethodNames = (L"Activar", L"Desactivar", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Prueba"); static wchar_t *g_MethodNamesRu = (L"Activar", L"Desactivar", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Prueba");

Métodos de enumeración (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Siempre último);
Editemos la función. Obtener NProps para que devuelva el número de parámetros del método “Test”:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( caso eMethShowInStatusLine: devuelve 1; caso eMethLoadPicture: devuelve 1; caso eMethTest: devuelve 2; predeterminado: devuelve 0; ) devuelve 0; )
Hagamos cambios en la función:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( caso eMethEnable: caso eMethDisable: caso eMethShowInStatusLine: caso eMethStartTimer : caso eMethStop Temporizador: caso eMethTest : // No hay valores de parámetros por defecto break default: return false;
Gracias a la línea agregada.
caso eMethTest:
si faltan uno o más argumentos, los parámetros correspondientes tendrán un valor vacío ( VTYPE_EMPTY). Si necesita un valor predeterminado para un parámetro, debe configurarlo en la sección prueba de metanfetamina declaración de cambio de función CAAddInNative::GetParamDefValue.
Dado que el método de prueba puede devolver un valor, es necesario realizar cambios en el código de la función. HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( caso eMethLoadPicture: caso eMethTest: devuelve verdadero; predeterminado: devuelve falso; ) devuelve falso; )
Y agregue el código ejecutable del método a la función. llamada como función:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( case eMethLoadPicture: ... break; case eMethTest: if (!lSizeArray || !paParams) devuelve falso; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstring_to_p(std::wstring(s1+s2), pvarRetValue; ;
Compilemos el componente y llevemos el código de configuración al formulario:
variable DemoComp; Procedimiento cuando se inicia el sistema() Conecte el componente externo("...", "DemoVK", Tipo de componente externo.Nativo); DemoComp = Nuevo("AddIn.DemoVK.SomeName"); carril = DemoComp.Test("Hola", "¡Mundo!"); Informe(por); Procedimiento final
Luego de iniciar la configuración, recibiremos el mensaje: “¡Hola mundo!”, que indica que el método funcionó exitosamente.

Temporizador

Tarea:
  1. Estudie la implementación del temporizador en la demostración VK.
  2. Modifique el método "StartTimer" agregando la capacidad de pasar en los parámetros el intervalo de respuesta del temporizador (en milisegundos)
  3. Asegúrese de que los cambios que realice funcionen.

En WinAPI, puedes usar el mensaje para trabajar con el tiempo. WM_TIMER. Este mensaje se enviará a su programa en el intervalo de tiempo que configuró al crear el temporizador.
Para crear un temporizador, use la función Establecer temporizador:
UINT SetTimer(HWND hWnd, // descriptor de ventana UINT nIDevent, // identificador del temporizador (número) UINT nElapse, // retardo TIMERPROC lpTimerFunc); // puntero a la función
El sistema operativo enviará un mensaje. WM_TIMER en el programa con el intervalo especificado en el argumento ntranscurrir(en milisegundos). En el último parámetro puede especificar una función que se ejecutará cada vez que se active el temporizador. El encabezado de esta función debería verse así (el nombre puede ser cualquier cosa):
anular __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Consideremos la implementación de un temporizador en el VC de demostración.
Dado que estamos considerando el proceso de desarrollo de un componente externo para la familia de sistemas operativos Windows, no consideraremos la implementación del temporizador en otros sistemas operativos. Para el sistema operativo GNU/Linux, en particular, la implementación diferirá en la sintaxis de la función. Establecer temporizador Y TemporizadorProc.
En el código de ejecución el método se llama Establecer temporizador, al que se pasa la función MiTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
El ID del temporizador creado se coloca en una variable. m_uiTimer para poder desactivarlo más tarde.
Función MiTimerProc como sigue:
VOID CALLBACK MyTimerProc(HWND hwnd, // identificador de ventana para mensajes del temporizador UINT uMsg, // mensaje WM_TIMER UINT idEvent, // identificador del temporizador DWORD dwTime // hora actual del sistema) ( if (!pAsyncEvent) return; wchar_t *who = L "ComponentNative", *what = L"Timer"; wchar_t *wstime = new wchar_t; if (wstime) ( wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); pAsyncEvent->ExternalEvent(quién , qué, wstime); eliminar wstime;
La esencia de la función es que el método se llama. Evento externo, que envía un mensaje al sistema 1C: Enterprise.
Para ampliar la funcionalidad del método. Temporizador de inicio Hagamos lo siguiente:
Modificando el código del método ObtenerNParams para que sea por el método eMethStartTimer valor devuelto 1:
caso eMethStartTimer: retorno 1;
Aquí está el código del método. llamadaAsProc a la forma:
caso eMethStartTimer: if (!lSizeArray || TV_VT(paParams) != VTYPE_I4 || TV_I4(paParams)<= 0) return false; pAsyncEvent = m_iConnect; #ifndef __linux__ m_uiTimer = ::SetTimer(NULL,0,TV_I4(paParams),(TIMERPROC)MyTimerProc); #else // код для GNU/Linux #endif break;
Ahora verifiquemos la funcionalidad. Para ello escribiremos el código en el módulo de aplicación gestionada de la configuración:
variable DemoComp; Procedimiento cuando se inicia el sistema() Conecte el componente externo("...", "DemoVK", Tipo de componente externo.Nativo); DemoComp = Nuevo("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Procedimiento final
Luego de iniciar la configuración, el programa recibirá mensajes a intervalos de 2 segundos, lo que indica que el temporizador está funcionando correctamente.

Interacción con el sistema 1C: Enterprise

Para interactuar entre el componente externo y el sistema 1C: Enterprise, los métodos de la clase IAddInDefBase, descritos en el archivo AddInDefBase.h. Te enumeramos los más utilizados:
Generando un mensaje de error
bool virtual ADDIN_API AddError (código w corto sin firmar, fuente constante WCHAR_T*, descripción constante WCHAR_T*, código largo)
código w, código- códigos de error (puede encontrar una lista de códigos de error con descripciones en el disco ITS)
fuente- fuente de error
descripción- Error de descripción
Enviar un mensaje al sistema 1C: Enterprise
virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszFuente- fuente del mensaje
wszMensaje- Mensaje de texto
wszDatos- datos transmitidos
La interceptación de mensajes se lleva a cabo mediante el procedimiento de procesamiento de eventos externos.
Registro de un componente externo en el sistema 1C: Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
nombre de perfil wsz- Nombre del componente.
Estos métodos son suficientes para una interacción completa entre VK y 1C. Para recibir datos de un componente externo del sistema 1C: Enterprise y viceversa, el componente externo envía un mensaje especial, que a su vez es interceptado por el sistema 1C y, si es necesario, llama a los métodos del componente externo para transmitir datos. .

Tipo de datos variante

Al intercambiar datos entre el componente externo y el sistema 1C: Enterprise, se utiliza el tipo de datos tVariant. Se describe en el archivo type.h, que se puede encontrar en el disco ITS:
struct _tVariant ( _ANONYMOUS_UNION union ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; unsigned int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ushortVal; uint32_t ulVal; uint64_t; int32_t errCode; float fltVal; bVal;wchar_t wchVal;estructura _tVal; struct tm tmVal; void* pInterfaceVal; __VARIANT_NAME_2/*iface*/; pstrVal; uint32_t strLen; //recuento de bytes) __VARIANT_NAME_3/*str*/; 1 ; matriz dimensional en pvarVal TYPEVAR vt);
Tipo variante t es una estructura que incluye:
  • mezcla (unión) destinada directamente al almacenamiento de datos
  • identificador de tipo de datos
En general, trabajar con variables de tipo variante t ocurre de acuerdo con el siguiente algoritmo:
  1. Determinar el tipo de datos almacenados actualmente en una variable
  2. Accede al campo de mezcla correspondiente para acceder directamente a los datos
Usando el tipo variante t simplifica significativamente la interacción de 1C: sistema empresarial y componentes externos

Solicitud

El directorio "ejemplos" contiene ejemplos para el artículo.
ejemplos/1 - iniciar el componente de demostración
ejemplos/2 - demostración de la expansión de la lista de propiedades
ejemplos/3 - demostración de cómo ampliar la lista de métodos
Cada directorio contiene un proyecto VS 2008 y una configuración 1C lista para usar.