Nouvelles versions de « 1C : Trade Management » : mise à jour sans développement. Résoudre les problèmes d'enregistrement des composants externes dans le terminal Extension de la liste des méthodes
Une nouvelle version de configuration a été publiée le 23 octobre "1C : Gestion du Commerce". Encore une fois, la mise à jour incluait des modifications apportées à VetIS, EGAIS et la fonctionnalité globale de la configuration n'était presque pas affectée.
Qu'est ce qui a changé?
Si vous regardez la structure des modifications incluses dans la dernière version de configuration "1C : Gestion du Commerce", alors plus de la moitié est une mise à jour pour EGAIS, VetIS, et seules quelques lignes dans la description de la version sont consacrées à l'extension des fonctionnalités du produit logiciel, qui ne sont stipulées par aucun acte législatif.
Sections où des changements ont eu lieu :
dans la vente au détail, un support a été ajouté pour la lecture d'un nouveau type de code-barres bidimensionnel des timbres spéciaux d'accise et fédéraux contenant l'identifiant numérique EGAIS ;
l'intégration avec le système de contrôle vétérinaire (VetIS) a été améliorée ;
l'échange avec le système EGAIS a été amélioré ;
de nouvelles fonctionnalités du service d'échange électronique de documents ont été ajoutées ;
des améliorations ont été apportées au service 1C : Business Network ;
L'intégration avec Yandex.Checkout a été améliorée.
En termes de fonctionnalité générale, plusieurs modifications ont été apportées au bloc de planification et de trésorerie. Et des ajouts traditionnellement constants à la comptabilité TVA.
Dans le même temps, la dernière version de configuration actuelle "1C : Gestion du Commerce" ne fait pas exception - désormais, le développement de la configuration pour la comptabilité opérationnelle vise principalement à résoudre les problèmes qui résultent de la réglementation législative dans le domaine du commerce. Il est logique que le respect des exigences réglementaires devienne une priorité plus élevée et, en fin de compte, détermine l'orientation du développement de la solution logicielle dans son ensemble.
La comptabilité opérationnelle est-elle en train de se réglementer ?
Configuration traditionnelle "1C : Gestion du Commerce" utilisé pour automatiser la comptabilité opérationnelle. Parallèlement, en lien avec "1C : Comptabilité" il était d'usage de « télécharger » toutes les exigences relatives à la modification des fonctionnalités standard dans "1C:TU", pour maintenir la capacité de mettre à jour le programme de comptabilité avec un minimum d'effort.
Compte tenu du volume de documents réglementaires relatifs à la comptabilité opérationnelle dans le commerce et du reflet de ces exigences dans la configuration standard, il existe des raisons d'adopter une approche plus prudente pour apporter des modifications à la fonctionnalité standard de la configuration commerciale. Par exemple, des problèmes d'échange avec le système Mercury peuvent, sinon paralyser les activités d'un certain nombre d'entreprises, conduire au minimum à de longs temps d'arrêt.
Comme l'une des options de solution, nous pouvons envisager d'utiliser le mécanisme d'extension, d'autant plus que 1C utilise activement cette fonctionnalité. Bien entendu, cette approche nécessitera un travail supplémentaire de la part des développeurs. Mais c’est la manière optimale de prendre en charge les changements dans les configurations modernes.
Une répartition plus radicale des fonctionnalités entre la configuration standard sera "1C : Gestion du Commerce" et certains systèmes comptables ou analytiques externes. Ici, 1C a encore une fois fait suffisamment pour résoudre efficacement ces types de problèmes au niveau de la plate-forme.
Dans tous les cas, lors de la conception des systèmes comptables d'entreprise et de la répartition des fonctionnalités entre les configurations, vous devez garder à l'esprit : il est possible que vous deviez mettre à jour "1C : Gestion du Commerce" il faudra le faire, sinon aussi souvent que "1C : Comptabilité", et certainement pas 1 à 2 fois par an, comme tant de personnes le faisaient auparavant.
- Didacticiel
Introduction
Cet article donne une idée du fonctionnement des composants externes dans le système 1C : Enterprise.Le processus de développement d'un composant externe pour le système 1C : Enterprise version 8.2, fonctionnant sous le système d'exploitation Windows avec un mode de fonctionnement de fichier, sera présenté. Cette option est utilisée dans la plupart des solutions conçues pour les petites entreprises. VK sera implémenté dans le langage de programmation C++.
Composants externes "1C : Entreprise"
« 1C : Enterprise » est un système extensible. Pour étendre les fonctionnalités du système, des composants externes (EC) sont utilisés. Du point de vue du développeur, un VC est un objet externe qui possède des propriétés et des méthodes, et peut également générer des événements à traiter par le système 1C : Enterprise.Des composants externes peuvent être utilisés pour résoudre une classe de problèmes difficiles voire impossibles à mettre en œuvre dans le langage de programmation intégré à 1C : Enterprise. En particulier, cette classe comprend des tâches qui nécessitent une interaction de bas niveau avec le système d'exploitation, par exemple pour travailler avec des équipements spécifiques.
Le système 1C : Enterprise utilise deux technologies pour créer des composants externes :
- en utilisant l'API native
- utilisant la technologie COM
Structure VK
Le composant externe du système 1C : Enterprise se présente sous la forme d'une bibliothèque DLL. Le code de la bibliothèque décrit la classe descendante IComponentBase. La classe créée doit définir les méthodes chargées d'implémenter les fonctions du composant externe. Les méthodes remplacées seront décrites plus en détail ci-dessous au fur et à mesure de la présentation du matériel.Lancer une démo VK
Tâche:- Assembler un composant externe fourni avec un abonnement ITS et destiné à démontrer les principales capacités du mécanisme de composant externe en 1C
- Connectez le composant de démonstration à la configuration 1C
- Assurez-vous que les fonctions déclarées fonctionnent correctement
Compilation
Le VK de démonstration se trouve sur le disque d'abonnement ITS dans le répertoire « /VNCOMP82/example/NativeAPI ».Pour créer la démo VC, nous utiliserons Microsoft Visual Studio 2008. Les autres versions de ce produit ne prennent pas en charge le format de projet Visual Studio utilisé.
Ouvrez le projet AddInNative. Dans les paramètres du projet, nous incluons le répertoire avec les fichiers d'en-tête nécessaires à la construction du projet. Par défaut, ils se trouvent sur le disque ITS dans le répertoire /VNCOMP82/inclure.
Le résultat de la construction est le fichier /bind/AddInNative.dll. Il s'agit de la bibliothèque compilée pour se connecter à la configuration 1C.
Connexion de VK à la configuration 1C
Créons une configuration 1C vide.Vous trouverez ci-dessous le code du module d'application géré.
variable DémoComp ; Procédure au démarrage du système() Connectez le composant externe ("...\bind\AddInNative.dll", "DemoVK", Type de composant externe.Native); DemoComp = Nouveau("AddIn.DemoVK.AddInNativeExtension"); Fin de la procédure
Si aucune erreur n'a été signalée lors du démarrage de la configuration 1C, le VK a été connecté avec succès.
Suite à l'exécution du code ci-dessus, un objet apparaît dans la visibilité globale de la configuration DémoComp, qui possède des propriétés et des méthodes définies dans le code du composant externe.
Démonstration de la fonctionnalité intégrée
Vérifions la fonctionnalité de la démo VK. Pour ce faire, essayons de définir et de lire certaines propriétés, d'appeler certaines méthodes VK, et également de recevoir et de traiter le message VK.La documentation fournie sur le disque ITS indique les fonctionnalités suivantes du VC de démonstration :
- Gestion de l'état des objets de composants
Méthodes : Allumer, Éteindre
Propriétés: Inclus - Gestion du minuteur
Chaque seconde, le composant envoie un message au système 1C : Entreprise avec des paramètres Composant, Minuteur et une ligne de compteur d'horloge système.
Méthodes : Minuterie de démarrage, Arrêter la minuterie
Propriétés: Il y a une minuterie - Méthode ShowInStatusLine, qui affiche le texte passé à la méthode en tant que paramètres dans la barre d'état
- Méthode Charger une photo. Charge une image à partir du fichier spécifié et la transfère vers le système 1C : Enterprise sous forme de données binaires.
variable DémoComp ; Procédure au démarrage du système() ConnectExternalComponent(...); DemoComp = Nouveau("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Rapport (DemoComp.Enabled); DemoComp.Enable(); Rapport (DemoComp.Enabled); DemoComp.StartTimer(); Fin de procédure Procédure Traitement des événements externes (Source, Événement, Données) Rapport (Source + " " + Événement + " " + Données); Fin de la procédure
Le résultat de l'exécution de la configuration est affiché dans l'image
Le panneau « Messages » affiche les résultats des appels de méthode DemoComp.Disable() Et Démo.Comp.Enable(). Les lignes suivantes dans le même panneau contiennent les résultats du traitement des messages reçus de VK - Source, Événement Et Données respectivement.
Nom du composant externe personnalisé
Tâche : Remplacez le nom du composant externe par un nom arbitraire.La section précédente utilisait l'identifiant AddInNativeExtension, dont la signification n’a pas été expliquée. Dans ce cas AddInNativeExtension- c'est le nom de l'extension.
Le code VK définit une méthode EnregistrerExtensionAs, renvoyant le nom au système 1C : Entreprise, ce qui est nécessaire pour l'enregistrement ultérieur du VK dans le système. Il est recommandé de spécifier un identifiant qui révèle dans une certaine mesure l'essence du composant externe.
Voici le code complet de la méthode EnregistrerExtensionAs avec le nom de l'extension modifié :
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, wsExtension, iActualSize); return true; ) return false; )
Dans l'exemple donné, le nom VK est remplacé par UnNom. Ensuite, lors de la connexion de VK, vous devez spécifier un nouveau nom :
DemoComp = Nouveau("AddIn.DemoVK.SomeName");
Extension de la liste des propriétés VK
Tâche:- Étudier l'implémentation des propriétés VK
- Ajouter une propriété en lecture/écriture de type chaîne
- Ajoutez une propriété de chaîne en lecture/écriture qui stocke le type de données du dernier jeu de propriétés. Aucune action n'est entreprise lors de la définition de la valeur de la propriété
Pour déterminer les propriétés du composant en cours de création, le développeur doit implémenter les méthodes suivantes dans le code de la bibliothèque AddInNative.cpp :
ObtenirNProps
Renvoie le nombre de propriétés de cette extension, 0 s'il n'y a pas de propriétés
RechercherProp
Renvoie le numéro de série de la propriété dont le nom est passé en paramètres
ObtenirNomProp
Renvoie le nom de la propriété par son numéro de série et par l'identifiant de langue transmis
ObtenirPropVal
Renvoie la valeur de la propriété avec le numéro ordinal spécifié
SetPropVal
Définit la valeur de la propriété avec le numéro ordinal spécifié
IsPropReadable
Renvoie l'indicateur de lisibilité de la propriété avec le numéro de séquence spécifié
IsPropWritable
Renvoie l'indicateur d'écriture de la propriété avec le numéro de séquence spécifié
Considérons l'implémentation des méthodes de classe ci-dessus CADdInNative.
Dans la démo VC, 2 propriétés sont définies : Inclus Et Il y a une minuterie (Est autorisé Et IsTimerPresent).
Dans la portée globale du code de la bibliothèque, deux tableaux sont définis :
statique wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Activé", L"Il y a une minuterie");
qui stockent les noms de propriétés russes et anglais. Dans le fichier d'en-tête AddInNative.h l'énumération est définie :
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Toujours dernier );
ePropIsEnabled Et ePropIsTimerPresent, ayant respectivement les valeurs 0 et 1, sont utilisés pour remplacer les numéros de série des propriétés par des identifiants significatifs. ePropLast, qui a la valeur 2, permet d'obtenir le nombre de propriétés (à l'aide de la méthode GetNProps). Ces noms sont utilisés uniquement dans le code du composant et ne sont pas disponibles de l'extérieur.
Les méthodes FindProp et GetPropName effectuent des recherches dans des tableaux g_PropNames Et g_PropNamesRu.
Pour stocker les valeurs des champs dans le module bibliothèque, la classe CADdInNative possède des propriétés qui stockent la valeur des propriétés du composant. Méthodes ObtenirPropVal Et SetPropVal return et définissez la valeur de ces propriétés en conséquence.
Méthodes IsPropReadable Et IsPropWritable et retour vrai ou FAUX, en fonction du numéro ordinal transmis de la propriété conformément à la logique d'application.
Pour ajouter une propriété personnalisée, vous devez :
- Ajouter le nom de la propriété ajoutée aux tableaux g_PropNames Et g_PropNamesRu(déposer AddInNative.cpp)
- Lister Accessoires(déposer AddInNative.h) avant ePropLast ajouter un nom qui identifie de manière unique la propriété ajoutée
- Organiser la mémoire pour stocker les valeurs des propriétés (créer des champs de composants de module qui stockent les valeurs correspondantes)
- Apporter des modifications aux méthodes ObtenirPropVal Et SetPropVal pour interagir avec la mémoire allouée à l'étape précédente
- Conformément à la logique applicative, apporter des modifications aux méthodes IsPropReadable Et IsPropWritable
Donnons des noms aux propriétés du test Test Et Vérification du type respectivement. Ensuite, suite à l’étape 1, nous avons :
wchar_t statique *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Activé", L"Il y a une minuterie", L"Test", L"Vérification de type");
Transfert Accessoires ressemblera:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Toujours dernier );
Pour simplifier considérablement le code, nous utiliserons STL C++. En particulier pour travailler avec des chaînes WCHAR, connectons la bibliothèque chaîne de caractères.
Pour enregistrer une valeur de méthode Test, on définit dans la classe CADdInNative dans le cadre d'un domaine privé :
test de chaîne1 ;
Pour transférer les paramètres de chaîne entre 1C : Entreprise et les composants externes, le gestionnaire de mémoire 1C : Entreprise est utilisé. Regardons de plus près son travail. Les fonctions sont utilisées respectivement pour allouer et libérer de la mémoire AllocMémoire Et Mémoire libre défini dans le fichier ImemoryManager.h. S'il est nécessaire de passer un paramètre chaîne au système 1C : Entreprise, le composant externe doit lui allouer de la mémoire en appelant la fonction AllocMémoire. Son prototype ressemble à ceci :
bool virtuel ADDIN_API AllocMemory (void** pMemory, long ulCountByte non signé) = 0 ;
Où pMémoire- l'adresse du pointeur dans lequel sera placée l'adresse de la zone mémoire allouée,
ulCountByte- la taille de la zone mémoire allouée.
Un exemple d'allocation de mémoire pour une chaîne :
WCHAR_T *t1 = NULL, *test = L"TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
Pour faciliter le travail avec les types de données chaîne, nous décrirons la fonction wstring_to_p. Il reçoit une chaîne wstring en paramètre. Le résultat de la fonction est une structure remplie tVariante. Code de fonction :
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) * sizeof(WCHAR_T)); memcpy(t1, str.c_str(), (str.length()+1) * sizeof(WCHAR_T)); val -> pstrVal = t1; val -> strLen = str.length(); renvoie vrai ; )
Ensuite, la section case correspondante de l'instruction switch de la méthode ObtenirPropVal prendra la forme :
cas ePropTest1 : wstring_to_p(test1, pvarPropVal); casser;
Méthode SetPropVal:
cas ePropTest1 : if (TV_VT(varPropVal) != VTYPE_PWSTR) renvoie false ; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); casser;
Pour implémenter la deuxième propriété, nous définissons un champ de classe CaddInNatif
uint8_t dernier_type ;
dans lequel nous enregistrerons le type de la dernière valeur transférée. Pour ce faire, ajoutez la commande à la méthode CaddInNative::SetPropVal :
last_type = TV_VT(varPropVal);
Désormais, lors de la demande de lecture de la valeur de la deuxième propriété, nous renverrons la valeur dernier_type, ce que requiert la tâche désignée.
Vérifions la fonctionnalité des modifications apportées.
Pour ce faire, présentons l'apparence de la configuration 1C comme suit :
variable DémoComp ; Procédure au démarrage du système() Connecter le composant externe("...", "DemoVK", Type de composant externe.Native); DemoComp = Nouveau("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1 ; Rapport (String (DemoComp.TypeCheck)); DemoComp.Test = "Vasya" ; Rapport (String (DemoComp.Test)); DemoComp.Test = "Petya" ; Rapport (String (DemoComp.Test)); Rapport (String (DemoComp.TypeCheck)); Fin de la procédure
À la suite du lancement, nous recevrons une séquence de messages :
3
Vassia
Pierre
22
Les deuxième et troisième messages sont le résultat de la lecture de la propriété définie à l'étape précédente. Les premier et deuxième messages contiennent le code de type du dernier jeu de propriétés. 3 correspond à une valeur entière, 22 à une valeur chaîne. La correspondance des types et de leurs codes est établie dans le dossier types.h, qui se trouve sur le disque ITS.
Élargir la liste des méthodes
Tâche:- Étendez les fonctionnalités du composant externe avec les fonctionnalités suivantes :
- Explorer les moyens d'implémenter des méthodes de composants externes
- Ajouter une méthode de fonction Fonction1, qui prend deux chaînes (« Parameter1 » et « Parameter2 ») comme paramètre. Le résultat est une chaîne du type : « Vérification. Paramètre1, Paramètre2"
- Assurez-vous que les modifications que vous apportez fonctionnent.
Pour définir les méthodes du composant en cours de création, le développeur doit implémenter les méthodes suivantes dans le code de la bibliothèque AddInNative :
ObtenirNMéthodes, Méthode de recherche, ObtenirNomMéthode
Conçu pour obtenir le nombre correspondant de méthodes, recherchez le numéro et le nom de la méthode. Semblable aux méthodes correspondantes pour les propriétés
ObtenirNParams
Renvoie le nombre de paramètres de méthode avec le numéro de séquence spécifié ; si une méthode avec ce numéro est absente ou n'a pas de paramètres, renvoie 0
GetParamDefValue
Renvoie la valeur par défaut du paramètre spécifié de la méthode spécifiée
HasRetVal
Renvoie l'indicateur indiquant si la méthode avec la valeur de retour ordinale spécifiée a une valeur de retour : true pour les méthodes avec une valeur de retour et FAUX sinon
AppelAsProc
FAUX, une erreur d'exécution se produit et l'exécution du module 1C : Enterprise est terminée. La mémoire pour le tableau de paramètres est allouée et libérée par 1C : Entreprise.
AppelAsFunc
Exécute la méthode avec le numéro de séquence spécifié. Si la méthode renvoie FAUX, une erreur d'exécution se produit et l'exécution du module 1C : Enterprise est terminée. La mémoire pour le tableau de paramètres est allouée par 1C : Entreprise. Si la valeur de retour est un type de données chaîne ou binaire, le composant alloue de la mémoire avec la fonction AllocMémoire gestionnaire de mémoire, y écrit des données et stocke cette adresse dans le champ correspondant de la structure. 1C : L'entreprise libérera cette mémoire en appelant Mémoire libre.
Une description complète des méthodes, incluant une liste de paramètres, est décrite en détail dans la documentation fournie sur le disque ITS.
Considérons la mise en œuvre des méthodes décrites ci-dessus.
Dans le code du composant, deux tableaux sont définis :
wchar_t statique *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); wchar_t statique *g_MethodNamesRu = (L"Activer", L"Désactiver", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
et dénombrement :
méthodes enum ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Toujours dernier );
Ils sont utilisés dans les fonctions ObtenirNMéthodes, Méthode de recherche Et ObtenirNomMéthode, par analogie avec la description des propriétés.
Méthodes ObtenirNParams, GetParamDefValue, HasRetVal implémentez le commutateur, en fonction des paramètres transmis et de la logique de l'application, renvoyez la valeur requise. Méthode HasRetVal dans son code, il contient une liste des seules méthodes pouvant renvoyer un résultat. Pour eux, il revient vrai. Pour toutes les méthodes de retour en acier FAUX.
Méthodes AppelAsProc Et AppelAsFunc contiennent le code directement exécutable de la méthode.
Pour ajouter une méthode qui ne peut être appelée qu'en tant que fonction, vous devez apporter les modifications suivantes au code source du composant externe :
- Ajouter le nom de la méthode aux tableaux g_MethodNames Et g_MethodNamesRu(déposer AddInNative.cpp)
- Ajoutez un identifiant de méthode significatif à l'énumération Méthodes (fichier AddInNative.h)
- Apporter des modifications au code de fonction ObtenirNParams selon la logique du programme
- Si nécessaire, apportez des modifications au code de la méthode GetParamDefValue, si vous souhaitez utiliser les valeurs par défaut des paramètres de la méthode.
- Apporter des modifications à la fonction HasRetVal
- Apporter des modifications à la logique des fonctions AppelAsProc ou AppelAsFunc, en y plaçant le code directement exécutable de la méthode
wchar_t statique *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); wchar_t statique *g_MethodNamesRu = (L"Activer", L"Désactiver", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");
Méthodes Enum ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Toujours dernier );
Modifions la fonction ObtenirNProps pour qu'il renvoie le nombre de paramètres de la méthode « Test » :
long CADdInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine : return 1 ; case eMethLoadPicture : return 1 ; case eMethTest : return 2 ; par défaut : return 0 ; ) return 0 ; )
Apportons des modifications à la fonction :
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case eMethEnable : case eMethDisable : case eMethShowInStatusLine : case eMethStartTime r : cas eMethStopTimer : cas eMethTest : // Il n'y a pas de valeurs de paramètre par défaut break ; par défaut : return false ; ) return false ; )
Merci à la ligne ajoutée
cas eMethTest :
s'il manque un ou plusieurs arguments, les paramètres correspondants auront une valeur vide ( VTYPE_EMPTY). Si vous avez besoin d'une valeur par défaut pour un paramètre, vous devez la définir dans la section eMethTest instruction de changement de fonction CADdInNative :: GetParamDefValue.
Étant donné que la méthode Test peut renvoyer une valeur, vous devez apporter des modifications au code de fonction HasRetVal:
bool CAAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture : case eMethTest : return true ; par défaut : return false ; ) return false ; )
Et ajoutez le code exécutable de la méthode à la fonction AppelAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( case eMethLoadPicture : ... break ; case eMethTest : si (!lSizeArray || !paParams) renvoie false ; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; wstring_to_p(std::wstring(s1+s2), pvarRetValue); ret = true ; pause; ) retour ret; )
Compilons le composant et amenons le code de configuration sous la forme :
variable DémoComp ; Procédure au démarrage du système() Connecter le composant externe("...", "DemoVK", Type de composant externe.Native); DemoComp = Nouveau("AddIn.DemoVK.SomeName"); lane = DemoComp.Test("Bonjour", "Monde !"); Rapport(par); Fin de la procédure
Après avoir lancé la configuration, nous recevrons le message : « Hello, World ! », qui indique que la méthode a fonctionné avec succès.
Minuteur
Tâche:- Étudiez l'implémentation de la minuterie dans la démo VK
- Modifier la méthode « StartTimer » en ajoutant la possibilité de passer en paramètres l'intervalle de réponse du timer (en millisecondes)
- Assurez-vous que les modifications que vous apportez fonctionnent.
Dans WinAPI, vous pouvez utiliser le message pour travailler avec le temps WM_TIMER. Ce message sera envoyé à votre programme à l'intervalle de temps que vous avez défini lors de la création du minuteur.
Pour créer un timer, utilisez la fonction Régler la minuterie:
UINT SetTimer(HWND hWnd, // descripteur de fenêtre UINT nIDevent, // identifiant du timer (numéro) UINT nElapse, // délai TIMERPROC lpTimerFunc); // pointeur vers la fonction
Le système d'exploitation enverra un message WM_TIMER dans le programme avec l'intervalle spécifié dans l'argument nElapse(en millisecondes). Dans le dernier paramètre, vous pouvez spécifier une fonction qui sera exécutée à chaque déclenchement du minuteur. L'en-tête de cette fonction devrait ressembler à ceci (le nom peut être n'importe quoi) :
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Considérons l'implémentation d'une minuterie dans la démo VC.
Puisque nous envisageons le processus de développement d'un composant externe pour la famille des systèmes d'exploitation Windows, nous n'envisagerons pas l'implémentation du minuteur dans d'autres systèmes d'exploitation. Pour le système d'exploitation GNU/Linux, en particulier, l'implémentation différera dans la syntaxe de la fonction Régler la minuterie Et MinuterieProc.
Le code exécutable appelle la méthode Régler la minuterie, auquel la fonction est passée MonProcMinuterie:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
L'ID du timer créé est placé dans une variable m_uiTimer afin qu'il puisse être désactivé plus tard.
Fonction MonProcMinuterie comme suit:
VOID CALLBACK MyTimerProc(HWND hwnd, // handle de fenêtre pour les messages de minuterie UINT uMsg, // message WM_TIMER UINT idEvent, // identifiant de minuterie DWORD dwTime // heure système actuelle) ( 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(who , quoi, wstime); supprimer wstime; ) )
L'essence de la fonction est que la méthode s'appelle Événement Externe, qui envoie un message au système 1C : Enterprise.
Pour étendre les fonctionnalités de la méthode Minuterie de démarrage Faisons ce qui suit :
Modification du code de la méthode ObtenirNParams donc c'est pour la méthode eMethStartTimer valeur renvoyée 1 :
cas eMethStartTimer : renvoie 1 ;
Voici le code de la méthode AppelAsProc au formulaire :
cas 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;
Vérifions maintenant la fonctionnalité. Pour ce faire, nous écrirons le code dans le module applicatif géré de la configuration :
variable DémoComp ; Procédure au démarrage du système() Connecter le composant externe("...", "DemoVK", Type de composant externe.Native); DemoComp = Nouveau("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Fin de la procédure
Après avoir démarré la configuration, le programme recevra des messages à intervalles de 2 secondes, ce qui indique que la minuterie fonctionne correctement.
Interaction avec le système 1C : Entreprise
Pour interagir entre le composant externe et le système 1C : Enterprise, méthodes de la classe IAddInDefBase, décrites dans le dossier AddInDefBase.h. Nous listons les plus couramment utilisés :Générer un message d'erreur
virtual bool ADDIN_API AddError (wcode court non signé, source const WCHAR_T*, const WCHAR_T* descr, scode long)
code w, code- codes d'erreur (une liste de codes d'erreur avec des descriptions peut être trouvée sur le disque ITS)
source- source d'erreur
description- Erreur de description
Envoi d'un message au système 1C : Entreprise
bool virtuel ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource-source du message
wszMessage- Texte du message
wszData- données transmises
L'interception des messages est réalisée par la procédure External Event Processing
Enregistrement d'un composant externe dans le système 1C : Entreprise
booléen virtuel ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- Nom du composant.
Ces méthodes sont suffisantes pour une interaction complète entre VK et 1C. Pour recevoir des données par un composant externe du système 1C : Entreprise et vice versa, le composant externe envoie un message spécial, qui à son tour est intercepté par le système 1C et, si nécessaire, appelle les méthodes du composant externe pour retransmettre les données. .
Type de données Variant
Lors de l'échange de données entre le composant externe et le système 1C : Enterprise, le type de données tVariant est utilisé. Il est décrit dans le fichier types.h, présent sur le disque 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 ullV al; int32_t errCode ; long hRes ; float fltVal ; double dblVal ; bool bVal; char chVal; wchar_t wchVal; DATE date; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NAME_2/*iface*/; _ANONYMOUS_STRUCT struct ( char* pstrVal; u int32_t strLen ; //nombre d'octets ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //nombre de symboles ) __VARIANT_NAME_4/*wstr*/; ) __VARIANT_NAME_1; uint32_t cbElements; //Dimension pour un tableau unidimensionnel dans pvarVal TYPEVAR vt; );
Taper tVariante est une structure qui comprend :
- mélange (union) destiné directement au stockage de données
- identifiant du type de données
- Déterminer le type de données actuellement stockées dans une variable
- Accédez au champ mélange correspondant pour accéder directement aux données
Application
Le répertoire « exemples » contient des exemples pour l'articleexemples/1 - lancer le composant démo
exemples/2 - démonstration de l'expansion de la liste de propriétés
exemples/3 - démonstration de l'élargissement de la liste des méthodes
Chaque répertoire contient un projet VS 2008 et une configuration 1C prête à l'emploi.
Option de syntaxe : Par nom et emplacement
Syntaxe:
ConnectExternalComponent(<Местоположение>, <Имя>, <Тип>)
Possibilités :
<Местоположение>(requis)
Type : chaîne.
L'emplacement du composant externe.
L'emplacement peut être utilisé :
chemin d'accès au fichier du composant externe sur le système de fichiers (non disponible sur le client Web), pas une archive ZIP ;
le nom complet de la mise en page stockant les données binaires ou l'archive ZIP ;
L'URL du composant externe, sous forme de données binaires ou d'archive ZIP, dans un format similaire à GetNavigationLink.
<Имя>(requis)
Type : chaîne.
Le nom symbolique du composant externe à connecter.
Le nom doit suivre les conventions de dénomination du langage intégré.
<Тип>(facultatif)
Tapez : Type de composant externe.
Type de composant externe à connecter.
Non utilisé si le composant est conditionné dans une archive ZIP.
Description de l'option de méthode :
Connecte les composants réalisés à l’aide de la technologie Native et COM.
Le composant peut être stocké dans l'infobase ou dans la présentation de configuration sous forme de données binaires ou dans une archive ZIP.
Pour les modes de lancement « Thin Client » et « Web Client », le composant doit au préalable être installé via la méthode Install External Component.
Option de syntaxe : Par ID
Syntaxe:
ConnectExternalComponent(<ИдентификаторОбъекта>)
Possibilités :
<ИдентификаторОбъекта>(requis)
Type : chaîne.
Identifiant de l'objet composant externe sous la forme de ProgID (Programmatic Identifier) du registre MS Windows (par exemple : « AddIn.Scanner »).
Doit correspondre aux informations contenues dans la base de données d'enregistrement du système (Registre).
Description de l'option de méthode :
Le composant doit être implémenté à l'aide de la technologie COM et enregistré dans le registre MS Windows.
Ces composants sont compatibles avec les composants 1C:Enterprise 7.7.
Attention! L'option méthode ne fonctionne pas sur le serveur et dans la connexion externe.
Valeur de retour :
Type : booléen.
Vrai : la connexion a réussi.
Description:
Connecte un composant externe à 1C:Enterprise.
Les composants externes peuvent être stockés dans une base d'informations ou des présentations de configuration sous forme d'archive ZIP ou de données binaires, ou dans un fichier de système de fichiers.
Lorsque vous travaillez sur un client léger et un client web, le composant doit être préinstallé.
Disponibilité:
Client léger, client web, serveur, connexion externe.
Note:
Les composants externes peuvent être implémentés à l’aide de la technologie Native API ou COM. Les composants fabriqués à l'aide de la technologie COM sont compatibles avec les composants 1C:Enterprise 7.7.
Le client Web ne peut fonctionner qu'avec les composants de l'infobase qui sont regroupés dans une archive.
Le client léger peut fonctionner avec des composants de l'infobase, regroupés dans une archive, et des composants situés dans le système de fichiers.
Le client lourd peut gérer toutes les options de stockage de composants. Dans ce cas, si un composant est installé à l'aide de la méthode Installer un composant externe, alors le composant installé est utilisé, et s'il n'est pas installé, le composant sera reçu au moment de la connexion.
Le serveur peut fonctionner avec tous les composants. Le composant est mis en cache par session de serveur.
Exemple:
Si ConnectExternalComponent("AddinObject.Scanner") Alors
Report("Composant chargé pour le lecteur de codes-barres");
Sinon
Report("Le composant du lecteur de codes-barres n'est pas chargé");
fin si;
Question : Composant externe Native Api en C++ pour Linux (Ubuntu x64) sur 1C 8.3
J'écris sur VK, mais je ne parviens pas à me connecter à 1c sur Ubuntu. Même l'exécutable de 1c ne se connecte pas. Donc une question à ce sujet :
1) J'essaie de connecter VK à partir de l'exemple VNCOMPS donné dans l'article
(le lien se trouve à la toute fin : « Copie »).
Il existe un makefile dans le projet NativeApi. Avec son aide, je construis une bibliothèque .so sur Ununtu.
Mais lorsque « Connecter un composant externe » 1c plante.
De même, si je construis en utilisant "build.sh" (à la racine du projet).
Dans le makefile lui-même, je change le drapeau de m32 à m64, car 1c et le système x64 lui-même. (avec le paramètre m32 ça ne se connecte pas de toute façon)
Voici un exemple d'appel de VK depuis 1C 8.3 :
Connexion effectuée = ConnectExternalComponent("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); Il y a un article uniquement sur ce sujet.
Mais, à ma connaissance, tous ces points ont déjà été pris en compte et corrigés dans l'exemple VNCOMPS.
Mais c'est essentiellement une question de paramètres de compilation. Un composant externe MB 32 bits se connecte normalement à un 1c 32 bits, mais je l'ai déployé sur Ubuntu x64 1c Enterprise83 8.3.5-1486 amd64. Et je veux la rencontrer sur VK.
Quelqu'un a-t-il une idée pour résoudre ce problème ?)
L'exemple VNCOMPS devrait fonctionner, mais les paramètres de construction doivent être ajustés, ou la plate-forme elle-même sur laquelle je teste est incorrecte.
Répondre: Je me demande, est-il possible d'écrire un composant externe en Java ?
Question : Le composant externe (natif) ne peut pas être connecté
J'ai compilé un exemple avec ITS, pour les systèmes 64 et 32 bits.
Je me connecte comme ceci :
Résultat de la connexion = ConnectExternalComponent (KDLLPath, "Comp", ExternalComponentType.Native); La connexion fonctionne sur un PC, mais pas sur l'autre. Il y a une différence dans le système d'exploitation. Là où la connexion est établie, il y a Win7, là où il n'y a pas de Win10. En parallèle, sur le PC où mon composant ne fonctionne pas, des composants standards fonctionnent.
Testé sur différentes plateformes (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).
Comment puis-je comprendre pourquoi il ne se connecte pas ?
Répondre: vc_redist oublié ?
Question : 1C8 et un composant externe de type Natif