CLOPOTUL

Sunt cei care citesc aceasta stire inaintea ta.
Abonați-vă pentru a primi cele mai recente articole.
E-mail
Nume
Nume de familie
Cum ți-ar plăcea să citești Clopoțelul
Fără spam

Întrebare: componentă API nativă externă în C++ pentru Linux (Ubuntu x64) pe 1C 8.3


Scriu VK, nu mă pot conecta la 1s pe ubuntu. Nici măcar exemplul de la 1s nu este conectat. Deci o intrebare despre asta:

1) Încerc să conectez VK din exemplul VNCOMPS dat în articol

(linkul poate fi găsit chiar la sfârșit: „Copiere”).
Pe plan intern, proiectul NativeApi are un makefile. Cu el, construiesc biblioteca .so pe Ununtu.
Dar la „Conectează componenta externă” 1 decolează.
În mod similar, dacă construiesc folosind „build.sh” (la rădăcina proiectului).

În makefile-ul în sine, schimb steag-ul de la m32 la m64, pentru că 1c și sistemul x64 însuși. (cu parametrul m32 oricum nu se ridica)
Iată un exemplu de apelare VK de la 1C 8.3:
ConnectionDone = Conectați o componentă externă("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); Există un articol doar pe această temă.
Dar, din câte văd, toate aceste puncte au fost deja luate în considerare și corectate în exemplul VNCOMPS.

Dar, de fapt, afaceri în parametrii de compilare. Componenta externă MB pe 32 de biți se conectează la 32 de biți 1c în mod normal, dar am implementat pe Ubuntu x64 1c enterprise83 8.3.5-1486 amd64. Și vreau să iau VK de la ea.

Are cineva idee cum se rezolvă această problemă?
Exemplul VNCOMPS ar trebui să funcționeze, dar parametrii de compilare trebuie corectați sau platforma în sine pe care testez este incorectă.

Răspuns: Interesant, este posibil să scrii o componentă externă în Java?

Întrebare: Componenta externă (nativă) nu este conectată


Compilat un exemplu cu ITS, pentru sisteme pe 64 și 32 de biți.

Mă conectez așa:
ConnectionResult = ConnectExternalComponent(CDLLPath, "Comp", ExternalComponentType.Native); Un PC se conectează, celălalt nu. Există o diferență în sistemul de operare. Unde merge conexiunea, există Win7, unde nu există Win10. În același timp, componentele standard funcționează pe un PC unde componenta mea nu funcționează.

Testat pe diferite platforme (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).

Cum să înțelegi de ce nu se conectează?

Răspuns: vc_redist nu a uitat?

Întrebare: 1C8 și o componentă externă cu tipul Nativ


Buna ziua.
Există o configurație de BP 3.0.50.12 și o dorință de a implementa cântărirea de la compania Scales-Soft folosind UniServerAuto.
Dezvoltatorii au compilat componenta nativă pentru Windows 32 și 64 și au pus-o într-o arhivă cu fișierul cel mai mare. Există, de asemenea, un exemplu pentru 1C, cum poate fi calculată greutatea. În ea, cu ajutorul unui layout cu date binare, este indicată această arhivă, după cum am înțeles-o. În exemplu, totul este în regulă: componenta este instalată, conectată, apoi se stabilește conexiunea și se citește greutatea.
Dar de îndată ce începi să te transferi la 1C, greutatea nu este citită. Se pare că totul este scris pur și simplu, dar nu înțeleg unde este grebla.
Cine va avea putin timp - ajuta, arunca o privire cu un ochi, poate solutia este la suprafata, dar merg undeva in locul nepotrivit si fac ceva gresit. Nu am mai lucrat niciodată cu tehnologia nativă până acum...

Și în atașament este textul meu de procesare

Răspuns:

Ei bine, am niște vești...
Tocmai am început să mă uit pas cu pas în ce moment începe să eșueze. Pentru a face acest lucru, am creat o bază de date goală și procesare cu comanda. Prin analogie cu exemplul furnizorului, am transferat aspectul într-o nouă conf - funcționează a doua oară. Acestea. Prima dată nu, a doua oară da. Acest lucru a dat naștere la ideea că va fi totuși necesară în prelucrarea sa să se separe legătura dintre componentă și obiect după diferite proceduri.
Apoi l-am transferat în baza mea de date cu o conexiune de aspect - funcționează. Fuh, deja e bine.... Dar as dori fara sa fac modificari la configuratie, asa ca sa trecem mai departe

Încerc să adaug un aspect la procesare. Dimensiunea sa crește imediat de la 10kb la 3mb și se observă o încetinire semnificativă - nu se potrivește. Încep să caut spre conectarea unei componente prin dll. Acestea. practic la fel ca de unde ai început. Dar există un „DAR”: căutând după numele dll-ului în folderul utilizatorului, am observat că acest dll se află acolo unde (după cum am înțeles) sunt adăugate dll-urile înregistrate în 1C:
C:\Utilizatori\UTILIZATOR\AppData\Roaming\1C\1cv8\ExtCompT
în consecință, nu este nevoie să folosiți calea completă către dll, puteți pur și simplu să-i scrieți numele:
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

Încerc... înjură la înregistrare, dar returnează rezultatul cântăririi. Se pare că dll-ul este deja înregistrat, ceea ce înseamnă că trebuie doar să îl conectați. Il scot si totul merge.
rezum:
1. La prelucrarea cântăririi în procedura La Deschidere am adăugat conexiunea unei componente externe și conexiunea la obiect.
2. Calea către dll nu am scris-o, doar i-am indicat numele.

Acum stau și mă gândesc, când s-a instalat dll-ul în 1C? În momentul instalării software-ului? Cu greu... În momentul rulării configurației pentru dezvoltatori a acestui dll, unde este setat când se deschide formularul? Nu știu, dar mi se pare aproape... Ce părere ai?
Și în al doilea rând, într-un loc nou, când este nevoie să instalați același terminal, ce trebuie făcut pentru ca totul să funcționeze? Instalați software-ul complet, rulați configurația furnizorului pentru a verifica funcționarea și apoi (teoretic) ar trebui să funcționeze procesarea mea? Ceva cam complicat... Sau după ce am instalat software-ul în procesarea mea, fac InstallExternalComponent o dată?

Mi-ar plăcea să aud părerile tale despre asta...

Întrebare: External component.dll


Bună ziua tuturor.
O intrebare.
dll care funcționează bine în 1C 7.7
în 1s 8.1 nu vrea să pornească deloc...
Încercați și lipiți-l în C:\Program Files\1cv81\bin\cache1c.dll
Am încercat să mă înregistrez folosind regsvr32 „C:\Program Files\1cv81\bin\cache1c.dll”
Inregistrat fara probleme.
Când încerc să-l accesez, primesc un mesaj de eroare:

Eroare la încărcarea componentei externe! cache1c.dll
Procedură Executați ButtonClick(Button) Încercați să încărcați o componentă externă( „C:\Program Files\1cv81\bin\cache1c.dll”); Raport de exceptie( „Eroare la încărcarea componentei externe!”+ "cache1c.dll"); Sfârșitul încercării; Încercați // Obțineți obiectul componentă. // m = Nou ("cache1c.GTMcmd"); m = New COMObject("cache1c.GTMcmd" ); Raport de exceptie(); Sfârșitul încercării; EndProcedure

Răspuns: Banal pana la imposibilitate...
Este necesar să se susțină pauze între apeluri (milisecunde)...
Procedură ButtonExecuteClick(Button) Attempt // Obține obiectul componentă. m = New COMObject("cache1c.GTMcmd" ); Raport de exceptie( „Nu s-a putut crea obiectul component extern”); Sfârșitul încercării; m.RemoteHost = "192.168.1.101" ; m.RemotePort = 6330; m.Connect(); m.pauză (100); ...... etc
Pentru 1s 7,7 - acest lucru nu este necesar, se dovedește că circulația este mai rapidă.

Întrebare: Lucrul unei componente externe cu serverul 1C ...


Buna ziua,

Există o componentă externă scrisă în C++, a cărei sarcină este să primească informații dintr-o bază de date externă și să returneze rezultatul interogării sub forma unui Tabel de Valori în 1C.
Pentru a forma un tabel de valori în momentul curent, se folosește interfața IDispatch* pBackConnection, care este primită ca parametru în funcția Init(). În plus, pur și simplu, folosind funcțiile 1C, formez un tabel de valori, îl completez și îl returnez la al doilea parametru din CallAsFunc (...).
Problemele au început cu trecerea la thin clients 1C. Pe partea de server, componenta externă nu pornește cu adevărat. Îl puteți rula pe partea clientului, dar totul arată ca niște cârje și nu se încadrează în logica generală „client-server” în 1C. De exemplu, clientul nu înțelege ce este un tabel de valori, probleme cu variabile „globale”, sesiuni etc.
NativeAPI este și mai trunchiat în acest sens.
Dansul cu o tamburină a dus la faptul că am putut lansa o componentă externă sub serverul 1C, DAR munca se întâmplă până când se încearcă apelarea la Invoke pe pBackConnection. Versiunea pe 64 de biți a serverului 8.2 încearcă să facă ceva până când scade la un timeout, versiunea pe 32 de biți (VK este, desigur, și pe 32 de biți) cade imediat.
Presupun că serverul 1C nu servește acest mod de operare.
În consecință, apar întrebări, este temporar sau logica 1C se reduce la desființarea acestei scheme de muncă? Dacă este imposibil să creați structuri interne 1C (tabel de valori) în acest fel, există, în principiu, o descriere a ceea ce este un tabel de valori la nivel de sistem pentru a încerca să îl creați în C++ , completați-l și apoi introduceți doar 1C ca parametru de returnare? Aș dori măcar să obțin o direcție în care să sap.

Mulțumesc.

Răspuns:

Scrii un lucru și vrei să spui altceva.
În mediul 1C, declararea variabilelor care vor fi vizibile în diferite sesiuni nu este imposibilă acum și nu era posibil înainte. O sesiune diferită este un proces diferit din punct de vedere fizic.
Sesiunea este o sesiune de conexiune la baza de date, de ex. sesiune utilizator. Sau pui ceva al tău și acest concept?

În cadrul unei sesiuni, a fost posibil, și este posibil acum, să se declare variabile în modulul de sesiune, care vor trăi și vor fi vizibile în cadrul sesiunii din diferite locuri... de fapt, sunt 4 dintre ele.
- Modul de sesiune;
- Modul de aplicare regulat;
- Modul de aplicație gestionat;
- Modul de conectare extern.

Și, desigur, trebuie să vă amintiți despre context. Contextul serverului nu este direct accesibil din partea clientului și invers.

În general, arhitectura 1C prevede că schimbul de date va continua:
- prin intermediul parametrilor/retururilor de proceduri/functii;
- prin intermediul așa-numiților parametri de sesiune (nu pot fi obiecte, de fapt îl puteți vedea în paletă).

Tabelul de pe formular... și este legat de orice tabel de obiect (procesări, de exemplu)? sau nu. Dacă da, atunci este disponibil și pe server (&AtServer) și editați acolo....

Și da, ValueTable nu este disponibil în UV pe partea clientului. Ei bine, 1C a decis așa.

Haide! Aici funcționează cu Excel, funcționează cu FSO și o grămadă de orice altceva, dar aici nu funcționează. Prinde eroarea si analizeaza....

Atentat, încercare
...
actiunile tale
...
Excepție
str = DescriptionError();
Sfârșitul încercării;

Cu capabilitățile hardware moderne, acesta nu este deloc un argument.

Opinie pur personală. nu are nimic de-a face cu realitatea. Nu în nici un fel. Repet încă o dată, 1C funcționează excelent cu COM. Atât cu in-proc cât și cu out-proc.

Dați codul pe care îl încărcați și aplicați la VK.

Apropo, VK... în cazul tău, este COM sau API nativ?
Dacă COM, atunci îl înregistrați ca... prin regsvr32... atunci cum „rezolvați” problema adâncimii de biți?

Întrebare: Instalarea unei componente externe


Vă rog să-mi spuneți cum să instalez o componentă externă. La executarea următorului cod, se afișează o eroare. Găsiți NameDecl.dll în aspect

Încercați să SetExternalComponent("GeneralLayout.Layout"); Excepție EndTry ;
Eroare: instalarea pluginului a eșuat!

Răspuns: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native) returnează FALSE ,
New("AddIn.NameDecl.CNameDecl", Nedefinit) = (()): Tip nedefinit (AddIn.NameDecl.NameDecl)

Întrebare: dll nativ nu este conectat la 1s 8.1 (fptrwin32_fz54_9_11_0_5549.dll)


Buna ziua.
1C a actualizat dll-ul pentru casele de marcat online atol pentru fdd 1.05 (inclus în procesarea de întreținere fptrwin32_fz54_9_11_0_5549.dll).
Am un vechi 1C 8.1. Spre deosebire de 8.2, nu acceptă lucrul cu echipamente externe în același mod ca 8.2, așa că mai întâi trebuie să înregistrați dll-ul în Windows și apoi să îl conectați doar la 1C?

ProgID = "AddIn.IntegrationComponent.ATOL_KKT_1C83_V9"; LoadExternalComponent("C:\fptrwin32_fz54_9_11_0_5549.dll"); ConnectExternalComponent(ProgID); Driver = New(ProgID);

Cu toate acestea, procesarea veche a fost scrisă în „technology” com, iar noul nativ. În consecință, la înregistrare, regsvr32 dă o eroare:
Modulul a fost încărcat, dar punctul de intrare DllRegisterServer nu a fost găsit. Și sugerează să verificați dacă acest fișier este fișierul dll sau OCX corect.
Cine s-a confruntat cu o situație similară, cum ai ieșit? Înțeleg că o problemă similară va fi în 7.7.
Cod 8.2:

Layout = GetLayout("IntegrationComponent"); Adresă = PlaceInTempStorage(Layout); ConnectExternalComponent(Adresă, „IntegrationComponent”, ExternalComponentType.Native); Driver = New ("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

1C 8.2:
Conectați componenta externă (<Местоположение>, <Имя>, <Тип>)
1C 8.1:
Conectați componenta externă (<Идентификатор объекта>)
Opțiuni:
<Идентификатор объекта>(necesar)
Tip: șir. ProgID (identificatorul programatic) al obiectului component extern. Trebuie să se potrivească cu informațiile din baza de date de înregistrare a sistemului (Registry).
Descriere:
Conectează obiectele componente externe la 1C:Enterprise.
Nu este disponibil pe serverul 1C:Enterprise. Nu este utilizat în modulul de conectare extern.
Notă:
Componentele externe sunt compatibile cu componentele 1C:Enterprise 7.7.
Exemplu:
Atentat, încercare
ConnectExternalComponent("AddinObject.Scanner");
alert(„Componenta scanerului de coduri de bare a fost încărcată”);
Excepție
alert(„Componenta scanerului de coduri de bare nu este încărcată”);
Încheierea încercărilor

Există vreo modalitate de a conecta acest dll la 8.1 sau nu?

Mulțumesc!

Răspuns:

Am avut si eu de curand aceasta problema. Nu a fost posibilă conversia la o versiune ulterioară a 1s. dll cu care funcționează această configurație pur și simplu a încetat să funcționeze și 1c a căzut cu o eroare.
Problema a fost rezolvată în felul următor:
Am creat o bază de date goală 8.3 în care am procesat inițializarea componentei și apoi de la 8.1 prin conexiune COM am accesat baza de date creată anterior și am inițializat componenta acolo. Apoi, deja în 8.1, am numit metodele acestei componente.
Desigur, aceasta este o cârjă, dar nu am găsit încă o altă cale de ieșire (

Exemplu de cod 8.3:
Export Driver Rem;
Funcția ConnectionComponentsCCP() Export
Atentat, încercare

Layout = GetLayout("IntegrationComponent");
Adresă = PlaceInTempStorage(Layout);
ConnectExternalComponent(Adresă, „IntegrationComponent”, ExternalComponentType.Native);
Driver = New ("AddIn.IntegrationComponent.SMDrvFR1C20");
rezultat = adevărat;​

Excepție

rezultat = fals;​

Sfârșitul încercării;
Întoarceți rezultatul
EndFunctions

Exemplu de cod 8.1

Funcția CreateDriverObject(Driver) Export

rezultat = adevărat;

Atentat, încercare

ConnectionString="File="""Cale către baza de date""";
ComObject= New COMObject("V83.ComConnector");
Conectare = ComObject.Connect(ConnectionString);

Procesare = Connect.Processing.ConnectingExternalComponent.Create();
ConnectionResult = Processing.ConnectingKKT Components();
Dacă rezultatul se conectează, atunci
Driver = Procesare.Driver;
EndIf;​

Excepție
Oricine a făcut acest lucru sau a experimentat probleme similare, vă rugăm să explice. exemplu simplu principiul în sine. Se pare că totul este clar cu conectarea componentelor externe.

// Un exemplu de completare a tabelului de valori TK.Clear(); Solicitare = Solicitare nouă; Query.Text = „SELECTARE | Nomenclator Link CUM Nomenclator | DE LA | Directory.Nomenclature AS Nomenclature"; QueryResult = Query.Execute(); Sampling = QueryResult.Select(); While Sampling.Next() Loop Str = TK.Add(); FillPropertyValues(Pr, Sampling); EndCycle;
Ați putea explica cu acest exemplu ce parte a codului este de obicei eliminată. Ar fi logic să scoatem partea cu cerere, dar atunci cum putem accesa baza de date din componenta externă din componenta externă, ocolind platforma? Textul este inutil. Sau eliminați însăși formarea părții tabulare. Vă rugăm să împărtășiți experiența dvs. cu asta.

Răspuns:Și că cuvântul „Incompatibil” înseamnă întotdeauna cuvântul „Rău”? Da, mi se pare că dacă îmi numesc stilul „1C: Cea mai proastă programare pe acest motor de scripting care există în natură (tradusă într-un limbaj literar)!” și apoi cu siguranță vor fi cei care vor să verifice această fiară. Și arată ca un clasic: „Nu am citit Pasternak, dar nu sunt complet de acord cu el!” :)

Întrebare: Conectarea unei componente externe în 1s 8.3.6 și Win8


Este necesar să conectați vk_rs232.dll ExternalComponent la configurația scrisă de sine. Like înregistrat prin regsvr32.exe. „Se pare” pentru că am primit un mesaj că „componenta este înregistrată, dar ceva nu este în regulă cu firewall-ul”. Bazându-mă pe prima jumătate a mesajului, scriu codul în 1s
AfterConnection = New NotificationDescription("AfterConnectionVK",ThisForm); StartExternalComponentInstallation(,"C:\Controller\vk_rs232.dll"); StartConnectingExternalComponent(AfterConnecting,"C:\Controller\vk_rs232.dll","DLL_Scales");
și primesc eroarea că
„Instalarea componentelor externe a eșuat! Este posibil ca componenta pentru aplicația client pe care o utilizați să lipsească!”.

Și acum nu înțeleg
1. Poate componenta nu este înregistrată în registry - cum pot să o verific acolo?
2. Poate că „versiunea” ei nu funcționează sub Win8, deși o am pe 32 de biți.
3. Poate că 1s în sine este prea nou, adică. prin urmare, nu poate lucra cu acest dll?
4. Ei bine, e banal - scriu ceva greșit.

Răspuns:Și toate acestea m-au condus la următoarea problemă. VneshComp instalat, acum trebuie să-l conectați. Și aici sunt ambele opțiuni.
ConnectExternalComponent("C:\Controller\vk_rs232.dll","Scale")
ConnectExternalComponent("GeneralLayout.Layout","Scale")

Opțiune de sintaxă: După nume și locație

Sintaxă:

Conectați componenta externă (<Местоположение>, <Имя>, <Тип>)
Opțiuni:

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

Tip: șir.
Locația componentei externe.
Locația poate fi folosită:
calea către fișierul componentei externe din sistemul de fișiere (nu este disponibilă pe clientul web), nu o arhivă ZIP;
Numele complet un aspect care stochează date binare sau o arhivă ZIP;
URL-ul către componenta externă, sub formă de date binare sau o arhivă ZIP, într-un , similar cu GetNaviLink.
<Имя>(necesar)

Tip: șir.
Numele simbolic al componentei externe conectabile.
Numele trebuie să respecte convențiile de denumire ale limbajului încorporat.
<Тип>(optional)

Tip: ExternalComponent Type.
Tipul de componentă externă care trebuie conectată.
Nu este utilizat dacă componenta este ambalată într-o arhivă ZIP.
Descrierea variantei metodei:

Conectează componente realizate folosind tehnologia nativă și COM.
Componenta poate fi stocată într-o bază de informații sau într-o configurație ca date binare sau într-o arhivă ZIP.
Pentru modurile de lansare „client subțire” și „client web”, componenta trebuie instalată în prealabil folosind metoda Instalare componente externe.
Opțiune de sintaxă: După ID

Sintaxă:

Conectați componenta externă (<ИдентификаторОбъекта>)
Opțiuni:

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

Tip: șir.
Identificatorul de obiect al componentelor externe sub forma ProgID (Identificatorul programatic) al registrului MS Windows (de exemplu: „AddIn.Scanner”).
Trebuie să se potrivească cu informațiile din baza de date de înregistrare a sistemului (Registry).
Descrierea variantei metodei:

Componenta trebuie implementată folosind tehnologia COM și înregistrată în registrul MS Windows.
Aceste componente sunt compatibile cu componentele 1C:Enterprise 7.7.
Atenţie! Varianta metodei nu funcționează pe server și în conexiunea exterioară.
Valoare returnată:

Tip: boolean.
Adevărat - conexiunea a avut succes.
Descriere:

Conectează o componentă externă la 1C:Enterprise.
Componentele externe pot fi stocate în baza de informații sau în configurații ca arhivă ZIP sau ca date binare sau într-un fișier de sistem de fișiere.
Când lucrați la un client subțire și un client web, componenta trebuie să fie preinstalată.

Disponibilitate:

Thin client, client web, server, conexiune externă.
Notă:

Componentele externe pot fi implementate folosind tehnologia Native API sau COM. Componentele realizate folosind tehnologia COM sunt compatibile cu componentele 1C:Enterprise 7.7.
Clientul web poate lucra numai cu componente dintr-o bază de informații care sunt împachetate într-o arhivă.
Clientul subțire poate lucra cu componente din baza de informații, ambalate într-o arhivă și componente situate în sistemul de fișiere.
Clientul gros poate lucra cu toate opțiunile de stocare pentru componente. În acest caz, dacă componenta este instalată folosind metoda InstallExternalComponent, atunci componenta instalată este utilizată, iar dacă nu este instalată, atunci componenta va fi primită în momentul conexiunii.
Serverul poate funcționa cu toate componentele. Componenta este stocată în cache pentru sesiunea de server.
Exemplu:

Dacă ConnectExternalComponent ("AddinObject.Scanner"), atunci
alert(„Componenta scanerului de coduri de bare a fost încărcată”);
In caz contrar
alert(„Componenta scanerului de coduri de bare nu este încărcată”);
EndIf;

  • tutorial

Introducere

Acest articol oferă o idee despre cum funcționează componentele externe în sistemul 1C:Enterprise.
Va fi afișat procesul de dezvoltare a unei componente externe pentru sistemul 1C:Enterprise versiunea 8.2 care rulează sub sistemul de operare Windows cu o versiune de fișier de lucru. Această opțiune este utilizată în majoritatea soluțiilor concepute pentru întreprinderile mici. VC va fi implementat în limbajul de programare C++.

Componente externe „1C: Enterprise”

„1C: Enterprise” este un sistem extensibil. Pentru extindere funcţionalitate sistemul utilizează componente externe (VC). Din punctul de vedere al dezvoltatorului, un VC este un obiect extern care are proprietăți și metode și poate genera și evenimente pentru procesare de către sistemul 1C:Enterprise.
Componentele externe pot fi folosite pentru a rezolva o clasă de sarcini care sunt dificil sau chiar imposibil de implementat folosind limbajul de programare încorporat în 1C: Enterprise. În special, această clasă include sarcini care necesită interacțiune la nivel scăzut cu sistemul de operare, de exemplu, pentru a lucra cu hardware specific.
Sistemul 1C:Enterprise utilizează două tehnologii pentru crearea componentelor externe:
  • folosind Native API
  • folosind tehnologia COM
Având în vedere restricțiile dintre cele două tehnologii de mai sus, diferența este nesemnificativă, așa că vom lua în considerare dezvoltarea VK folosind API-ul nativ. Dacă este necesar, dezvoltările implementate pot fi aplicate dezvoltării VC folosind tehnologia COM și, de asemenea, cu modificări minore, aplicate pentru utilizare în sistemul 1C: Enterprise cu alte opțiuni de operare, altele decât modul de operare fișier.
Structura VK
Componenta externă a sistemului 1C:Enterprise este prezentată ca o bibliotecă DLL. Codul bibliotecii descrie clasa derivată IComponentBase. În clasa care se creează trebuie definite metodele responsabile cu implementarea funcțiilor componentei externe. Metodele anulate vor fi descrise mai detaliat mai târziu în cursul prezentării materialului.

Lansarea demo-ului VK

O sarcină:
  1. Asamblați componenta externă furnizată cu abonamentul ITS și concepută pentru a demonstra principalele capabilități ale mecanismului componentei externe în 1C
  2. Conectați componenta demo la configurația 1C
  3. Asigurați-vă că funcțiile declarate funcționează corect
Compilare
VC-ul demonstrativ se află pe discul de abonament ITS în directorul „/VNCOMP82/example/NativeAPI”.
Vom folosi Microsoft Visual Studio 2008 pentru a asambla VK demo.Alte versiuni ale acestui produs nu acceptă formatul de proiect Visual Studio utilizat.


Deschideți proiectul AddInNative. În setările proiectului, conectăm directorul cu fișierele de antet necesare pentru a construi proiectul. În mod implicit, acestea sunt localizate pe discul ITS din director /VNCOMP82/include.
Rezultatul construcției este un fișier /bind/AddInNative.dll. Aceasta este biblioteca compilată pentru conectarea la configurația 1C.
Se conectează configurația VK la 1C
Să creăm o configurație goală 1C.
Mai jos este codul pentru modulul aplicației gestionate.
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...\bind\AddInNative.dll", "DemoVK", ExternalComponentType.Native); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); EndProcedure
Dacă nu a fost raportată nicio eroare la pornirea configurației 1C, atunci VK-ul a fost conectat cu succes.
Ca urmare a executării codului de mai sus, în vizibilitatea globală a configurației apare un obiect DemoComp Un care are proprietăți și metode care sunt definite în codul bean extern.
Demonstrarea funcționalității încorporate
Să verificăm performanța demo-ului VK. Pentru a face acest lucru, să încercăm să setăm și să citim unele proprietăți, să apelăm unele metode VK și, de asemenea, să primim și să procesăm un mesaj VK.
Documentația furnizată pe discul ITS precizează următoarea funcționalitate a VC-ului demo:
  1. Managementul stării obiectelor componente
    Metode: Porniți, Opriți
    Proprietăți: Inclus
  2. Control cu ​​temporizator
    În fiecare secundă, componenta trimite un mesaj către sistemul 1C: Enterprise cu parametri Componentă, temporizatorși un șir de contor al ceasului de sistem.
    Metode: StartTimer, StopTimer
    Proprietăți: Există un cronometru
  3. Metodă ShowInStatusLine, care afișează în bara de stare textul transmis metodei ca parametri
  4. Metodă Incarca imaginea. Încarcă o imagine din fișierul specificat și o transferă în sistemul 1C:Enterprise ca date binare.
Să ne asigurăm că aceste funcții funcționează. Pentru a face acest lucru, vom executa următorul cod:
var DemoComp; SystemStart() Procedura ConnectExternalComponent(...); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Notify(DemoComp. Activat); DemoComp.Enable(); Notify(DemoComp. Activat); DemoComp.StartTimer(); EndProcedure ProcedureExternalEventHandler(Sursa, Eveniment, Date) Raport(Sursa + " " + Eveniment + " " + Date); EndProcedure
Rezultatul rulării configurației este afișat în imagine


Rezultatele apelurilor de metodă sunt afișate în panoul „Mesaje”. DemoComp.Disable()și Demo.Comp.Enable(). Rândurile ulterioare de pe același panou conțin rezultatele procesării mesajelor primite de la VK - Sursă, Evenimentși Date respectiv.

Denumire arbitrară a componentei externe

Sarcină: Schimbați numele componentei externe într-unul arbitrar.
Secțiunea anterioară a folosit identificatorul AddInNativeExtension, al cărui sens nu a fost explicat. În acest caz AddInNativeExtension este numele extensiei.
Codul VC definește o metodă RegisterExtensionAs, care returnează numele sistemului 1C: Enterprise, care este necesar pentru înregistrarea ulterioară a VC în sistem. Se recomandă precizarea unui identificator care, într-o anumită măsură, dezvăluie esența componentei externe.
Iată codul complet al metodei RegisterExtensionAs cu numele extensiei schimbat:
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) ( if(m_iMemory) ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T)))::convToShortWchar(wsExtensionName, wsExtension, iActualSize); return true; ) return false; )
În exemplul de mai sus, numele VK a fost schimbat în Un nume. Apoi, atunci când conectați VK, trebuie să specificați un nou nume:
DemoComp = New("AddIn.DemoVK.SomeName");

Extinderea listei de proprietăți VK

O sarcină:
  1. Studiați implementarea proprietăților VC
  2. Adăugați o proprietate de citire-scriere de tip șir
  3. Adăugați o proprietate de tip șir de citire/scriere care stochează tipul de date al ultimului set de proprietăți. Nu se întreprinde nicio acțiune la setarea valorii proprietății

Pentru a defini proprietățile componentei care este creată, dezvoltatorul trebuie să implementeze următoarele metode în codul bibliotecii AddInNative.cpp:
GetNProps
Returnează numărul de proprietăți pentru această extensie, 0 dacă nu există proprietăți
FindProp
Returnează numărul ordinal al proprietății al cărei nume este trecut în parametri
GetPropName
Returnează numele proprietății după ordinal și după ID-ul limbii transmise
GetPropVal
Returnează valoarea proprietății cu ordinalul specificat
SetPropVal
Setează valoarea proprietății cu ordinalul specificat
IsPropReadable
Returnează indicatorul de lizibilitate al proprietății cu ordinalul specificat
IsPropWritable
Returnează indicatorul de scriere a proprietății cu numărul de secvență specificat


Luați în considerare implementarea metodelor de clasă de mai sus CAddInNative.
VC demonstrativ definește 2 proprietăți: Inclusși Există un cronometru (Este activatși IsTimerPresent).
Două matrice sunt definite în domeniul global al codului bibliotecii:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Activat", L"Există un temporizator");
care stochează denumirile în rusă și engleză ale proprietăților. În fișierul antet AddInNative.h o enumerare este definită:
Enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Întotdeauna ultimul );
ePropIsEnabledși ePropIsTimerPresent, respectiv având valorile 0 și 1, sunt folosite pentru a înlocui numerele ordinale ale proprietăților cu identificatori semnificativi. ePropLast, care are valoarea 2, este folosit pentru a obține numărul de proprietăți (folosind metoda GetNProps). Aceste nume sunt folosite doar în interiorul codului componentei și nu sunt accesibile din exterior.
Metodele FindProp și GetPropName caută prin matrice g_PropNamesși g_PropNames.
Pentru a stoca valoarea câmpurilor din modulul bibliotecă, clasa CAddInNative are proprietăți care stochează valoarea proprietăților componentei. Metode GetPropValși SetPropVal respectiv returnează și setează valoarea acestor proprietăți.
Metode IsPropReadableși IsPropWritableși întoarce-te Adevărat sau fals, în funcție de ordinalul trecut al proprietății conform logicii aplicației.
Pentru a adăuga o proprietate personalizată:

  1. Adăugați numele proprietății care urmează să fie adăugate în matrice g_PropNamesși g_PropNames(fişier AddInNative.cpp)
  2. La enumerare recuzită(fişier AddInNative.h) inainte de ePropLast adăugați un nume care identifică în mod unic proprietatea care trebuie adăugată
  3. Organizați memoria pentru stocarea valorilor proprietăților (creați câmpuri ale modulelor componente care stochează valorile corespunzătoare)
  4. Faceți modificări metodelor GetPropValși SetPropVal pentru a interacționa cu memoria alocată în pasul anterior
  5. În conformitate cu logica aplicației, efectuați modificări metodelor IsPropReadableși IsPropWritable
Punctele 1, 2, 5 nu au nevoie de explicații. Detalii despre implementarea acestor pași pot fi găsite în anexa la articol.
Să numim proprietățile testului Testși Verificare tip respectiv. Apoi, ca urmare a paragrafului 1, avem:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Activat", L"HasTimer", L"Test", L"CheckType");
Enumerare recuzită va arata ca:
Enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Întotdeauna ultimul);
Pentru a simplifica semnificativ codul, vom folosi STL C++. În special, pentru lucrul cu șiruri WCHAR, conectați biblioteca wstring.
Pentru a stoca valoarea unei metode Test, definiți în clasă CAddInNativeîn domeniul privat:
string test1;
Pentru a transfera parametrii de șir între 1C:Enterprise și o componentă externă, este utilizat managerul de memorie 1C:Enterprise. Să aruncăm o privire mai atentă la munca lui. Pentru a aloca și, respectiv, a elibera memorie, utilizați funcțiile AllocMemoryși Memorie libera, definit în dosar MemoryManager.h. Dacă este necesar să se transmită un parametru șir sistemului 1C: Enterprise, componenta externă trebuie să-i aloce memorie prin apelarea funcției AllocMemory. Prototipul său arată astfel:
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
Unde pMemorie- adresa pointerului în care va fi plasată adresa memoriei alocate,
ulCountByte- dimensiunea zonei de memorie alocată.
Un exemplu de alocare a memoriei pentru un șir:
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);
Pentru confortul lucrului cu tipuri de date șir, descriem funcția wstring_to_p. Este nevoie de un șir wstring ca parametru. Rezultatul funcției este o structură umplută tVariant. Codul funcției:
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(); returneaza adevarat;)
Apoi, secțiunea de caz corespunzătoare a instrucțiunii switch a metodei GetPropVal va lua forma:
caz ePropTest1: wstring_to_p(test1, pvarPropVal); pauză;
metodă SetPropVal:
caz ePropTest1: dacă (TV_VT(varPropVal) != VTYPE_PWSTR) returnează fals; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); pauză;
Pentru a implementa a doua proprietate, definim un câmp de clasă CaddInNative
uint8_t last_type;
în care vom stoca tipul ultimei valori transmise. Pentru a face acest lucru, adăugați următoarea comandă la metoda CaddInNative::SetPropVal:
ultimul_tip = TV_VT(varPropVal);
Acum, când solicităm citirea valorii celei de-a doua proprietăți, vom returna valoarea ultimul_tip, care este cerut de sarcina desemnată.
Să verificăm performanța modificărilor făcute.
Pentru aceasta, vă prezentăm aspect configurația 1C la vedere:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.CheckType = 1; Raport(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raport(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raport(String(DemoComp.Test)); Raport(String(DemoComp.TypeCheck)); EndProcedure
Ca urmare a lansării, primim o secvență de mesaje:
3
Vasia
Petya
22

Al doilea și al treilea mesaj sunt rezultatul citirii proprietății stabilite în pasul anterior. Primul și al doilea mesaj conțin codul de tip al ultimului set de proprietăți. 3 corespunde unei valori întregi, 22 - unei valori șir. Corespondența tipurilor și a codurilor acestora se stabilește în dosar tipuri.h, care se află pe discul ITS.

Extinderea listei de metode

O sarcină:
  1. Extindeți funcționalitatea componentei externe cu următoarea funcționalitate:
  2. Aflați cum să implementați metode de componente externe
  3. Adăugați metoda-funcție Funcția 1, care ia două șiruri de caractere ("Parameter1" și "Parameter2") ca parametru. Ca rezultat, este returnat un șir din formular: „Verifică. Parametrul 1, Parametrul 2"
  4. Verificați dacă modificările efectuate funcționează.

Pentru a defini metodele componentei care se creează, dezvoltatorul trebuie să implementeze următoarele metode în codul bibliotecii AddInNative:
GetNMethods, FindMethod, GetMethodName
Conceput pentru a obține, respectiv, numărul de metode, căutarea numărului și denumirea metodei. Similar cu metodele corespunzătoare pentru proprietăți
GetNParams
Returnează numărul de parametri ai metodei cu numărul de secvență specificat; dacă nu există nicio metodă cu acest număr sau nu are parametri, returnează 0
GetParamDefValue
Returnează valoarea implicită a parametrului specificat al metodei specificate
HasRetVal
Returnează un indicator pe care îl are metoda cu valoarea de returnare specificată ordinal: true pentru metodele cu o valoare returnată și fals in caz contrar
CallAsProc
fals, apare o eroare de rulare și execuția modulului 1C: Enterprise se oprește. Memoria pentru matricea de parametri este alocată și eliberată de 1C: Enterprise.
CallAsFunc
Execută metoda cu ordinalul specificat. Dacă metoda revine fals, apare o eroare de rulare și execuția modulului 1C: Enterprise se oprește. Memoria pentru matricea de parametri este alocată de 1C: Enterprise. Dacă valoarea returnată este de tip șir sau date binare, componenta alocă memorie cu funcția AllocMemory manager de memorie, scrie acolo datele și stochează această adresă în câmpul corespunzător al structurii. 1С: Întreprinderea va elibera această memorie prin apel Memorie libera.
O descriere completă a metodelor, inclusiv lista de parametri, este descrisă în detaliu în documentația furnizată pe discul ITS.
Luați în considerare implementarea metodelor descrise mai sus.
În codul componentelor, sunt definite două matrice:
static wchar_t *g_MethodNames = (L"Activare", L"Dezactivare", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Activare", L"Dezactivare", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
si enumerare:
Metode enum ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Întotdeauna ultimul);
Sunt folosite în funcții GetNMethods, FindMethodși GetMethodName, prin analogie cu descrierea proprietăților.
Metode GetNParams, GetParamDefValue, HasRetVal comutatorul instrumentului, în funcție de parametrii trecuți și de logica aplicației, returnează valoarea necesară. Metodă HasRetValîn codul său are o listă de numai metode care pot returna un rezultat. Pentru ei se întoarce Adevărat. Pentru toate metodele de oțel returnări fals.
Metode CallAsProcși CallAsFunc conţin cod de metodă direct executabil.
Pentru a adăuga o metodă care poate fi apelată doar ca funcție, trebuie să faceți următoarele modificări în codul sursă al componentei externe:
  1. Adăugați numele metodei la matrice g_MethodNamesși g_MethodNames(fişier AddInNative.cpp)
  2. Adăugați un identificator de metodă semnificativ la enumerarea Metode (fișier AddInNative.h)
  3. Efectuați modificări la codul funcției GetNParams conform logicii programului
  4. Dacă este necesar, faceți modificări codului metodei GetParamDefValue dacă doriți să utilizați valorile implicite ale parametrilor metodei.
  5. Efectuați modificări la o funcție HasRetVal
  6. Faceți modificări în logica funcțiilor CallAsProc sau CallAsFunc, plasând acolo codul executabil direct al metodei
Să aducem matrice g_MethodNamesși g_MethodNames, precum și enumerarea metode la vedere:
static wchar_t *g_MethodNames = (L"Activare", L"Dezactivare", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Activare", L"Dezactivare", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage", L"Test");

Metode de enumerare ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Întotdeauna ultimul);
Să edităm funcția GetNProps astfel încât să returneze numărul de parametri ai metodei „Test”:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) (case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; implicit: return 0; ) return 0; )
Să facem modificări în funcție:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; comutator(lMethodNum) ( case eMethCaseDisable:Tcase eMethCaseStatus:Tcase eMethCase:MethCaseStatus:Tcase : case / Nu există valori ale parametrilor în mod implicit break; implicit: return false; ) return false; )
Mulțumită liniei adăugate
caz eMethTest:
în absența unuia sau a mai multor argumente, parametrii corespunzători vor avea o valoare goală ( VTYPE_EMPTY). Dacă aveți nevoie de o valoare implicită pentru un parametru, trebuie să o specificați în secțiune eMethTest instrucțiunea de comutare a funcției CAddInNative::GetParamDefValue.
Deoarece metoda „Test” poate returna o valoare, trebuie să faceți modificări codului funcției HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) (case eMethLoadPicture: case eMethTest: return true; default: return false; ) return false; )
Și adăugați codul executabil al metodei la funcție CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) (... std::wstring s1, s2; switch(lMethodNum) (case eMethLoadPicture: ...T break; dacă (!lSizeArray || !paParams) returnează fals; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; wstring_to_p(std::wstring(s1+s2), pvarRetValue); ret = adevărat ; pauză; ) întoarcere ret; )
Să compilam componenta și să aducem codul de configurare la forma:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); lane = DemoComp.Test("Bună, ", "Lumea!"); Notificare(per); EndProcedure
După începerea configurației, vom primi un mesaj: „Bună, lume!”, ceea ce indică faptul că metoda a funcționat cu succes.

Temporizator

O sarcină:
  1. Studiați implementarea temporizatorului în demo VK
  2. Modificați metoda „StartTimer” adăugând posibilitatea de a trece în parametri intervalul temporizatorului (în milisecunde)
  3. Verificați dacă modificările efectuate funcționează.

În WinAPI, pentru a lucra cu timpul, puteți folosi mesajul WM_TIMER. Acest mesaj va fi trimis programului dumneavoastră la intervalul de timp specificat la crearea cronometrului.
Pentru a crea un cronometru utilizați funcția SetTimer:
UINT SetTimer(HWND hWnd, // manevrarea ferestrei UINT nIDevent, // identificatorul temporizatorului (număr) UINT nElapse, // întârziere TIMERPROC lpTimerFunc); // indicatorul funcției
Sistemul de operare va trimite un mesaj WM_TIMER la programul cu intervalul specificat în argument nElapse(în milisecunde). În ultimul parametru, puteți specifica o funcție care va fi executată de fiecare dată când se declanșează temporizatorul. Antetul acestei funcții ar trebui să arate astfel (numele poate fi orice):
void __stdcall TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Luați în considerare implementarea temporizatorului în demo VK.
Deoarece luăm în considerare procesul de dezvoltare a unei componente externe pentru familia de sisteme de operare Windows, nu vom lua în considerare implementarea temporizatorului în alte sisteme de operare. Pentru sistemul de operare GNU/Linux, în special, implementarea va diferi în sintaxa funcției SetTimerși TimerProc.
Metoda este numită în codul executabil SetTimer, căruia i se transmite funcția MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
ID-ul temporizatorului creat este plasat într-o variabilă m_uiTimer pentru a-l putea opri mai târziu.
Funcţie MyTimerProc după cum urmează:
VOID CALLBACK MyTimerProc(HWND hwnd, // mânerul ferestrei pentru mesajele timer UINT uMsg, // WM_TIMER mesaj UINT idEvent, // identificator timer DWORD dwTime // ora curentă a sistemului) ( dacă (!pAsyncEvent) return; wchar_t *who = L „ComponentNative”, *what = L „Timer”; wchar_t *wstime = wchar_t nou; if (wstime) ( wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); pAsyncEvent->ExternalEvent(who , ce, wstime); șterge wstime; ))
Esența funcției este că metoda este numită Eveniment extern, care trimite un mesaj către sistemul 1C: Enterprise.
Pentru a extinde funcționalitatea metodei StartTimer hai sa facem urmatoarele:
Modificarea codului metodei GetNParams astfel încât să fie pentru metodă eMethStartTimer valoarea returnată 1:
caz eMethStartTimer: return 1;
Aici este codul metodei CallAsProc la vedere:
case 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;
Acum să verificăm funcționalitatea. Pentru a face acest lucru, în modulul aplicației gestionate al configurației, vom scrie codul:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); EndProcedure
După pornirea configurației, programul va primi mesaje cu un interval de 2 secunde, ceea ce indică funcționarea corectă a cronometrului.

Interacțiune cu sistemul 1C: Enterprise

Pentru a interacționa între componenta externă și sistemul 1C:Enterprise, metodele clasei IAddInDefBase descrise în fișier AddInDefBase.h. Enumerăm cele mai frecvent utilizate:
Generarea mesajelor de eroare
virtual bool ADDIN_API AddError(unsigned short wcode, const WCHAR_T* source, const WCHAR_T* descr, long code)
wcode, cod- coduri de eroare (o listă de coduri de eroare cu o descriere poate fi găsită pe discul ITS)
sursă- sursa erorii
descr- descrierea erorii
Trimiterea unui mesaj către sistemul 1C: Enterprise
virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- sursa mesajului
wszMessage- Mesaj text
wszData- datele transmise
Interceptarea mesajului se realizează prin procedura HandlingExternalEvent
Înregistrarea unei componente externe în sistemul 1C:Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- denumirea componentei.
Aceste metode sunt suficiente pentru interacțiunea completă a VK și 1C. Pentru a primi date de către o componentă externă din sistemul 1C:Enterprise și invers, componenta externă trimite un mesaj special, care, la rândul său, este interceptat de sistemul 1C și, dacă este necesar, apelează metodele componentei externe pentru a trimite date din spate.

tVariant tip de date

La schimbul de date între o componentă externă și sistemul 1C:Enterprise, se utilizează tipul de date tVariant. Este descris în fișierul types.h, care poate fi găsit pe discul 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 ushortVal; uint32_t ushortVal; uint32_t ushortVal; uint32_t ushortVal; uint32_t ushortVal; uint32_t; bVal; char chVal; wchar_t wchVal; DATA data; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NAME_2/*iface*/; _ANONYMOUS_STRUCT struct (_*3 STRUCT __; /număr de octeți ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //număr de simbol ) __VARIANT_NAME_4/*wstr*/; ) __VARIANT_NAME_1; uint32_t/uint32_element; în pvarVal TYPEVAR vt; );
Tip de tVariant este o structură care include:
  • amestec (unire) destinat direct stocării datelor
  • identificatorul tipului de date
În general, lucrul cu variabile de tip tVariant are loc conform următorului algoritm:
  1. Determinarea tipului de date stocate în prezent într-o variabilă
  2. Acces la câmpul corespunzător al amestecului, pentru acces direct la date
Utilizare tip tVariant simplifică foarte mult interacțiunea dintre sistemul 1C: Enterprise și o componentă externă

Aplicație

Directorul „exemple” conține exemple pentru articol
exemples/1 - rulați componenta demo
exemple/2 - demo extensie pentru lista de proprietăți
exemple/3 - demonstrarea extensiei listei de metode
Fiecare director conține un proiect VS 2008 și o configurație 1C prefabricată.

Adesea, programatorii au probleme la conectarea componentelor externe (de exemplu, drivere de echipamente comerciale) atunci când utilizatorii lucrează cu 1C conectându-se la server prin terminal.

În același timp, utilizatorii văd, de exemplu, poza prezentată în anunțul articolului.

În timp ce lucrați de pe computere locale, nu există probleme cu conectarea componentelor externe.

Cu ce ​​este legat? Acest lucru se datorează faptului că atunci când utilizatorii lucrează prin Terminal Server, au mai puține drepturi decât atunci când lucrează pe computerul local.

Acest lucru este ușor de verificat dacă vă conectați la serverul terminal sub un cont cu drepturi administrative.

Motivul acestei diferențe este că 1C nu poate înregistra o componentă externă în registru atunci când utilizatorul lucrează în terminal cu drepturi normale, deoarece un utilizator normal nu are permisiuni de scriere în ramura registrului de sistem HKEY_CLASSES_ROOT.

În publicațiile pe tema conectării componentelor externe în terminal, sunt oferite o varietate de metode pentru rezolvarea acestei probleme.

De exemplu, acestea:

1. Rulați 1C pentru prima dată cu drepturi administrative.

Această opțiune nu funcționează întotdeauna. Voi explica mai jos de ce.

2. Oferiți utilizatorilor obișnuiți ai terminalului dreptul de a scrie în filiala registrului de sistem HKEY_CLASSES_ROOT.

Utilizatorii insuficient de „avansați” nu ar trebui să facă acest lucru, altfel pot apărea probleme.

3. Folosind diverse „gadget” înregistrați VK în numele unui utilizator cu drepturi depline.

Nici să mănânci nu e bine.

Deci, care este cel mai bun mod de a ieși din această situație?

Ofer soluția mea la această problemă. După părerea mea - simplu și frumos, neoferit anterior la infostart.

Investigând această problemă, m-am întrebat - de ce încearcă 1C chiar să înregistreze VK pe o nouă cale? La urma urmei, este deja înregistrat în sistem.

Lucrul s-a dovedit a fi că în configurațiile tipice 1C (de exemplu, „Managementul comerțului”) este utilizată următoarea sintaxă a metodei contextului global ConnectExternalComponent() :

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

După cum puteți vedea, driverul VK este conectat din aspectul „DriverATOLScannerBarcode” din directorul „Echipament conectat”.

Ce se întâmplă atunci?

1C salvează componenta în folderul temporar al utilizatorului, de exemplu „C:\Documents and Settings\User\Local Settings\Temp\1032\v8_4_12.tmp”

și încearcă să-l înregistreze în ramura de registru HKEY_CLASSES_ROOT de-a lungul acestei căi.

Pe terminal, utilizatorii obișnuiți nu au drepturi de a schimba această ramură de registry, așa că componenta nu este conectată pentru ei.

Acum despre cum să ieși din această situație.

Metoda contextului global ConnectExternalComponent() are mai multe opțiuni de sintaxă. Acesta este ceea ce vom folosi.

Deci, pas cu pas:

1. Înregistrați componenta externă utilizând utilitarul regsvr32.exe pe serverul terminal în folderul C:\WINDOWS\SYSTEM32 pentru un sistem de operare pe 32 de biți sau în folderul C:\WINDOWS\SYSWOW64 pentru sistemul de operare pe 64 de biți.

2. Utilizați una dintre cele două opțiuni de sintaxă suplimentare pentru metoda ConnectExternalComponent():

Opțiunea 1:

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

DriverObject = New ("AddIn.ATOLScanner.Scanner45");

Opțiunea 2:

ProgID = "AddIn.Scanner45";

Conectați Componenta Externă (ProgID);

DriverObject = New(ProgID);

În opinia mea, opțiunea #2 este de preferat.

În același timp, 1C nu încearcă să reînregistreze VC-ul pe o nouă cale în registry și, astfel, toate problemele sunt rezolvate.

Ei bine, asta-i tot. Mult succes la job!

De exemplu, nu va fi posibil să rescrieți o componentă dacă nu sunteți autorul acesteia și pur și simplu nu există coduri sursă. Sau dacă cele mai simple tipuri suportate de tehnologia Native API (număr, șir, boolean, dată) nu sunt suficiente pentru funcționarea acesteia.

Nu există probleme speciale atunci când lucrați cu baza de fișiere. Sarcina programată este apelată în procesul de fundal al unui utilizator normal. Prin urmare, apelurile clienților îi sunt disponibile. Nu există un context client în baza de date a serverului când este pornită o sarcină programată, deci apelul ConnectExternalComponent() nu e disponibil.

În acest caz, puteți apela componenta pe client. Pentru a face acest lucru, este suficient să lansați încă o sesiune 1C din sarcina programată pe server în care să efectuați acțiunile necesare asupra clientului. Ei bine, nu uitați să încheiați sesiunea de rulare mai târziu.

Să presupunem că în sarcina noastră programată, generăm și salvăm un raport care utilizează componenta externă COM NameDeclension.dll pentru a refuza numele complet. Pe baza de fișiere, o astfel de sarcină programată va funcționa corect, dar nu va funcționa pe componenta serverului.

Pentru a remedia problema, să adăugăm o procedură la modulul de sarcini programate care va lansa o altă sesiune în modul server și în acesta va executa un apel de generare a raportului asupra clientului din procesare externă.

#If Client Then Procedure ExecuteFormationAndSavingReport() Export If ConnectExternalComponent("CommonLayout.NAMEDECL","Cl",ExternalComponentType.COM) Then Component = New ("AddIn.Cl.NameDeclension"); //Iată codul pentru generarea și salvarea raportului. ElseJoinRegisterLog("RegistTask", LevelJoinLog.Error, "Failed to connect the external component on the client"); EndIf; Sfârșitul procedurii #Otherwise Procedure ExecuteFormationAndSavingReport() Export ExecuteOperationOnClient("RegularTasks.ExecuteFormationAndSavingReport()"); EndProcedure Procedure PerformOperationOnClient(ParameterToExecute) ExportUserName = ""; UserPassword = ""; PathToExternalProcessing = "c:/temp/Autostart.epf"; Citat = """"; DirectoryBIN = DirectoryProgram(); PathToConfiguration = InfoBase ConnectionString(); ConfigurationPath = StrReplace(ConfigurationPath, Quote, Quote + Quote); StartString = Citat + Director Bin + „1cv8.exe” + Citat + „ ENTERPRISE” + „ /IBConnectionString „ + Citat + ConfigurationPath + Citat + „ /N „ + Citat + Nume utilizator + Citat + „ /P „ + Citat + Parola utilizator + Citat + „ /Execute „ + Citat + PathToExternalProcessing + Citat + „ /C „ + Citat + ParameterToExecute + Citat; StartApplication(StartString); EndProcedure #EndIf

Cod de procesare extern care va determina pur și simplu contextul clientului să imprime raportul necesar din modulul de joburi programate și să încheie sesiunea după generarea raportului.

Încercarea de a executa (StartupParameter); Excepție EndTry; ShutdownSystem (Fals);

Comoditatea soluției este că atunci când configurați sarcini programate, nu contează în ce mod va fi lansată sarcina. Dacă baza de date este una de fișiere, atunci procedura necesară va începe imediat. Dacă baza de date este pe partea serverului și nu există un context client la pornire, atunci o nouă sesiune va fi inițializată și procedura va funcționa corect în contextul clientului.

Cod pentru o aplicație tipică. Teoretic, va funcționa într-un mod complet similar într-unul gestionat.

p.s. De asemenea, această abordare poate fi utilizată pentru a executa orice proceduri client în joburi programate.

CLOPOTUL

Sunt cei care citesc aceasta stire inaintea ta.
Abonați-vă pentru a primi cele mai recente articole.
E-mail
Nume
Nume de familie
Cum ți-ar plăcea să citești Clopoțelul
Fără spam