Noile versiuni ale „1C: Trade Management”: actualizare fără dezvoltare. Rezolvarea problemelor legate de înregistrarea componentelor externe în terminal Extinderea listei de metode
O nouă versiune de configurare a fost lansată pe 23 octombrie „1C: Managementul comerțului”. Încă o dată, actualizarea a inclus modificări la VetIS, EGAIS, iar funcționalitatea generală a configurației aproape că nu a fost afectată.
Ce sa schimbat?
Dacă vă uitați la structura modificărilor care sunt incluse în cea mai recentă versiune de configurare „1C: Managementul comerțului”, apoi mai mult de jumătate este o actualizare pentru EGAIS, VetIS și doar câteva rânduri din descrierea lansării sunt dedicate extinderii funcționalității produsului software, care nu sunt stipulate de niciun act legislativ.
Secțiuni în care au avut loc modificări:
în vânzările cu amănuntul, a fost adăugat suport pentru citirea unui nou tip de cod de bare bidimensional de accize și timbre speciale federale care conțin identificatorul digital EGAIS;
integrarea cu sistemul de control veterinar (VetIS) a fost îmbunătățită;
schimbul cu sistemul EGAIS a fost îmbunătățit;
au fost adăugate noi caracteristici ale serviciului de schimb electronic de documente;
au fost aduse îmbunătățiri serviciului 1C: Business Network;
Integrarea cu Yandex.Checkout a fost îmbunătățită.
În ceea ce privește funcționalitatea generală, au fost aduse mai multe modificări la blocul de planificare și trezorerie. Și în mod tradițional adăugări constante la contabilitatea TVA.
În același timp, cea mai recentă versiune de configurație actuală „1C: Managementul comerțului” nu face excepție - acum dezvoltarea configurației pentru contabilitatea operațională este în principal pe calea soluționării problemelor care apar ca urmare a reglementării legislative în domeniul comerțului. Este logic ca susținerea cerințelor de reglementare să devină o prioritate mai mare și, în cele din urmă, să determină direcția de dezvoltare a soluției software în ansamblu.
Contabilitatea operațională devine reglementată?
Configurație tradițională „1C: Managementul comerțului” utilizate pentru automatizarea contabilității operaționale. Totodată, în legătură cu „1C: Contabilitate” era obișnuit să „descărcați” toate cerințele pentru modificarea funcționalității standard în „1C:UT”, pentru a menține capacitatea de a actualiza programul de contabilitate cu un efort minim.
Având în vedere volumul documentelor de reglementare pentru contabilitatea operațională în comerț și reflectarea acestor cerințe în configurația standard, există motive pentru a lua o abordare mai atentă pentru a face modificări la funcționalitatea standard a configurației de tranzacționare. De exemplu, problemele cu schimbul cu sistemul Mercur pot, dacă nu paraliza activitățile unui număr de întreprinderi, atunci pot duce la timpi de nefuncționare lungi, cel puțin.
Ca una dintre opțiunile de soluție, putem lua în considerare utilizarea mecanismului de extensie, mai ales că 1C utilizează în mod activ această funcționalitate. Desigur, această abordare va necesita muncă suplimentară din partea dezvoltatorilor. Dar aceasta este modalitatea optimă de a sprijini schimbările în configurațiile moderne.
O distribuție mai radicală a funcționalității între configurația standard va fi „1C: Managementul comerțului”şi unele sisteme contabile sau analitice externe. Aici, 1C a făcut din nou suficient pentru a rezolva în mod eficient aceste tipuri de probleme la nivel de platformă.
În orice caz, acum, atunci când proiectați sisteme de contabilitate corporativă și distribuiți funcționalitatea între configurații, trebuie să aveți în vedere: este posibil să aveți nevoie să actualizați „1C: Managementul comerțului” va trebui dacă nu la fel de des ca „1C: Contabilitate”, atunci cu siguranță nu de 1-2 ori pe an, așa cum au făcut mulți înainte.
- 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 versiunea 8.2 a sistemului 1C: Enterprise, care rulează sub sistemul de operare Windows cu un mod de funcționare fișier. Această opțiune este utilizată în majoritatea soluțiilor concepute pentru întreprinderile mici. VK va fi implementat în limbajul de programare C++.
Componente externe „1C: Enterprise”
„1C: Enterprise” este un sistem extensibil. Pentru a extinde funcționalitatea sistemului, sunt utilizate componente externe (EC). Din punctul de vedere al dezvoltatorului, un VC este un obiect extern care are proprietăți și metode și poate genera, de asemenea, evenimente pentru procesare de către sistemul 1C: Enterprise.Componentele externe pot fi folosite pentru a rezolva o clasă de probleme care sunt dificil sau chiar imposibil de implementat în limbajul de programare integrat î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 echipamente specifice.
Sistemul 1C: Enterprise folosește două tehnologii pentru a crea componente externe:
- folosind Native API
- folosind tehnologia COM
Structura VK
Componenta externă a sistemului 1C: Enterprise este prezentată sub forma unei biblioteci DLL. Codul bibliotecii descrie clasa descendentă IComponentBase. Clasa creată trebuie să definească metode responsabile de implementarea funcțiilor componentei externe. Metodele anulate vor fi descrise mai detaliat mai jos pe măsură ce materialul este prezentat.Lansarea unui demo VK
Sarcină:- Asamblați o componentă externă furnizată cu un abonament ITS și destinată să demonstreze principalele capacități ale mecanismului de componentă externă în 1C
- Conectați componenta demo la configurația 1C
- Asigurați-vă că funcțiile declarate funcționează corect
Compilare
VK-ul demo se află pe discul de abonament ITS în directorul „/VNCOMP82/example/NativeAPI”.Pentru a construi VC demo vom folosi Microsoft Visual Studio 2008. Alte versiuni ale acestui produs nu acceptă formatul de proiect Visual Studio utilizat.
Deschideți proiectul AddInNative. În setările proiectului, includem 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 fișierul /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 1C goală.Mai jos este codul pentru modulul aplicației gestionate.
variabila DemoComp; Procedură la pornirea sistemului() Conectați Componenta externă("...\bind\AddInNative.dll", "DemoVK", Tipul componentei externe.Native); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); Sfârșitul procedurii
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, un obiect apare în vizibilitatea globală a configurației DemoComp, care are proprietăți și metode care sunt definite în codul componentei externe.
Demonstrarea funcționalității încorporate
Să verificăm funcționalitatea 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 mesajul VK.Documentația furnizată pe discul ITS precizează următoarea funcționalitate a VC-ului demo:
- Gestionarea stării obiectului componente
Metode: Porniți, Opriți
Proprietăți: Inclus - Gestionarea cronometrului
În fiecare secundă, componenta trimite un mesaj către sistemul 1C: Enterprise cu parametri Componentă, Temporizatorși o linie de contor al ceasului de sistem.
Metode: StartTimer, StopTimer
Proprietăți: Există un cronometru - Metodă ShowInStatusLine, care afișează textul transmis metodei ca parametri în bara de stare
- Metodă Încarcă imagine. Încarcă o imagine din fișierul specificat și o transferă în sistemul 1C: Enterprise sub formă de date binare.
variabila DemoComp; Procedura la pornirea sistemului() ConnectExternalComponent(...); DemoComp = New ("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Raport (DemoComp.Activat); DemoComp.Enable(); Raport (DemoComp.Activat); DemoComp.StartTimer(); Sfârșitul procedurii Procesare externă a evenimentelor (Sursă, Eveniment, Date) Raport (Sursă + " " + Eveniment + " " + Date); Sfârșitul procedurii
Rezultatul rulării configurației este afișat în imagine
Panoul „Mesaje” afișează rezultatele apelurilor de metodă DemoComp.Disable()Și Demo.Comp.Enable(). Rândurile ulterioare din același panou conțin rezultatele procesării mesajelor primite de la VK - Sursă, EvenimentȘi Date respectiv.
Nume personalizat de componentă externă
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- acesta este numele extensiei.
Codul VK definește o metodă RegisterExtensionAs, returnând numele sistemului 1C: Enterprise, care este necesar pentru înregistrarea ulterioară a VK-ului în sistem. Se recomandă specificarea unui identificator care dezvăluie într-o oarecare măsură 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 dat, numele VK este schimbat în SomeName. Apoi, atunci când vă conectați VK, trebuie să specificați un nume nou:
DemoComp = New("AddIn.DemoVK.SomeName");
Extinderea listei de proprietăți VK
Sarcină:- Studiați implementarea proprietăților VK
- Adăugați o proprietate de citire/scriere de tip șir
- Adăugați o proprietate ș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 determina proprietățile componentei care se creează, dezvoltatorul trebuie să implementeze următoarele metode în codul bibliotecii AddInNative.cpp:
GetNProps
Returnează numărul de proprietăți ale acestei extensii, 0 dacă nu există proprietăți
FindProp
Returnează numărul de serie al proprietății al cărei nume este trecut în parametri
GetPropName
Returnează numele proprietății după numărul de serie și prin identificatorul de limbă transmis
GetPropVal
Returnează valoarea proprietății cu numărul ordinal specificat
SetPropVal
Setează valoarea proprietății cu numărul ordinal specificat
IsPropReadable
Returnează indicatorul de lizibilitate al proprietății cu numărul de secvență specificat
IsPropWritable
Returnează indicatorul de scriere al proprietății cu numărul de secvență specificat
Să luăm în considerare implementarea metodelor de clasă de mai sus CAddInNative.
În VC demonstrativ, sunt definite 2 proprietăți: InclusȘi Există un cronometru (Este activatȘi IsTimerPresent).
În domeniul global al codului bibliotecii, sunt definite două matrice:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Activat", L"Există un temporizator");
care stochează nume de proprietate în limba rusă și engleză. În fișierul antet AddInNative.h enumerarea 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 de serie 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 numai în cadrul codului componentei și nu sunt disponibile din exterior.
Metodele FindProp și GetPropName efectuează căutări în matrice g_PropNamesȘi g_PropNamesRu.
Pentru a stoca valorile câmpurilor din modulul bibliotecă, clasa CAddInNative are proprietăți care stochează valoarea proprietăților componente. Metode GetPropValȘi SetPropVal returnați și setați valoarea acestor proprietăți în consecință.
Metode IsPropReadableȘi IsPropWritableși întoarce-te Adevărat sau fals, în funcție de numărul ordinal transmis al proprietății în conformitate cu logica aplicației.
Pentru a adăuga o proprietate personalizată, trebuie să:
- Adăugați numele proprietății care este adăugată la matrice g_PropNamesȘi g_PropNamesRu(fişier AddInNative.cpp)
- A lista Recuzită(fişier AddInNative.h) inainte de ePropLast adăugați un nume care identifică în mod unic proprietatea adăugată
- Organizați memoria pentru stocarea valorilor proprietăților (creați câmpuri componente ale modulului care stochează valorile corespunzătoare)
- Faceți modificări metodelor GetPropValȘi SetPropVal pentru a interacționa cu memoria alocată în pasul anterior
- În conformitate cu logica aplicației, efectuați modificări metodelor IsPropReadableȘi IsPropWritable
Să dăm nume proprietăților testului TestȘi Verificare tip respectiv. Apoi, ca rezultat al pasului 1, avem:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Activat", L"Există un temporizator", L"Test", L"Verificare tip");
Transfer 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, haideți să conectăm biblioteca wstring.
Pentru a salva valoarea unei metode Test, definim în clasă CAddInNativeîn domeniul privat:
string test1;
Pentru a transfera parametrii șir între componentele 1C: Enterprise și externe, se folosește 1C: Manager de memorie Enterprise. Să aruncăm o privire mai atentă la munca lui. Funcțiile sunt folosite pentru a aloca și, respectiv, elibera memorie AllocMemoryȘi Memorie libera definite în dosar ImemoryManager.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 zonei de memorie alocată,
ulCountByte- dimensiunea zonei de memorie alocată.
Un exemplu de alocare de memorie 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, vom descrie funcția wstring_to_p. Primește 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 salva tipul ultimei valori transferate. Pentru a face acest lucru, adăugați comanda 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, ceea ce necesită sarcina desemnată.
Să verificăm funcționalitatea modificărilor făcute.
Pentru a face acest lucru, să prezentăm aspectul configurației 1C după cum urmează:
variabila DemoComp; Procedură la pornirea sistemului() Conectare componentă externă("...", "DemoVK", Tip componentă externă.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Raport(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raport(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raport(String(DemoComp.Test)); Raport(String(DemoComp.TypeCheck)); Sfârșitul procedurii
Ca urmare a lansării, vom primi o secvență de mesaje:
3
Vasia
Petru
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
Sarcină:- Extindeți funcționalitatea componentei externe cu următoarea funcționalitate:
- Explorați modalități de implementare a metodelor componentelor externe
- Adăugați o metodă de funcție Funcția 1, care ia două șiruri de caractere („Parameter1” și „Parameter2”) ca parametru. Rezultatul este un șir de genul: „Verificare. Parametrul 1, Parametrul 2"
- Asigurați-vă că modificările pe care le faceți 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 numărul corespunzător de metode, căutați numărul și numele metodei. Similar cu metodele corespunzătoare pentru proprietăți
GetNParams
Returnează numărul de parametri ai metodei cu numărul de secvență specificat; dacă o metodă cu acest număr este absentă sau nu are parametri, returnează 0
GetParamDefValue
Returnează valoarea implicită a parametrului specificat al metodei specificate
HasRetVal
Returnează indicatorul dacă metoda cu valoarea de returnare ordinală specificată are o valoare returnată: 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 este încheiată. Memoria pentru matricea de parametri este alocată și eliberată de 1C: Enterprise.
CallAsFunc
Execută metoda cu numărul de ordine specificat. Dacă metoda revine fals, apare o eroare de rulare și execuția modulului 1C: Enterprise este încheiată. Memoria pentru matricea de parametri este alocată de 1C: Enterprise. Dacă valoarea returnată este un șir sau un tip de 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. 1C: Întreprinderea va elibera această memorie prin apel Memorie libera.
O descriere completă a metodelor, inclusiv o listă de parametri, este descrisă în detaliu în documentația furnizată pe discul ITS.
Să luăm î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 executabil direct al metodei.
Pentru a adăuga o metodă care poate fi apelată doar ca funcție, trebuie să faceți următoarele modificări la codul sursă al componentei externe:
- Adăugați numele metodei la matrice g_MethodNamesȘi g_MethodNamesRu(fişier AddInNative.cpp)
- Adăugați un identificator de metodă semnificativ la enumerarea Metode (fișier AddInNative.h)
- Efectuați modificări la codul funcției GetNParams conform logicii programului
- Dacă este necesar, faceți modificări la codul metodei GetParamDefValue, dacă doriți să utilizați valorile implicite ale parametrilor metodei.
- Efectuați modificări ale funcției HasRetVal
- Faceți modificări în logica funcțiilor CallAsProc sau CallAsFunc, plasând acolo codul executabil direct al metodei
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"LoadPicture", 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; switch(lMethodNum) (case eMethEnable:case eMethStatue:hocase eMethStatue:hocase eLineStatus tTime r: caz eMethStopTimer: caz eMethTest: // Nu există valori ale parametrilor în mod implicit break; implicit: return false; ) return false; )
Mulțumită liniei adăugate
caz eMethTest:
dacă lipsesc unul sau mai multe argumente, parametrii corespunzători vor avea o valoare goală ( VTYPE_EMPTY). Dacă aveți nevoie de o valoare implicită pentru un parametru, ar trebui să o setaț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:
variabila DemoComp; Procedură la pornirea sistemului() Conectare componentă externă("...", "DemoVK", Tip componentă externă.Native); DemoComp = New("AddIn.DemoVK.SomeName"); lane = DemoComp.Test ("Bună ziua," "Lumea!"); Raport (per); Sfârșitul procedurii
După lansarea configurației, vom primi mesajul: „Hello, World!”, care indică faptul că metoda a funcționat cu succes.
Temporizator
Sarcină:- Studiați implementarea temporizatorului în demo VK
- Modificați metoda „StartTimer” adăugând posibilitatea de a trece în parametri intervalul de răspuns al temporizatorului (în milisecunde)
- Asigurați-vă că modificările pe care le faceți funcționează.
În WinAPI, puteți folosi mesajul pentru a lucra cu timpul WM_TIMER. Acest mesaj va fi trimis programului dumneavoastră la intervalul de timp pe care l-ați setat la crearea cronometrului.
Pentru a crea un cronometru, utilizați funcția SetTimer:
UINT SetTimer(HWND hWnd, // descriptor de fereastră UINT nIDevent, // identificator timer (număr) UINT nElapse, // întârziere TIMERPROC lpTimerFunc); // pointer către funcție
Sistemul de operare va trimite un mesaj WM_TIMERîn program 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ă cronometrul. 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)
Să luăm în considerare implementarea unui temporizator în VC demonstrativ.
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.
Codul executabil apelează metoda 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 putea fi dezactivat ulterior.
Funcţie MyTimerProc după cum urmează:
VOID CALLBACK MyTimerProc(HWND hwnd, // handle of window for timer messages UINT uMsg, // WM_TIMER message UINT idEvent, // timer identifier DWORD dwTime // time system current) (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 Să facem următoarele:
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 forma:
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, vom scrie codul în modulul aplicației gestionate al configurației:
variabila DemoComp; Procedură la pornirea sistemului() Conectare componentă externă("...", "DemoVK", Tip componentă externă.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Sfârșitul procedurii
După pornirea configurației, programul va primi mesaje la intervale de 2 secunde, ceea ce indică faptul că temporizatorul funcționează corect.
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. Le enumerăm pe cele mai frecvent utilizate:Generarea unui mesaj 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 descrieri 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 mesajelor se realizează prin procedura de procesare externă a evenimentelor
Înregistrarea unei componente externe în sistemul 1C: Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- denumirea componentei.
Aceste metode sunt suficiente pentru o interacțiune completă între VK și 1C. Pentru a primi date de către o componentă externă de la 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 transmite date înapoi. .
tVariant tip de date
La schimbul de date între componenta externă și sistemul 1C: Enterprise, este utilizat tipul de date tVariant. Este descris în fișierul types.h, care poate fi găsit pe discul ITS:struct _tVariant ( _ANONYMOUS_UNION uniune ( 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 ullV al4_Valur; uint32_t al4_Valur; Res; float fltVal; dublu dblVal; bool 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*/; _STRUCTstrANONYMO u; int32_t strLen ; //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*/; ) _2_1VARIANT_NUME_2_1Element; pentru o matrice unidimensională în pvarVal TYPEVAR vt; );
Tip tVariant este o structură care include:
- amestec (unire) destinat direct stocării datelor
- identificatorul tipului de date
- Determinarea tipului de date stocate în prezent într-o variabilă
- Accesați câmpul de amestec corespunzător pentru a accesa direct datele
Aplicație
Directorul „exemple” conține exemple pentru articolexemple/1 - lansați componenta demo
exemple/2 - demonstrarea extinderii listei de proprietăți
exemple/3 - demonstrarea extinderii listei de metode
Fiecare director conține un proiect VS 2008 și o configurație 1C gata făcută.
Opțiune de sintaxă: După nume și locație
Sintaxă:
ConnectExternalComponent(<Местоположение>, <Имя>, <Тип>)
Opțiuni:
<Местоположение>(necesar)
Tip: șir.
Locația componentei externe.
Locația poate fi folosită:
calea către fișierul component extern de pe sistemul de fișiere (nu este disponibil pe clientul web), nu o arhivă ZIP;
numele complet calificat al aspectului care stochează datele binare sau arhiva ZIP;
URL-ul către componenta externă, ca date binare sau arhivă ZIP, într-un format similar cu GetNavigationLink.
<Имя>(necesar)
Tip: șir.
Numele simbolic al componentei externe de conectat.
Numele trebuie să respecte convențiile de denumire ale limbajului încorporat.
<Тип>(optional)
Tip: ExternalComponentType.
Tipul de componentă externă care trebuie conectată.
Nu este utilizat dacă componenta este ambalată într-o arhivă ZIP.
Descrierea opțiunii de metodă:
Conectează componente realizate folosind tehnologia nativă și COM.
Componenta poate fi stocată în baza de informații sau în configurația ca date binare sau într-o arhivă ZIP.
Pentru modurile de lansare „Thin Client” și „Web Client”, componenta trebuie mai întâi instalată utilizând metoda Instalare componente externe.
Opțiune de sintaxă: După ID
Sintaxă:
ConnectExternalComponent(<ИдентификаторОбъекта>)
Opțiuni:
<ИдентификаторОбъекта>(necesar)
Tip: șir.
Identificatorul obiectului component extern sub forma ProgID (Identificatorul programatic) al registrului MS Windows (de exemplu: „AddIn.Scanner”).
Trebuie să corespundă informațiilor din baza de date de înregistrare a sistemului (Registry).
Descrierea opțiunii de metodă:
Componenta trebuie implementată folosind tehnologia COM și înregistrată în registrul MS Windows.
Aceste componente sunt compatibile cu componentele 1C:Enterprise 7.7.
Atenţie! Opțiunea de metodă nu funcționează pe server și în conexiunea externă.
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 din baza de informații care sunt ambalate într-o arhivă.
Clientul subțire poate lucra cu componente din baza de informații, ambalate într-o arhivă și cu componente situate în sistemul de fișiere.
Clientul gros poate gestiona toate opțiunile de stocare a componentelor. În acest caz, dacă o componentă este instalată folosind metoda Instalare componentă externă, atunci componenta instalată este utilizată, iar dacă nu este instalată, componenta va fi primită în momentul conectării.
Serverul poate funcționa cu toate componentele. Componenta este stocată în cache pentru fiecare sesiune de server.
Exemplu:
Dacă ConnectExternalComponent ("AddinObject.Scanner"), atunci
Raport(„Componenta pentru scanerul de coduri de bare încărcate”);
In caz contrar
Raport ("Componenta pentru scanerul de coduri de bare nu este încărcată");
endIf;
Întrebare: API nativă componentă externă în C++ pentru Linux (Ubuntu x64) pe 1C 8.3
Scriu la VK, dar nu mă pot conecta la 1c pe ubuntu. Nici măcar executabilul de la 1c nu se conectează. Deci o intrebare despre asta:
1) Încerc să conectez VK din exemplul VNCOMPS dat în articol
(linkul poate fi găsit la sfârșit: „Copiere”).
Există un makefile în interiorul proiectului NativeApi. Cu ajutorul lui, construiesc o bibliotecă .so pe Ununtu.
Dar când „Conectează componenta externă” 1c se blochează.
La fel, dacă construiesc folosind „build.sh” (în 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 conecteaza)
Iată un exemplu de apelare a VK din 1C 8.3:
Conexiune gata = ConnectExternalComponent("/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, în esență, este o chestiune de parametri de compilare. O componentă externă MB pe 32 de biți se conectează la un 1c pe 32 de biți în mod normal, dar am implementat-o pe Ubuntu x64 1c enterprise83 8.3.5-1486 amd64. Și vreau să mă conectez cu ea pe VK.
Are cineva vreo idee despre cum să rezolvi această problemă?)
Exemplul VNCOMPS ar trebui să funcționeze, dar parametrii de compilare trebuie ajustați sau platforma în sine pe care testez este incorectă.
Răspuns: Mă întreb, este posibil să scrii o componentă externă în Java?
Întrebare: Componenta externă (nativă) nu poate fi conectată
Am compilat un exemplu cu ITS, pentru sisteme pe 64 și 32 de biți.
Mă conectez așa:
Rezultat conexiune = ConnectExternalComponent(KDLLPath, "Comp", ExternalComponentType.Native); Conexiunea funcționează pe un PC, dar nu pe celălalt. Există o diferență în sistemul de operare. Unde se face conexiunea, există Win7, unde nu există Win10. În același timp, pe PC-ul unde componenta mea nu funcționează, funcționează componentele standard.
Testat pe diferite platforme (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).
Cum pot înțelege de ce nu se conectează?
Răspuns: vc_redist ați uitat?
Întrebare: 1C8 și o componentă externă cu tipul Nativ