Ulkoisten komponenttien tekniikka (). Ulkoisten komponenttien tekniikka () Tietotyyppi tVariant

ansmirnov 22. elokuuta 2013 klo 14.12

Ulkoiset komponentit kohdassa 1C 8.2

  • Ohjelmointi,
  • C++
  • Opetusohjelma

Johdanto

Tämä artikkeli antaa käsityksen siitä, kuinka ulkoiset komponentit toimivat 1C: Enterprise -järjestelmässä.
Näytetään ulkoisen komponentin kehitysprosessi 1C: Enterprise -järjestelmän versiolle 8.2, joka toimii Windows-käyttöjärjestelmässä tiedostotoiminnolla. Tätä vaihtoehtoa käytetään useimmissa pienille yrityksille suunnitelluissa ratkaisuissa. VK toteutetaan C++-ohjelmointikielellä.

Ulkoiset komponentit "1C: Enterprise"

"1C: Enterprise" on laajennettava järjestelmä. Järjestelmän toiminnallisuuden laajentamiseksi käytetään ulkoisia komponentteja (EC). Kehittäjän näkökulmasta VC on ulkoinen objekti, jolla on ominaisuuksia ja menetelmiä ja joka voi myös luoda tapahtumia 1C: Enterprise -järjestelmän käsittelyä varten.
Ulkoisia komponentteja voidaan käyttää ratkaisemaan ongelmia, joita on vaikea tai jopa mahdoton toteuttaa 1C: Enterprisen sisäänrakennetulla ohjelmointikielellä. Erityisesti tämä luokka sisältää tehtäviä, jotka vaativat matalan tason vuorovaikutusta käyttöjärjestelmän kanssa, esimerkiksi tiettyjen laitteiden kanssa työskentelyyn.
1C: Enterprise -järjestelmä käyttää kahta tekniikkaa ulkoisten komponenttien luomiseen:
  • käyttämällä alkuperäistä APIa
  • käyttämällä COM-tekniikkaa
Annetut rajoitukset huomioiden ero kahden edellä mainitun teknologian välillä on merkityksetön, joten harkitsemme videopelien kehittämistä Native API:lla. Toteutettuja kehityssuuntia voidaan tarvittaessa soveltaa COM-teknologiaa käyttävien tietokoneohjelmistojen kehittämiseen, ja myös pienin muutoksin soveltaa 1C: Enterprise -järjestelmään myös muilla toimintavaihtoehdoilla kuin tiedoston käyttötilalla.
VK rakenne
1C: Enterprise -järjestelmän ulkoinen komponentti esitetään DLL-kirjaston muodossa. Kirjastokoodi kuvaa jälkeläisluokkaa IComponentBase. Luodun luokan tulee määrittää menetelmät, jotka vastaavat ulkoisen komponentin toimintojen toteuttamisesta. Ohitettavia menetelmiä kuvataan tarkemmin alla materiaalia esitettäessä.

Demo-VK:n käynnistäminen

Tehtävä:
  1. Kokoa ulkoinen komponentti, joka toimitetaan ITS-tilauksen mukana ja jonka tarkoituksena on osoittaa ulkoisen komponenttimekanismin pääominaisuudet 1C:ssä
  2. Liitä demokomponentti 1C-kokoonpanoon
  3. Varmista, että ilmoitetut funktiot toimivat oikein
Kokoelma
Demo-VK sijaitsee ITS-tilauslevyllä "/VNCOMP82/example/NativeAPI"-hakemistossa.
Demo-VC:n rakentamiseen käytämme Microsoft Visual Studio 2008:aa. Muut tämän tuotteen versiot eivät tue käytettyä Visual Studio -projektimuotoa.


Avaa AddInNative-projekti. Sisällytämme projektiasetuksiin hakemiston, jossa on projektin rakentamiseen tarvittavat otsikkotiedostot. Oletusarvoisesti ne sijaitsevat ITS-levyllä hakemistossa /VNCOMP82/sisältää.
Rakennuksen tulos on tiedosto /bind/AddInNative.dll. Tämä on käännetty kirjasto 1C-kokoonpanoon yhdistämistä varten.
VK:n yhdistäminen 1C-kokoonpanoon
Luodaan tyhjä 1C-kokoonpano.
Alla on hallitun sovellusmoduulin koodi.
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() Yhdistä ulkoinen komponentti("...\bind\AddInNative.dll", "DemoVK", ulkoisen komponentin tyyppi.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); Menettelyn loppu
Jos virhettä ei raportoitu 1C-kokoonpanon käynnistämisen yhteydessä, VK yhdistettiin onnistuneesti.
Yllä olevan koodin suorittamisen seurauksena objekti ilmestyy konfiguraation globaaliin näkyvyyteen DemoComp, jolla on ominaisuuksia ja menetelmiä, jotka on määritelty ulkoisen komponentin koodissa.
Sisäänrakennetun toiminnallisuuden esittely
Tarkastellaan demo-VK:n toimivuutta. Tätä varten yritetään asettaa ja lukea joitain ominaisuuksia, kutsua joitain VK-menetelmiä ja myös vastaanottaa ja käsitellä VK-viesti.
ITS-levyllä toimitetussa dokumentaatiossa mainitaan seuraavat demo-VC:n toiminnot:
  1. Hallinnoi komponenttiobjektin tilaa
    Menetelmät: Kiihottua, Kytke pois päältä
    Ominaisuudet: Mukana
  2. Ajastimen hallinta
    Joka sekunti komponentti lähettää parametreilla viestin 1C: Enterprise -järjestelmään Komponentti, Ajastin ja järjestelmän kellon laskurilinja.
    Menetelmät: Aloitusajastin, StopTimer
    Ominaisuudet: On ajastin
  3. Menetelmä ShowInStatusLine, joka näyttää tilarivillä menetelmälle parametreina välitetyn tekstin
  4. Menetelmä Lataa kuva. Lataa kuvan määritetystä tiedostosta ja siirtää sen 1C: Enterprise -järjestelmään binääritietojen muodossa.
Varmistetaan, että nämä toiminnot toimivat. Voit tehdä tämän suorittamalla seuraavan koodin:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Raportti(DemoComp.Enabled); DemoComp.Enable(); Raportti(DemoComp.Enabled); DemoComp.StartTimer(); Toimenpiteen lopetusmenettely Ulkoisen tapahtuman käsittelyn (lähde, tapahtuma, tiedot) raportti (lähde + " " + Tapahtuma + " " + tiedot); Menettelyn loppu
Konfiguroinnin tulos näkyy kuvassa


Viestit-paneeli näyttää menetelmäkutsujen tulokset DemoComp.Disable() Ja Demo.Comp.Enable(). Saman paneelin seuraavat rivit sisältävät VK:lta saatujen viestien käsittelytulokset - Lähde, Tapahtuma Ja Data vastaavasti.

Mukautettu ulkoisen komponentin nimi

Tehtävä: Muuta ulkoisen komponentin nimi mielivaltaiseksi.
Edellisessä osiossa käytettiin tunnistetta AddInNativeExtension, jonka merkitystä ei selitetty. Tässä tapauksessa AddInNativeExtension- tämä on laajennuksen nimi.
VK-koodi määrittelee menetelmän RegisterExtensionAs, palauttaa nimen 1C: Enterprise -järjestelmään, mikä on tarpeen VK:n myöhempää rekisteröintiä varten järjestelmään. On suositeltavaa määrittää tunniste, joka jossain määrin paljastaa ulkoisen komponentin olemuksen.
Tässä on menetelmän täydellinen koodi RegisterExtensionAs jonka laajennuksen nimi on muutettu:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* kohde = 0; if (m-m_Alloc_iMemory ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) return false;
Annetussa esimerkissä VK-nimi muutetaan muotoon SomeName. Sitten kun yhdistät VK:n, sinun on määritettävä uusi nimi:
DemoComp = Uusi("AddIn.DemoVK.SomeName");

VK-ominaisuuksien luettelon laajentaminen

Tehtävä:
  1. Tutki VK-ominaisuuksien toteutusta
  2. Lisää merkkijonotyyppinen luku/kirjoitusominaisuus
  3. Lisää luku/kirjoitusmerkkijonoominaisuus, joka tallentaa viimeisen ominaisuusjoukon tietotyypin. Ominaisuuden arvoa määritettäessä ei tehdä mitään

Luotavan komponentin ominaisuuksien määrittämiseksi kehittäjän on otettava käyttöön seuraavat menetelmät AddInNative.cpp-kirjastokoodissa:
Hanki Nprops
Palauttaa tämän laajennuksen ominaisuuksien lukumäärän, 0, jos ominaisuuksia ei ole
FindProp
Palauttaa sen ominaisuuden sarjanumeron, jonka nimi on välitetty parametreissa
Hanki PropName
Palauttaa ominaisuuden nimen sen sarjanumeron ja hyväksytyn kielitunnisteen perusteella
GetPropVal
Palauttaa ominaisuuden arvon määritetyllä järjestysnumerolla
SetPropVal
Asettaa ominaisuuden arvon määritetyllä järjestysnumerolla
IsPropReadable
Palauttaa ominaisuuden luettavuuslipun määritetyllä järjestysnumerolla
IsPropWritable
Palauttaa ominaisuuden kirjoitettavuuslipun määritetyllä järjestysnumerolla


Tarkastellaanpa yllä olevien luokkamenetelmien toteutusta CAddInNative.
Demo-VC:ssä määritellään 2 ominaisuutta: Mukana Ja On ajastin (On kytketty Ja IsTimerPresent).
Kirjastokoodin globaalissa laajuudessa määritellään kaksi taulukkoa:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Käytössä", L"Ajastin on olemassa");
joka tallentaa venäjän ja englannin kiinteistöjen nimet. Otsikkotiedostossa AddInNative.h luettelo on määritelty:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Aina viimeinen );
ePropIsEnabled Ja ePropIsTimerPresent, joiden arvot ovat 0 ja 1, käytetään korvaamaan kiinteistöjen sarjanumerot merkityksellisillä tunnisteilla. ePropLastia, jonka arvo on 2, käytetään ominaisuuksien lukumäärän saamiseksi (GetNprops-menetelmällä). Näitä nimiä käytetään vain komponenttikoodissa, eivätkä ne ole saatavilla ulkopuolelta.
FindProp- ja GetPropName-menetelmät suorittavat taulukkohakuja g_PropNames Ja g_PropNamesRu.
Kenttien arvojen tallentamiseksi kirjastomoduuliin CAddInNative-luokassa on ominaisuuksia, jotka tallentavat komponentin ominaisuuksien arvon. menetelmät GetPropVal Ja SetPropVal palauttaa ja asettaa näiden ominaisuuksien arvot vastaavasti.
menetelmät IsPropReadable Ja IsPropWritable ja palata totta tai väärä, riippuen kiinteistön hyväksytystä järjestysnumerosta sovelluslogiikan mukaisesti.
Jotta voit lisätä mukautetun ominaisuuden, sinun on:

  1. Lisää taulukoihin lisättävän ominaisuuden nimi g_PropNames Ja g_PropNamesRu(tiedosto AddInNative.cpp)
  2. Listata Rekvisiitta(tiedosto AddInNative.h) ennen ePropLast lisää nimi, joka yksilöi lisättävän ominaisuuden
  3. Järjestä muisti ominaisuusarvojen tallentamista varten (luo moduulikomponenttikentät, jotka tallentavat vastaavat arvot)
  4. Tee muutoksia menetelmiin GetPropVal Ja SetPropVal olla vuorovaikutuksessa edellisessä vaiheessa varatun muistin kanssa
  5. Tee muutoksia menetelmiin sovelluslogiikan mukaisesti IsPropReadable Ja IsPropWritable
Kohdat 1, 2, 5 eivät kaipaa selitystä. Yksityiskohtaiset tiedot näiden vaiheiden toteuttamisesta löytyvät tutkimalla artikkelin liitettä.
Annetaan testiominaisuuksille nimet Testata Ja Tyyppitarkistus vastaavasti. Sitten vaiheen 1 tuloksena meillä on:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Käytössä", L"Ajastin on", L"Testi", L"Tyyppitarkistus");
Siirtää Rekvisiitta näyttää tältä:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Aina viimeinen );
Yksinkertaistaaksemme koodia merkittävästi, käytämme STL C++:aa. Erityisesti kielten kanssa työskentelyyn WCHAR, yhdistetään kirjasto wstring.
Tallentaaksesi menetelmän arvon Testata, määrittelemme luokassa CAddInNative yksityisellä alalla:
merkkijono testi1;
Merkkijonoparametrien siirtämiseen 1C: Enterprisen ja ulkoisten komponenttien välillä käytetään 1C: Enterprise -muistinhallintaa. Katsotaanpa tarkemmin hänen töitään. Toimintoja käytetään muistin varaamiseen ja vapauttamiseen AllocMemory Ja Vapaa muisti, määritelty tiedostossa ImemoryManager.h. Jos on tarpeen välittää merkkijonoparametri 1C: Enterprise -järjestelmään, ulkoisen komponentin on varattava sille muistia kutsumalla funktiota AllocMemory. Sen prototyyppi näyttää tältä:
virtuaalinen bool ADDIN_API AllocMemory (void** pMemory, allekirjoittamaton pitkä ulCountByte) = 0;
Missä pMuisti- sen osoittimen osoite, johon varatun muistialueen osoite sijoitetaan,
ulCountByte- varatun muistialueen koko.
Esimerkki muistin varaamisesta merkkijonolle:
WCHAR_T *t1 = NULL, *testi = L"TESTI_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, testi1, iActualSize);
Merkkijonotietotyyppien kanssa työskentelyn helpottamiseksi kuvaamme toiminnon wstring_to_p. Se vastaanottaa parametrina wstring-merkkijonon. Toiminnon tuloksena on täytetty rakenne tVariantti. Toimintokoodi:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( merkki* t1; TV_VT(arvo) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * sizeof(WCHAR_T)); memcpy(t1, str.c_str(), (str.length()+1) * koko(WCHAR_T) val -> pstrVal = t1; palauta tosi)
Sitten vastaava tapaus osa menetelmän kytkinlauseesta GetPropVal tulee muodossa:
tapaus ePropTest1: wstring_to_p(test1, pvarPropVal); tauko;
Menetelmä SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) return false; testi1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); tauko;
Toteuttaaksemme toisen ominaisuuden määrittelemme luokkakentän CaddInNative
uint8_t last_type;
johon tallennamme viimeksi siirretyn arvon tyypin. Voit tehdä tämän lisäämällä komennon CaddInNative::SetPropVal-metodiin:
viimeinen_tyyppi = TV_VT(varPropVal);
Nyt kun pyydämme lukemaan toisen ominaisuuden arvon, palautamme arvon viimeinen_tyyppi, mitä määrätty tehtävä edellyttää.
Tarkastellaan tehtyjen muutosten toimivuutta.
Tätä varten esittelemme 1C-kokoonpanon ulkoasun seuraavasti:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy () Yhdistä ulkoinen komponentti ("...", "DemoVK", ulkoisen komponentin tyyppi. Alkuperäinen); DemoComp = Uusi("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Raportti(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raportti(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raportti(String(DemoComp.Test)); Raportti(String(DemoComp.TypeCheck)); Menettelyn loppu
Käynnistyksen seurauksena saamme viestisarjan:
3
Vasja
Peter
22

Toinen ja kolmas viesti ovat tulosta edellisessä vaiheessa asetettujen ominaisuuksien lukemisesta. Ensimmäinen ja toinen viesti sisältävät viimeisen ominaisuusjoukon tyyppikoodin. 3 vastaa kokonaislukuarvoa, 22 merkkijonoarvoa. Tyyppien ja niiden koodien vastaavuus selvitetään tiedostosta tyypit.h, joka sijaitsee ITS-levyllä.

Menetelmien luettelon laajentaminen

Tehtävä:
  1. Laajenna ulkoisen komponentin toimintoja seuraavilla toiminnoilla:
  2. Tutki tapoja toteuttaa ulkoisia komponenttimenetelmiä
  3. Lisää funktiomenetelmä Toiminto1, joka ottaa kaksi merkkijonoa ("Parametri1" ja "Parametri2") parametrina. Tuloksena on merkkijono, kuten: "Tarkistaa. Parametri1, Parametri2"
  4. Varmista, että tekemäsi muutokset toimivat.

Määrittääkseen luotavan komponentin menetelmät kehittäjän on otettava käyttöön seuraavat menetelmät AddInNative-kirjastokoodissa:
GetNMethods, FindMethod, GetMethodName
Suunniteltu hankkimaan vastaava määrä menetelmiä, etsi menetelmän numero ja nimi. Samanlainen kuin vastaavat ominaisuuksien menetelmät
Hanki NParams
Palauttaa menetelmäparametrien määrän määritetyllä järjestysnumerolla; jos menetelmä, jolla on tämä numero, puuttuu tai sillä ei ole parametreja, palauttaa arvon 0
GetParamDefValue
Palauttaa määritetyn menetelmän määritetyn parametrin oletusarvon
HasRetVal
Palauttaa lipun siitä, onko menetelmällä, jolla on määritetty järjestysarvo, palautusarvo: true menetelmille, joilla on palautusarvo ja väärä muuten
CallAsProc
väärä, tapahtuu ajonaikainen virhe ja 1C: Enterprise -moduulin suoritus lopetetaan. 1C: Enterprise varaa ja vapauttaa muistin parametrijoukolle.
CallAsFunc
Suorittaa menetelmän määritetyllä järjestysnumerolla. Jos menetelmä palaa väärä, tapahtuu ajonaikainen virhe ja 1C: Enterprise -moduulin suoritus lopetetaan. 1C: Enterprise varaa muistin parametrijoukolle. Jos palautusarvo on merkkijono tai binääritietotyyppi, komponentti varaa muistia funktiolle AllocMemory muistinhallinta, kirjoittaa sinne dataa ja tallentaa tämän osoitteen rakenteen vastaavaan kenttään. 1C: Yritys vapauttaa tämän muistin soittamalla Vapaa muisti.
Menetelmien täydellinen kuvaus, mukaan lukien luettelo parametreista, on kuvattu yksityiskohtaisesti ITS-levyllä toimitetussa dokumentaatiossa.
Tarkastellaanpa edellä kuvattujen menetelmien toteutusta.
Komponenttikoodissa määritellään kaksi taulukkoa:
static wchar_t *g_MethodNames = (L"Ota käyttöön", L"Poista", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Ota käyttöön", L"Poista käytöstä", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
ja luettelointi:
enum Methods ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Aina viimeinen );
Niitä käytetään funktioissa GetNMethods, FindMethod Ja GetMethodName, analogisesti ominaisuuksien kuvauksen kanssa.
menetelmät Hanki NParams, GetParamDefValue, HasRetVal Työkonekytkin palauttaa vaaditun arvon hyväksytyistä parametreista ja sovelluslogiikasta riippuen. Menetelmä HasRetVal sen koodissa on luettelo vain menetelmistä, jotka voivat palauttaa tuloksen. Heille hän palaa totta. Kaikille teräsmenetelmille palautukset väärä.
menetelmät CallAsProc Ja CallAsFunc sisältävät menetelmän suoraan suoritettavan koodin.
Jos haluat lisätä menetelmän, jota voidaan kutsua vain funktiona, sinun on tehtävä seuraavat muutokset ulkoisen komponentin lähdekoodiin:
  1. Lisää menetelmän nimi taulukoihin g_MethodNames Ja g_MethodNamesRu(tiedosto AddInNative.cpp)
  2. Lisää merkityksellinen menetelmätunniste Methods-luetteloon (tiedosto AddInNative.h)
  3. Tee muutokset toimintokoodiin Hanki NParams ohjelman logiikan mukaisesti
  4. Tee tarvittaessa muutoksia menetelmäkoodiin GetParamDefValue, jos haluat käyttää menetelmäparametrien oletusarvoja.
  5. Tee muutoksia toimintoon HasRetVal
  6. Tee muutoksia funktioiden logiikkaan CallAsProc tai CallAsFunc, sijoittamalla menetelmän suoraan suoritettavan koodin sinne
Esitellään taulukot g_MethodNames Ja g_MethodNamesRu, sekä listaus menetelmät lomakkeeseen:
static wchar_t *g_MethodNames = (L"Ota käyttöön", L"Poista", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Ota käyttöön", L"Poista käytöstä", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Enum Methods ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Aina viimeinen );
Muokataan funktiota Hanki Nprops niin, että se palauttaa "Testi"-menetelmän parametrien määrän:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; oletus: return 0; ) return 0; )
Tehdään muutoksia funktioon:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) (TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case e MethStartTimer: tapaus eMethStopTimer: tapaus eMethTest : / / Parametriarvoja ei ole oletusarvoisesti: return false;
Kiitos lisätyn linjan
tapaus eMethTest:
jos yksi tai useampi argumentti puuttuu, vastaavilla parametreilla on tyhjä arvo ( VTYPE_EMPTY). Jos tarvitset parametrille oletusarvon, aseta se osiossa eMethTest toimintokytkimen lausunto CAddInNative::GetParamDefValue.
Koska testimenetelmä voi palauttaa arvon, sinun on tehtävä muutoksia funktiokoodiin HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; oletus: return false; ) return false; )
Ja lisää menetelmän suoritettava koodi funktioon CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetArray, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( case eMethLoadT case:eMethLoadT; case eMethLoadP; if (!lSizeArray || !paParams) return s1 = (paParams) -> pwstrVal ;
Käännetään komponentti ja tuodaan konfigurointikoodi lomakkeeseen:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy () Yhdistä ulkoinen komponentti ("...", "DemoVK", ulkoisen komponentin tyyppi. Alkuperäinen); DemoComp = Uusi("AddIn.DemoVK.SomeName"); kaista = DemoComp.Test("Hei", "Maailma!"); Raportti(per); Menettelyn loppu
Konfiguroinnin käynnistämisen jälkeen saamme viestin: "Hei, maailma!", joka osoittaa, että menetelmä toimi onnistuneesti.

Ajastin

Tehtävä:
  1. Tutki ajastimen toteutusta demo-VK:ssa
  2. Muokkaa StartTimer-menetelmää lisäämällä parametreihin mahdollisuus välittää ajastimen vasteaika (millisekunteina)
  3. Varmista, että tekemäsi muutokset toimivat.

WinAPI:ssa voit käyttää sanomaa työskennelläksesi ajan kanssa WM_TIMER. Tämä viesti lähetetään ohjelmallesi aikavälillä, jonka määritit ajastimen luomisen yhteydessä.
Voit luoda ajastimen käyttämällä toimintoa Aseta ajastin:
UINT SetTimer(HWND hWnd, // ikkunakuvaus UINT nIDevent, // ajastimen tunniste (numero) UINT nElapse, // viive TIMERPROC lpTimerFunc); // osoitin toimintoon
Käyttöjärjestelmä lähettää viestin WM_TIMER ohjelmaan argumentissa määritetyllä aikavälillä nElapse(millisekunteina). Viimeisessä parametrissa voit määrittää toiminnon, joka suoritetaan aina, kun ajastin laukeaa. Tämän funktion otsikon pitäisi näyttää tältä (nimi voi olla mikä tahansa):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Tarkastellaanpa ajastimen käyttöönottoa demo-VC:ssä.
Koska harkitsemme ulkoisen komponentin kehittämistä Windows-käyttöjärjestelmäperheelle, emme harkitse ajastimen käyttöönottoa muissa käyttöjärjestelmissä. Erityisesti GNU/Linux-käyttöjärjestelmässä toteutus eroaa funktion syntaksista Aseta ajastin Ja TimerProc.
Suoritettava koodi kutsuu menetelmää Aseta ajastin, jolle funktio välitetään MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
Luodun ajastimen tunnus sijoitetaan muuttujaan m_uiTimer jotta se voidaan poistaa käytöstä myöhemmin.
Toiminto MyTimerProc seuraavasti:
VOID CALLBACK MyTimerProc(HWND hwnd, // ajastinviestien ikkunan kahva UINT uMsg, // WM_TIMER viesti UINT idEvent, // ajastimen tunniste DWORD dwTime // nykyinen järjestelmäaika) ( if (!pAsyncEvent) return; wchar_t "ComponentNative", *what = L"Ajastin"; wchar_t *wstime = uusi wchar_t; , what, wstime);
Toiminnon ydin on, että menetelmää kutsutaan Ulkoinen tapahtuma, joka lähettää viestin 1C: Enterprise -järjestelmään.
Laajentaa menetelmän toimivuutta Aloitusajastin Toimitaan seuraavasti:
Metodikoodin muuttaminen Hanki NParams joten se on menetelmää varten eMethStartTimer palautti arvon 1:
case eMethStartTimer: paluu 1;
Tässä on menetelmäkoodi CallAsProc lomakkeeseen:
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;
Nyt tarkistetaan toimivuus. Tätä varten kirjoitamme koodin määrityksen hallittavaan sovellusmoduuliin:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() Yhdistä ulkoinen komponentti("...", "DemoVK", ulkoisen komponentin tyyppi.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Menettelyn loppu
Konfiguroinnin aloittamisen jälkeen ohjelma vastaanottaa viestejä 2 sekunnin välein, mikä osoittaa, että ajastin toimii oikein.

Vuorovaikutus 1C: Enterprise -järjestelmän kanssa

Vuorovaikutukseen ulkoisen komponentin ja 1C: Enterprise -järjestelmän välillä, tiedostossa kuvatut IAddInDefBase-luokan menetelmät AddInDefBase.h. Listaamme yleisimmin käytetyt:
Virheilmoituksen luominen
virtuaalinen bool ADDIN_API AddError (allekirjoittamaton lyhyt wcode, const WCHAR_T* lähde, const WCHAR_T* descr, pitkä koodi)
wcode, scode- virhekoodit (luettelo virhekoodeista ja kuvaukset löytyvät ITS-levyltä)
lähde- virheen lähde
descr- virheen kuvaus
Viestin lähettäminen 1C: Enterprise -järjestelmään
virtuaalinen bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- viestin lähde
wszMessage- Viestin teksti
wszData- siirretyt tiedot
Viestien sieppaus suoritetaan External Event Processing -menettelyllä
Ulkoisen komponentin rekisteröinti 1C: Enterprise -järjestelmässä
virtuaalinen bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- komponentin nimi.
Nämä menetelmät riittävät täydelliseen vuorovaikutukseen VK:n ja 1C:n välillä. Jotta ulkoinen komponentti vastaanottaa tietoja 1C: Enterprise -järjestelmästä ja päinvastoin, ulkoinen komponentti lähettää erityisen viestin, jonka 1C-järjestelmä sieppaa ja tarvittaessa kutsuu ulkoisen komponentin menetelmiä tietojen lähettämiseksi takaisin .

tVariantin tietotyyppi

Kun tietoja vaihdetaan ulkoisen komponentin ja 1C: Enterprise -järjestelmän välillä, käytetään tVariant-tietotyyppiä. Se on kuvattu Types.h-tiedostossa, joka löytyy ITS-levyltä:
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 uintt.2 _t errCode: wchar_tVal; struct tmVal; __VARIANT_NAME_2/*iface*/; ) __VARIANT_NAME_1 ; mittataulukko pvarVal TYPEVAR vt);
Tyyppi tVariantti on rakenne, joka sisältää:
  • seos (liitto), joka on tarkoitettu suoraan tietojen tallentamiseen
  • tietotyypin tunniste
Yleensä työskentely tyyppisten muuttujien kanssa tVariantti tapahtuu seuraavan algoritmin mukaan:
  1. Muuttujaan tällä hetkellä tallennettujen tietojen tyypin määrittäminen
  2. Siirry vastaavaan sekoituskenttään päästäksesi suoraan tietoihin
Tyypin käyttäminen tVariantti yksinkertaistaa merkittävästi 1C: Enterprise -järjestelmän ja ulkoisten komponenttien vuorovaikutusta

Sovellus

"Esimerkit" -hakemisto sisältää esimerkkejä artikkelista
esimerkit/1 - käynnistä demokomponentti
esimerkit/2 - esittely kiinteistöluettelon laajentamisesta
esimerkit/3 - esitys menetelmäluettelon laajentamisesta
Jokainen hakemisto sisältää VS 2008 -projektin ja valmiin 1C-kokoonpanon.

Artikkelin otsikko sisältää lauseen "nukkeille". Teekannulla tarkoitin ennen kaikkea itseäni. Kaikki tietoni C++:sta pysyi 3-4 vuoden yliopiston tasolla, kun lähdin 1C:n kierolle polulle. Ja kaikki olisi hyvin, mutta äskettäin ilmaantui tehtävä, joka vaati ulkoisen komponentin kirjoittamista. Minun oli muistettava muistoni ja pyyhittävä pöly pois C++-tietoni. Osoittautuu, että kaikki ei ole niin pelottavaa. Haluan tarjota sinulle lyhyen johdannon ulkoisten komponenttien kirjoittamiseen.

Mallikomponentit ITS:ssä

ITS-levy sisältää täydellisen dokumentaation ulkoisten komponenttien mekanismista, jota täydentää esimerkkiprojekti ja malli omaa kehitystä varten. Materiaalia kutsutaan nimellä "External Component Technology". Dokumentaatio on hienoa, mutta sinun on silti ymmärrettävä se, ja aika on tuttuun tapaan lyhyt. Itse asiassa on vain muutama keskeinen seikka, joihin kannattaa kiinnittää huomiota, loput on rappeutumista ja turhamaisuutta :)

Tarvittavat materiaalit

Ulkoisen komponentin luomiseksi tarvitsemme:

  1. Materiaali "Teknologia ulkoisten komponenttien luomiseen" sijaitsee ITS:ssä
  2. Materiaalin mukana toimitettu tyhjä ulkokomponenttimalli
  3. MS Visual Studio. Express-versio on ilmainen ja enemmän kuin riittävä tarpeisiimme.
  4. Perustiedot C++-syntaksista, nimittäin:
  • Kyky erottaa muuttujan ilmoitus silmukasta tai ehdosta
  • Ymmärtäen, että merkkijonoja puhtaassa muodossaan ei ole olemassa C++:ssa, on olemassa taulukoita, joiden kanssa sinun täytyy selvästi vaivautua muistiin
  • Tietysti vaaditaan kyky toteuttaa tehtävä määritetyllä kielellä. Ainakin mahdollisuus kutsua jotain kolmannen osapuolen kirjastoa C++:sta, joka tekee kaiken itse.

Aloitetaan kaivaminen

Native API:n dokumentaatio on melko yksityiskohtainen. Yhteenvetona se sanoo seuraavaa:

  1. Ulkoisen komponentin avulla voit laajentaa sisäänrakennettua kieltä uudella objektilla (tai useilla). Nuo. luomme tietyn luokan, jonka voimme luoda "New"-operaattorilla ja kutsumme tämän objektin menetelmiä sisäänrakennetusta kielestä.
  2. Jotta esineemme toimisi, alusta "kommunikoi" sen kanssa käyttämällä tiettyä protokollaa, joka meidän on toimitettava.
  3. Itse komponenttikoodi koostuu perinteisesti kahdesta osasta: ensimmäinen on itse komponentin rekisteröinti järjestelmään, toinen on uuden luokan toiminta ja sen vuorovaikutus alustan kanssa.

Emme perehdy toteutuksen yksityiskohtiin, meillä on loppumassa määräajat, eikä meillä ole tarpeeksi osaamista. Meidän on nopeasti ymmärrettävä, mihin meidän on syötettävä rivimme, jotta komponentti toimisi. Voit tehdä tämän ottamalla komponenttimallin ITS:n kanssa ja avaamalla se Visual Studiossa. Malli sijaitsee pakkaamattoman arkiston mallikansiossa. Katsotaan mitä täällä on.

Olemme kiinnostuneita AddInNative.cpp-tiedostosta. Kaikki oivallus on siinä. Se sisältää malleja kaikille tarvittaville menetelmille, sinun on vain mukautettava niitä hieman. Kävi kuitenkin ilmi, että oli helpompaa olla käyttämättä tyhjää mallia pohjana, vaan käsitellä toimivaa esimerkkiä. Siinä on useita hyödyllisiä kelloja ja pillejä, jotka eivät sisälly tyhjään malliin. Kun ymmärrys tulee, sinun on otettava tyhjä malli ja hiottava sitä asian tiedolla. Esimerkki toimivasta komponentista sijaitsee esimerkki\NativeAPI-kansiossa ja tyhjä mallipohja mallikansiossa.

Avataan projekti esimerkkikansiosta ja siinä - tiedosto AddInNative.cpp

Aivan tiedoston alussa on vakioiden ja apufunktioiden ilmoitukset. Olemme kiinnostuneita seuraavista riveistä:

Kohteemme "oikeana" tukee sekä venäjäksi että englanniksi kirjoitettuja menetelmiä. Tätä tarkoitusta varten ominaisuuksien ja menetelmien kirjalliset nimet ilmoitetaan kahdella kielellä. Sininen runko on englantilaisille kylpyille, punainen kehys venäläisille kylpyille. Kuvassa näkyy, että esimerkki toteuttaa jo useita menetelmiä ja ominaisuuksia. Tehtävämme on poistaa ne ja lisätä omamme.

Rivi, jolla luokan nimi ilmoitetaan, on korostettu vihreällä kehyksellä. Rehellisesti sanottuna en ymmärtänyt mitä se tarkoitti. Jos muutat sen, mikään ei toimi. Koska he alun perin tekivät varauksen, että olin "nukke", voin antaa anteeksi. :)

Jos siis objektimme sisältää "RunCalculation"-menetelmän ja "Destination"-ominaisuuden, meidän on kuvattava tämä nimi g_MethodNamesRu- ja g_PropNamesRu-taulukoissa, vastaavasti.

Puhelut 1C-kieleltä

Joten objektimme sisältää yhden menetelmän ja luku-kirjoitusominaisuuden.

Otetaan seuraava käyttöskenaario:

OurObject = Uusi("AddIn. MyComponent. DataSender"); MeidänObjektimme. Kohde = "joku sähköposti@palvelin. fi";
MeidänObjektimme. RunCalculation(PaymentAmount, "Apuohjelmille");

On merkkijono-ominaisuus ja menetelmä, jossa on numeerinen ja merkkijonoparametri. Jotta tämä kaikki toimisi, 1C suorittaa suunnilleen seuraavan viestintäprotokollan komponentin kanssa:

Alusta kutsuu ennalta määritettyjä toimintoja objektillamme, ja se vastaa siihen ja suorittaa sen komentoja. Tilanne on samanlainen menetelmien kanssa, vain siellä pyydetään menetelmän numeron lisäksi parametrien lukumäärää, paluuarvon olemassaoloa ja valinnaisten parametrien läsnäoloa.

Palataan koodiimme. "Maagisten lukujen" välttämiseksi CAddInNative-luokassa ilmoitetaan kaksi luettelointia, jotka ovat vastuussa menetelmien ja ominaisuuksien lukumäärän määrittämisestä. Avataan tiedosto CAddInNative.h ja katsotaan ne heti alussa:

Tyhjä malli ei sisällä näitä luetteloita, eikä myöskään ole esimerkkiä venäjänkielisten puhelujen erottamisesta ei-venäläisistä puheluista. Tämä lähestymistapa on valinnainen. On tärkeää seurata käyttöliittymää, ja se, tuleeko siirtoja vai ei, on sinun päätettävissäsi.

Unicode-merkkijonot

Monet ihmiset luultavasti tietävät, että alusta toimii kaksitavuisilla Unicode-muodossa olevilla merkeillä. Malli ilmoittaa erityistyypin WCHAR_T tätä tarkoitusta varten. Tämä tyyppi on monialustainen kääre ja varmistaa saman merkkikoon Windowsissa ja Linuxissa. Vakio wchar_t-tyyppi voi vaihdella kooltaan eri järjestelmissä. Huomaa myös, että kaikki merkkijonoliteraalit ilmoitetaan L-kirjaimen etuliitteellä. Tämä tarkoittaa, että tällainen merkkijono on tyyppiä wchar_t.

On olemassa yksinkertainen sääntö: sisäisesti merkkijonokomponentit käsitellään muodossa wchar_t (Linuxissa voi olla 4 tavua, Windowsissa - 2), mutta heti kun siirrämme merkkijonon 1C: hen tai vastaanotamme sen sieltä, tarvitsemme WCHAR_T (tiukasti 2 tavua kaikissa järjestelmissä).

Jos haluat muuntaa yhden tyyppisen merkkijonon toiseksi, malli tarjoaa aputoimintoja:

Ensimmäinen muodostaa WCHAR_T standardista wchar_t:

uint32_t convToShortWchar(WCHAR_T** Kohde, const wchar_t* Lähde, uint32_t len ​​= 0);

Toinen on päinvastoin. Lomakkeet wchar_t kohteesta WCHAR_T.

uint32_t convFromShortWchar(wchar_t** Kohde, const WCHAR_T* Lähde, uint32_t len ​​​​= 0);

Vuorovaikutuksessa alustan kanssa käytetään aina vain WCHAR_T:tä.

Varianttityyppi

Toinen mielenkiintoinen asia on yleinen Variant-tietotyyppi. Sen avulla voimme olla vuorovaikutuksessa 1C-kielen kanssa, jota, kuten tiedät, ei kirjoiteta ja jokainen muuttuja voi sisältää mitä tahansa. Tätä tyyppiä käytetään arvoja vaihdettaessa. Välitämme RunCalculation-menetelmään kaksi parametria - numeron ja merkkijonon. Komponentti saa kaksi Variant-arvoa. Meidän vastuullamme on tarkistaa niiden todellinen tyyppi. Kukaan ei estä sinua välittämästä komponentille numeroa, vaan esimerkiksi arvotaulukkoa.

Vaikka näyttää siltä, ​​että olen väärässä. Minusta näyttää siltä, ​​​​että arvotaulukon siirtäminen NativeAPI:hen ei vieläkään ole mahdollista, koska se ei ole sallittujen tyyppien luettelossa, mutta voit silti antaa päivämäärän merkkijonon sijaan. Tämä ei myöskään ole hyvä. Meidän on tarkistettava muuttujan todellinen tyyppi, joka tuli 1C:stä.

Variant-tyyppi on yksinkertainen. Tämä on rakenne, jonka ominaisuudet ovat erityyppisiä arvoja. On ominaisuuksia, kuten DATE, wchar_t, int ja muita. Variantin pääosa on "vt"-ominaisuus, joka tallentaa muuttujan todellisen tyypin ja josta voit ymmärtää tarkalleen kuinka tämä Variantti tulkitaan. Lisäksi useita apumakroja on ilmoitettu yksinkertaistamaan Variant-tyypin kanssa työskentelyä.

Mennä asiaan

Näyttää siltä, ​​että tämä kaikki on johdannossa. Ehdotan, että harkitaan esimerkkiä ulkoisen komponentin toteuttamisesta. TK on esimerkki komponentista ITS-levyltä. Tämä esimerkki kuvaa seuraavat ominaisuudet:

  • Tekstin näyttäminen pääikkunan tilapalkissa;
  • Ulkoisen ajastintapahtuman lähettäminen;
  • Binääritietojen siirto 1C:Enterprise-palveluun;
  • Kiinteistöjen toteutus;
  • Menettelyjen täytäntöönpano;
  • Toimintojen toteuttaminen;

Komponentilla on seuraava API:

  • Ominaisuudet:
    • Käytössä/On Enabled;
    • IsTimer/IsTimerPresent;
    • Menetelmät:
      • Ota käyttöön;
      • Poista käytöstä / Poista käytöstä;
      • ShowInStatusLine;
      • EnableTimer/StartTimer;
      • Sammuta ajastin/pysäytysajastin;
      • LoadPicture/LoadPicture;

Ulkoinen tapahtuma tapahtuu ajastimella, joka voidaan tilata 1C-koodista.

Tarkastellaanpa komponenttia alusta alkaen olemassa olevan tiedon ohjaamana.

Rekisteröinnin komponentit

Oliomme on toteutettu erillisenä C++-luokana, tässä tapauksessa CAddInNativena. Jotta 1C näkee luokkamme, dll-kirjaston on vietävä 3 toimintoa:

  • GetClassObject
  • DestroyObject
  • Hanki ClassNames

Nämä viennit näkyvät AddInNative.def-tiedostossa VisualStudio-projektipuussa. Katsotaanpa näiden funktioiden koodia:

Yksinkertaisin - GetClassNames-funktio - kertoo 1C-alustalle, mitkä luokat ovat komponentissamme. Oikaiskoon C++-gurut, minusta tuntuu, että tässä alustan on vastattava C++-luokkien nimiin, jotta se voi tuoda ne. Juuri tähän käytetään g_kClassNames-taulukkoa, jossa on vihreä "kehys". En tarkistanut sitä erikseen, mutta jos haluat vain saada komponentin toimimaan, jätä kaikki niin kuin se on esimerkissä. Se toimii jo, ei sen kanssa tarvitse toistaiseksi puuhata.

Joten GetClassNames palauttaa alustalle joukon luokkanimiä, jotka toteuttavat ulkoisen komponentin hyödyllisiä objekteja. Esimerkissämme komponentti palauttaa alustalle yhden elementin joukon, jonka luokka on CAddInNative.

Huomaa, että alusta saa arvon, jonka tyyppi on WCHAR_T, ja luokan nimi g_kClassNames-taulukossa on tyyppiä wchar_t. Siksi heitto suoritetaan käyttämällä yllä käsiteltyä aputoimintoa.

Seuraava funktio on GetClassObject. Kutsutaan, kun olemme kirjoittaneet yrityskoodiin "Uusi". Alusta edellyttää, että luomme luokasta uuden ilmentymän ja palautamme osoittimen uuteen objektiin.

Huomaa jälleen, että ensimmäinen parametri, jonka alusta kertoo meille, on mikä luokka luodaan (GetClassNames-menetelmällä sille annetuista). Koska meillä on vain yksi luokka, tätä nimeä ei tarkasteta täällä ollenkaan, objekti luodaan yksinkertaisesti uuden kautta ja palautetaan tulosparametrin pInterface kautta.

Ja viimeinen vaadittu vientitoiminto on DestroyObject. Nimi puhuu puolestaan. Kun alusta ei enää tarvitse objektia, se on poistettava. Saamme osoittimen aiemmin luotuun objektiin. Vapautamme sen poistamalla ja nollaamalla tarpeettomat osoittimet.

Kuvatut toteutukset ovat melko yleisiä. Jos komponenttimme toteuttaa vain yhden luokan (kuten esimerkissä), nämä funktiot on yksinkertaisesti kopioitava itselleen. Ainoa ehto on luoda oikea luokka GetClassObject-funktiossa, jos nimesi ei ole CAddInObject, vaan jokin muu.

Komponentin alustus/lopetus

Kun komponenttia toteuttava luokka on luotu, alusta kutsuu tämän luokan menetelmiä. Ennen työn aloittamista alusta kertoo meille "itsensä" -objektin, jolla voimme kutsua tiettyjä itse alustan menetelmiä. Tämä tapahtuu Init-menetelmässä. Esimerkissä alustaobjekti on tallennettu m_iConnect-muuttujaan.

Toinen tärkeä menetelmä on setMemManager. Voit varata muistilohkoja, jotka alusta itse vapauttaa. Se toteutetaan seuraavasti:

Tallennamme yksinkertaisesti osoittimen muistinhallintaan, jonka alusta välittää meille. Sitten tämän hallinnan avulla varaamme itse alustan vapauttaman muistin.

Ja jälleen, kuten vientitoimintojen tapauksessa, alustusmenetelmät ovat melko yleisiä, voit yksinkertaisesti kopioida ne itsellesi ja olla huolehtimatta niiden "viimeistelystä" ennen kuin se on todella välttämätöntä.

Hyötykuorma. Komponenttiobjektin menetelmät ja ominaisuudet

Rekisteröinti

No, tietenkään emme luoneet komponenttia sen alustuksen vuoksi, vaan hyödyllisten toimintojen vuoksi. On aika katsoa, ​​miten se toteutetaan.

Ensin meidän on rekisteröitävä objekti, joka voidaan luoda ja kutsua 1C-kielellä. Tämä objekti on rekisteröity RegisterExtensionAs-metodissa.

Tässä menetelmässä ilmoitamme alustalle luokkamme nimen, koska se näkyy 1C-kielellä. Tällä nimellä luomme sen "Uuden" kautta. Tässä tapauksessa objektin luonti suoritetaan seuraavalla koodilla:

ConnectExternalComponent(Tiedosto, "Oma komponentti", Ulkoinen komponenttityyppi. Alkuperäinen);
ObjectComponents = New( "AddIn.MyComponent.AddInNativeExtension");

Dokumentaation mukaan muistinhallinta varaa muistin merkkijonolle luokan nimellä, ja nimi kirjoitetaan tähän osoitteeseen - "AddInNativeExtension". Täällä voit kirjoittaa nimesi kivuttomasti. Huomaa, että wchar_t on jälleen muunnettu alustaksi WCHAR_T.

Käyttö

Kuten edellä kirjoitin, alusta kysyy komponentilta eri kieliominaisuuksia. Onko määritetty ominaisuus olemassa, onko se kirjoitettava, onko funktioparametrilla oletusarvoa, onko sillä palautusarvoa jne. Jos otamme aiemmin annetun koodiesimerkin:

OurObject = Uusi( "AddIn.MyComponent.DataSender"); // DataSender on nimi RegisterExtensionAs-funktiosta (käsitellään alla).
MeidänObjektimme. Osoite = " [sähköposti suojattu]" ;
MeidänObjektimme. Suorita laskelma (maksusumma, "Yhteispalveluille");

sitten suoritetaan seuraava kysely:

  1. Onko olemassa kohde-omaisuutta?
  2. Tukeeko se tallennusta?
  3. Onko olemassa menetelmää nimeltä RunCalculation?
  4. Kuinka monta parametria siinä on?
  5. Onko sillä palautusarvoa
  6. Mitkä ovat valinnaisten parametrien oletusasetukset (jos sellaisia ​​on)

Hyödyllisintä tässä on katsoa esimerkkiä ja tarkistaa dokumentaatio. Kaikkien näiden tutkimusten toteuttaminen on melko yksinkertaista. Kokonainen eläintarha menetelmiä vastaa vuorovaikutuksesta. En käy kaikkea läpi, ne ovat melko hyvin dokumentoituja, ja lisäksi ne on helppo toteuttaa. Vain merkittävimmät hetket huomioidaan, joihin meidän nukkeina on saatava käsiimme :). Peruslähestymistapa on seuraava: kun ominaisuus tai menetelmä mainitaan ensimmäisen kerran, alusta pyytää meitä etsimään sitä nimellä. Meidän on vastattava tämän ominaisuuden yksilöivällä numerolla (menetelmä). Kaikki jatkoviestintä tapahtuu vain numeroiden avulla. Tässä auttavat mainitut luettelot, jotka tallentavat nämä numerot.

Ominaisuudet

Ensimmäinen asia, joka on otettava huomioon, on kiinteistön infrastruktuuri. Alusta pyytää ominaisuuden olemassaoloa FindProp-menetelmällä

Alusta välittää meille etsimämme kiinteistön nimen muodossa WCHAR_T. Se muunnetaan wchar_t-muotoon apumenetelmällä ja tätä tekstiä haetaan ensin englanninkielisillä termeillä ja sitten venäjänkielisillä termeillä. Meidän on palautettava kiinteistön numero. Huomaa, että findName-aputoiminto on mukana tässä. Sen toteutus on esimerkissä, mutta komponentti ei ole tyhjässä mallissa. Vaikuttaa sopivalta vetää se itseäsi kohti, jos aiot sisältää kaksikielisiä termejä komponentissasi.

Seuraavaksi GetPropName-menetelmä suorittaa käänteisen tehtävän ja saa ominaisuuden nimen numeron mukaan. Nimimerkkijono varataan myös yrityksen muistinhallinnan kautta. Epäilen, että GetPropName-menetelmää käytetään yhdessä GetNpropsin kanssa, kun laajennamme kohteen ominaisuuksia plusmerkillä debuggerissa. Sitten alusta vastaanottaa kiinteistöjen kokonaismäärän ja pyytää nimeä jokaiselle.

Seuraava menetelmäpari on IsPropReadable/IsPropWritable. Kaikki on täällä yksinkertaista, määritetylle omaisuusnumerolle on sanottava, voidaanko se lukea/kirjoittaa.

Arvojen vastaanotto ja kirjoittaminen suoritetaan GetPropVal/SetPropVal-menetelmillä. Täällä kannattaa perehtyä tarkemmin. Aloitamme työskentelyn 1C:Enterprise-tyyppien kanssa, mikä tarkoittaa, että Variant on tulossa näyttämölle.

Komponenttimalli määrittää joukon apumakroja Variantin kanssa työskentelyn yksinkertaistamiseksi. Ensimmäinen on arvotyypin tarkistus. Esimerkiksi makron TV_VT avulla voit tarkistaa/asettaa arvon tyypin. Jokaiselle tuetulle tyypille määritetään myös nimetyt vakiot. Nämä vakiot ja niiden vastaavuus 1C:Enterprise-tyypeille on lueteltu dokumentaatiossa.

TV_BOOL-makro saa Boolen arvon variantista, jota voit käyttää. Analogisesti saadaan kokonaislukuarvot (TV_INT), merkkijonot (TV_WSTR) ja muut. Tarkat arvot ovat koodissa, voit aina nähdä ne.

Tärkeä seikka on, että arvon määrittäminen variantille ei riitä, sinun on määritettävä myös todellinen tyyppi. Kiinnitä huomiota GetPropValiin. TV_BOOL = true -määrityksen lisäksi on tyyppimääritys: TV_VT = VTYPE_BOOL. Jos tyyppiä ei ole määritetty, alusta ei tiedä, minkä tyyppinen arvo sille palautettiin. Tietysti voit sotkea ja asettaa väärän tyypin. Tähän liittyy usein alustan putoaminen.

Tehdään yhteenveto yllä olevasta:

Saamme arvon vaihtoehdosta:

bool someVariable = TV_BOOL(pVariant);

Kirjoita arvo vaihtoehdolle:

TV_VT(pVariant) = VTYPE_BOOL; // kelvollinen tietotyyppi

TV_BOOL(pVariant) = jokin Boolen muuttuja; // aseta itse arvo

Ja nyt - kyttyräselkämenetelmät!

Menetelmät ovat hieman monimutkaisempia, mutta yleensä ne ovat samanlaisia ​​kuin ominaisuudet. Ensinnäkin on täsmälleen sama toiminto: menetelmän etsiminen nimellä, menetelmien kokonaismäärä, nimi numerolla. Yllä olevien lisäksi on kuitenkin lisätty seuraavat ominaisuudet:

  • Jos menetelmä voi palauttaa arvon, sitä voidaan käyttää "Laske" -kohdassa ja kirjoittaa määritystoiminnon oikealle puolelle 1C-kielellä. Jos ei, se on menettely, ja sellaiset asiat aiheuttavat "Proseduurin käyttäminen funktiona" -poikkeuksen
  • Menetelmällä on parametrit. Alustan on tiedettävä heidän numeronsa. Jos kutsu määrittää enemmän argumentteja kuin menetelmän allekirjoituksessa on määritetty, ilmenee "Liian monta parametria" -virhe.
  • Jos menetelmälle ei välitetä tarpeeksi argumentteja, osa niistä voi olla valinnaisia, ja jos valinnaisia ​​parametreja ei ole, tapahtuu "Insufficient parameters" -virhe.
  • Kutsuttaessa, jos se on proseduuri, paluuarvoa ei voi olla. Jos se on funktio, sillä on palautusarvo. Se on myös käsiteltävä.

On olemassa useita yksinkertaisia ​​menetelmiä, joiden tarkoitus on selvä niiden nimistä ja dokumentaatiosta. Näitä ovat HasRetVal, GetNParams, GetParamDefValue. Ehdotan, että niitä ei oteta huomioon. Kiinnostuksemme kohdistuu hyötykuorman suoraan toteuttamiseen. Se on toteutettu CallAsProc- ja CallAsFunc-menetelmillä. Ensimmäinen vastaa kutsumenettelyistä, toinen vastaa kutsutoiminnoista. Ne eroavat toisistaan ​​siinä, että CallAsFuncilla on lisälähtöparametri, jossa välitämme funktion palautusarvon alustalle.

Kutsu suoritetaan seuraavasti: alusta välittää meille kutsutun menetelmän numeron, joukon todellisia parametreja ja niiden numeron. Meidän on jäsennettävä menetelmän numero ja syötettävä sille hyväksytyt parametrit. Kun kyseessä on funktio, meidän on myös kirjoitettava jotain palautusarvoon.

Esimerkissä menetelmän numero analysoidaan kytkimessä/tapauksessa ja numerosta riippuen suoritetaan menetelmälogiikka. Valitse Ota käyttöön/Poista menetelmät -kohdassa valintaruutu. ShowInStatusLine-menetelmä on mielenkiintoinen. Se näyttää, mitä sille välitettiin 1C:Enterprise-ikkunan tilapalkissa. Tätä varten käytämme m_iConnect-alustan yhteysobjektia, joka "myönnettiin" meille komponenttia rekisteröitäessä. Täydellinen luettelo sen ominaisuuksista on kuvattu dokumentaatiossa.

Mielenkiintoinen pointti. Tässä esimerkissä 1C:stä tulevan arvon tyyppiä ei tarkisteta, vaan SetStatusLine kutsutaan yksinkertaisesti merkkijonoosalla Variant. Epäilen, että jos kutsut komponenttimenetelmää 1C-kielestä ja välität sinne numeron tai päivämäärän (merkkijonon sijaan), niin mikään ei toimi... Jälleen, anna gurujen korjata, mutta näyttää siltä, ​​​​että pwstrVal-osoitin osoittaa Jumala tietää mistä, jos se tulee yrityksestä, sanotaanko numero, ei rehellinen merkkijono. SetStatusLinea soitettaessa alusta yrittää lukea riviä tuntemattomasta osoitteesta ja todennäköisesti kaatuu. On parempi aina tarkistaa odotettu tyyppi. Ei sitä koskaan tiedä.

Esimerkin LoadImage-funktio on toteutettu mielenkiintoisemmalla tavalla, se ottaa huomioon merkkijonojen ja binääritietojen vaihdon alustan kanssa.

Ensin tässä tarkistetaan hyväksyttyjen parametrien määrä. Jos he eivät ole paikalla, puhelu katsotaan epäonnistuneeksi. Palauttaa false, jonka alusta tulkitsee puheluvirheeksi.

Seuraavaksi tässä tarkistetaan hyväksytyn parametrin tyyppi. Jos tämä on kapea merkkijono (VTYPE_PSTR), käytetään muunnelman char-osaa. Esimerkissä lukee paParam->pstrVal, mutta voit käyttää TV_STR-makroa, se on sama, mutta myös valinnan kanssa työskentelyn yhtenäisyys säilyy.

Jos se on leveä merkkijono (VTYPE_PWSTR), muunnos tehdään ensin muotoon wchar_t ja sitten char. Tosiasia on, että tiedoston polku välitetään 1C-kielestä tähän menetelmään, jota käytetään sitten fopen(char*)-funktiossa. Tämä toiminto vaatii syötteenä char*-tyypin, ja WCHAR_T lähetetään meille alustalta. Oikean toiminnan varmistamiseksi merkkijonomuunnokset suoritetaan.

Ja lopuksi, jos tämä ei ole merkkijono ollenkaan, puhelu katsotaan epäonnistuneeksi ja palautetaan false.

Varaamme muistia binääritiedoille käyttämällä muistinhallintaohjelmaa. Tämä on loogista; binääritiedoista tulee täysimittainen objekti alustassa, ja sen on hallittava sitä. Muistia on varattu pvarRetValue-variantille, joka on ulkoisen komponentin funktion palautusarvo.

Lisäksi koko tiedosto luetaan varattuun puskuriin; Välttämättä tavukoko määritetään strLen-option ominaisuudessa ja VTYPE_BLOB-asetuksen tietotyyppi. Jos muistin varaus on onnistunut, palautetaan true merkkinä onnistuneesta kutsusta koko funktiolle.

Joten kun 1C-kielellä kirjoitetaan:

BinaryData = Komponentti. Lataa kuva("C:\pic.jpg");

Kutsutaan komponenttiobjektin CallAsFunc-metodia, joka kulkee polun ja palauttaa binääridatan edellä kuvatulla tavalla.

Jos onnistuu, BinaryData-muuttuja sisältää täysimittaisen 1C-kieliobjektin. Kun se menee soveltamisalan ulkopuolelle, alusta vapauttaa kaiken sen käyttämän muistin. Siksi se jaettiin muistinhallinnan kautta.

Johtopäätös

Tarina on kirjoittanut teekannu nukkeille, joten se on todennäköisesti täynnä terminologisia epätarkkuuksia. Tämän artikkelin tarkoituksena on kuitenkin tarjota nopea johdatus ulkoisiin komponentteihin. Jos sinun on valmistettava komponentti nopeasti lyhyessä ajassa, ilman turhaa vaivaa, ilman pitkiä keskusteluja, toivon, että tämä artikkeli auttaa sinua. Jos jokin virheistäni saa sinut tuntemaan olosi huonoksi, C++-guruna, kerro siitä minulle kommenteissa, niin korjaamme ne.

Kiitos huomiostasi.

  • Opetusohjelma

Johdanto

Tämä artikkeli antaa käsityksen siitä, kuinka ulkoiset komponentit toimivat 1C: Enterprise -järjestelmässä.
Näytetään ulkoisen komponentin kehitysprosessi 1C: Enterprise -järjestelmän versiolle 8.2, joka toimii Windows-käyttöjärjestelmässä tiedostotoiminnolla. Tätä vaihtoehtoa käytetään useimmissa pienille yrityksille suunnitelluissa ratkaisuissa. VK toteutetaan C++-ohjelmointikielellä.

Ulkoiset komponentit "1C: Enterprise"

"1C: Enterprise" on laajennettava järjestelmä. Järjestelmän toiminnallisuuden laajentamiseksi käytetään ulkoisia komponentteja (EC). Kehittäjän näkökulmasta VC on ulkoinen objekti, jolla on ominaisuuksia ja menetelmiä ja joka voi myös luoda tapahtumia 1C: Enterprise -järjestelmän käsittelyä varten.
Ulkoisia komponentteja voidaan käyttää ratkaisemaan ongelmia, joita on vaikea tai jopa mahdoton toteuttaa 1C: Enterprisen sisäänrakennetulla ohjelmointikielellä. Erityisesti tämä luokka sisältää tehtäviä, jotka vaativat matalan tason vuorovaikutusta käyttöjärjestelmän kanssa, esimerkiksi tiettyjen laitteiden kanssa työskentelyyn.
1C: Enterprise -järjestelmä käyttää kahta tekniikkaa ulkoisten komponenttien luomiseen:
  • käyttämällä alkuperäistä APIa
  • käyttämällä COM-tekniikkaa
Annetut rajoitukset huomioiden ero kahden edellä mainitun teknologian välillä on merkityksetön, joten harkitsemme videopelien kehittämistä Native API:lla. Toteutettuja kehityssuuntia voidaan tarvittaessa soveltaa COM-teknologiaa käyttävien tietokoneohjelmistojen kehittämiseen, ja myös pienin muutoksin soveltaa 1C: Enterprise -järjestelmään myös muilla toimintavaihtoehdoilla kuin tiedoston käyttötilalla.
VK rakenne
1C: Enterprise -järjestelmän ulkoinen komponentti esitetään DLL-kirjaston muodossa. Kirjastokoodi kuvaa jälkeläisluokkaa IComponentBase. Luodun luokan tulee määrittää menetelmät, jotka vastaavat ulkoisen komponentin toimintojen toteuttamisesta. Ohitettavia menetelmiä kuvataan tarkemmin alla materiaalia esitettäessä.

Demo-VK:n käynnistäminen

Tehtävä:
  1. Kokoa ulkoinen komponentti, joka toimitetaan ITS-tilauksen mukana ja jonka tarkoituksena on osoittaa ulkoisen komponenttimekanismin pääominaisuudet 1C:ssä
  2. Liitä demokomponentti 1C-kokoonpanoon
  3. Varmista, että ilmoitetut funktiot toimivat oikein
Kokoelma
Demo-VK sijaitsee ITS-tilauslevyllä "/VNCOMP82/example/NativeAPI"-hakemistossa.
Demo-VC:n rakentamiseen käytämme Microsoft Visual Studio 2008:aa. Muut tämän tuotteen versiot eivät tue käytettyä Visual Studio -projektimuotoa.


Avaa AddInNative-projekti. Sisällytämme projektiasetuksiin hakemiston, jossa on projektin rakentamiseen tarvittavat otsikkotiedostot. Oletusarvoisesti ne sijaitsevat ITS-levyllä hakemistossa /VNCOMP82/sisältää.
Rakennuksen tulos on tiedosto /bind/AddInNative.dll. Tämä on käännetty kirjasto 1C-kokoonpanoon yhdistämistä varten.
VK:n yhdistäminen 1C-kokoonpanoon
Luodaan tyhjä 1C-kokoonpano.
Alla on hallitun sovellusmoduulin koodi.
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() Yhdistä ulkoinen komponentti("...\bind\AddInNative.dll", "DemoVK", ulkoisen komponentin tyyppi.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); Menettelyn loppu
Jos virhettä ei raportoitu 1C-kokoonpanon käynnistämisen yhteydessä, VK yhdistettiin onnistuneesti.
Yllä olevan koodin suorittamisen seurauksena objekti ilmestyy konfiguraation globaaliin näkyvyyteen DemoComp, jolla on ominaisuuksia ja menetelmiä, jotka on määritelty ulkoisen komponentin koodissa.
Sisäänrakennetun toiminnallisuuden esittely
Tarkastellaan demo-VK:n toimivuutta. Tätä varten yritetään asettaa ja lukea joitain ominaisuuksia, kutsua joitain VK-menetelmiä ja myös vastaanottaa ja käsitellä VK-viesti.
ITS-levyllä toimitetussa dokumentaatiossa mainitaan seuraavat demo-VC:n toiminnot:
  1. Hallinnoi komponenttiobjektin tilaa
    Menetelmät: Kiihottua, Kytke pois päältä
    Ominaisuudet: Mukana
  2. Ajastimen hallinta
    Joka sekunti komponentti lähettää parametreilla viestin 1C: Enterprise -järjestelmään Komponentti, Ajastin ja järjestelmän kellon laskurilinja.
    Menetelmät: Aloitusajastin, StopTimer
    Ominaisuudet: On ajastin
  3. Menetelmä ShowInStatusLine, joka näyttää tilarivillä menetelmälle parametreina välitetyn tekstin
  4. Menetelmä Lataa kuva. Lataa kuvan määritetystä tiedostosta ja siirtää sen 1C: Enterprise -järjestelmään binääritietojen muodossa.
Varmistetaan, että nämä toiminnot toimivat. Voit tehdä tämän suorittamalla seuraavan koodin:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Raportti(DemoComp.Enabled); DemoComp.Enable(); Raportti(DemoComp.Enabled); DemoComp.StartTimer(); Toimenpiteen lopetusmenettely Ulkoisen tapahtuman käsittelyn (lähde, tapahtuma, tiedot) raportti (lähde + " " + Tapahtuma + " " + tiedot); Menettelyn loppu
Konfiguroinnin tulos näkyy kuvassa


Viestit-paneeli näyttää menetelmäkutsujen tulokset DemoComp.Disable() Ja Demo.Comp.Enable(). Saman paneelin seuraavat rivit sisältävät VK:lta saatujen viestien käsittelytulokset - Lähde, Tapahtuma Ja Data vastaavasti.

Mukautettu ulkoisen komponentin nimi

Tehtävä: Muuta ulkoisen komponentin nimi mielivaltaiseksi.
Edellisessä osiossa käytettiin tunnistetta AddInNativeExtension, jonka merkitystä ei selitetty. Tässä tapauksessa AddInNativeExtension- tämä on laajennuksen nimi.
VK-koodi määrittelee menetelmän RegisterExtensionAs, palauttaa nimen 1C: Enterprise -järjestelmään, mikä on tarpeen VK:n myöhempää rekisteröintiä varten järjestelmään. On suositeltavaa määrittää tunniste, joka jossain määrin paljastaa ulkoisen komponentin olemuksen.
Tässä on menetelmän täydellinen koodi RegisterExtensionAs jonka laajennuksen nimi on muutettu:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* kohde = 0; if (m-m_Alloc_iMemory ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) return false;
Annetussa esimerkissä VK-nimi muutetaan muotoon SomeName. Sitten kun yhdistät VK:n, sinun on määritettävä uusi nimi:
DemoComp = Uusi("AddIn.DemoVK.SomeName");

VK-ominaisuuksien luettelon laajentaminen

Tehtävä:
  1. Tutki VK-ominaisuuksien toteutusta
  2. Lisää merkkijonotyyppinen luku/kirjoitusominaisuus
  3. Lisää luku/kirjoitusmerkkijonoominaisuus, joka tallentaa viimeisen ominaisuusjoukon tietotyypin. Ominaisuuden arvoa määritettäessä ei tehdä mitään

Luotavan komponentin ominaisuuksien määrittämiseksi kehittäjän on otettava käyttöön seuraavat menetelmät AddInNative.cpp-kirjastokoodissa:
Hanki Nprops
Palauttaa tämän laajennuksen ominaisuuksien lukumäärän, 0, jos ominaisuuksia ei ole
FindProp
Palauttaa sen ominaisuuden sarjanumeron, jonka nimi on välitetty parametreissa
Hanki PropName
Palauttaa ominaisuuden nimen sen sarjanumeron ja hyväksytyn kielitunnisteen perusteella
GetPropVal
Palauttaa ominaisuuden arvon määritetyllä järjestysnumerolla
SetPropVal
Asettaa ominaisuuden arvon määritetyllä järjestysnumerolla
IsPropReadable
Palauttaa ominaisuuden luettavuuslipun määritetyllä järjestysnumerolla
IsPropWritable
Palauttaa ominaisuuden kirjoitettavuuslipun määritetyllä järjestysnumerolla


Tarkastellaanpa yllä olevien luokkamenetelmien toteutusta CAddInNative.
Demo-VC:ssä määritellään 2 ominaisuutta: Mukana Ja On ajastin (On kytketty Ja IsTimerPresent).
Kirjastokoodin globaalissa laajuudessa määritellään kaksi taulukkoa:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Käytössä", L"Ajastin on olemassa");
joka tallentaa venäjän ja englannin kiinteistöjen nimet. Otsikkotiedostossa AddInNative.h luettelo on määritelty:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Aina viimeinen );
ePropIsEnabled Ja ePropIsTimerPresent, joiden arvot ovat 0 ja 1, käytetään korvaamaan kiinteistöjen sarjanumerot merkityksellisillä tunnisteilla. ePropLastia, jonka arvo on 2, käytetään ominaisuuksien lukumäärän saamiseksi (GetNprops-menetelmällä). Näitä nimiä käytetään vain komponenttikoodissa, eivätkä ne ole saatavilla ulkopuolelta.
FindProp- ja GetPropName-menetelmät suorittavat taulukkohakuja g_PropNames Ja g_PropNamesRu.
Kenttien arvojen tallentamiseksi kirjastomoduuliin CAddInNative-luokassa on ominaisuuksia, jotka tallentavat komponentin ominaisuuksien arvon. menetelmät GetPropVal Ja SetPropVal palauttaa ja asettaa näiden ominaisuuksien arvot vastaavasti.
menetelmät IsPropReadable Ja IsPropWritable ja palata totta tai väärä, riippuen kiinteistön hyväksytystä järjestysnumerosta sovelluslogiikan mukaisesti.
Jotta voit lisätä mukautetun ominaisuuden, sinun on:

  1. Lisää taulukoihin lisättävän ominaisuuden nimi g_PropNames Ja g_PropNamesRu(tiedosto AddInNative.cpp)
  2. Listata Rekvisiitta(tiedosto AddInNative.h) ennen ePropLast lisää nimi, joka yksilöi lisättävän ominaisuuden
  3. Järjestä muisti ominaisuusarvojen tallentamista varten (luo moduulikomponenttikentät, jotka tallentavat vastaavat arvot)
  4. Tee muutoksia menetelmiin GetPropVal Ja SetPropVal olla vuorovaikutuksessa edellisessä vaiheessa varatun muistin kanssa
  5. Tee muutoksia menetelmiin sovelluslogiikan mukaisesti IsPropReadable Ja IsPropWritable
Kohdat 1, 2, 5 eivät kaipaa selitystä. Yksityiskohtaiset tiedot näiden vaiheiden toteuttamisesta löytyvät tutkimalla artikkelin liitettä.
Annetaan testiominaisuuksille nimet Testata Ja Tyyppitarkistus vastaavasti. Sitten vaiheen 1 tuloksena meillä on:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Käytössä", L"Ajastin on", L"Testi", L"Tyyppitarkistus");
Siirtää Rekvisiitta näyttää tältä:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Aina viimeinen );
Yksinkertaistaaksemme koodia merkittävästi, käytämme STL C++:aa. Erityisesti kielten kanssa työskentelyyn WCHAR, yhdistetään kirjasto wstring.
Tallentaaksesi menetelmän arvon Testata, määrittelemme luokassa CAddInNative yksityisellä alalla:
merkkijono testi1;
Merkkijonoparametrien siirtämiseen 1C: Enterprisen ja ulkoisten komponenttien välillä käytetään 1C: Enterprise -muistinhallintaa. Katsotaanpa tarkemmin hänen töitään. Toimintoja käytetään muistin varaamiseen ja vapauttamiseen AllocMemory Ja Vapaa muisti, määritelty tiedostossa ImemoryManager.h. Jos on tarpeen välittää merkkijonoparametri 1C: Enterprise -järjestelmään, ulkoisen komponentin on varattava sille muistia kutsumalla funktiota AllocMemory. Sen prototyyppi näyttää tältä:
virtuaalinen bool ADDIN_API AllocMemory (void** pMemory, allekirjoittamaton pitkä ulCountByte) = 0;
Missä pMuisti- sen osoittimen osoite, johon varatun muistialueen osoite sijoitetaan,
ulCountByte- varatun muistialueen koko.
Esimerkki muistin varaamisesta merkkijonolle:
WCHAR_T *t1 = NULL, *testi = L"TESTI_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, testi1, iActualSize);
Merkkijonotietotyyppien kanssa työskentelyn helpottamiseksi kuvaamme toiminnon wstring_to_p. Se vastaanottaa parametrina wstring-merkkijonon. Toiminnon tuloksena on täytetty rakenne tVariantti. Toimintokoodi:
bool CAddInNative::wstring_to_p(std::wstring str, tVariant* val) ( merkki* t1; TV_VT(arvo) = VTYPE_PWSTR; m_iMemory->AllocMemory((void**)&t1, (str.length()+1) * sizeof(WCHAR_T)); memcpy(t1, str.c_str(), (str.length()+1) * koko(WCHAR_T) val -> pstrVal = t1; palauta tosi)
Sitten vastaava tapaus osa menetelmän kytkinlauseesta GetPropVal tulee muodossa:
tapaus ePropTest1: wstring_to_p(test1, pvarPropVal); tauko;
Menetelmä SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) return false; testi1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); tauko;
Toteuttaaksemme toisen ominaisuuden määrittelemme luokkakentän CaddInNative
uint8_t last_type;
johon tallennamme viimeksi siirretyn arvon tyypin. Voit tehdä tämän lisäämällä komennon CaddInNative::SetPropVal-metodiin:
viimeinen_tyyppi = TV_VT(varPropVal);
Nyt kun pyydämme lukemaan toisen ominaisuuden arvon, palautamme arvon viimeinen_tyyppi, mitä määrätty tehtävä edellyttää.
Tarkastellaan tehtyjen muutosten toimivuutta.
Tätä varten esittelemme 1C-kokoonpanon ulkoasun seuraavasti:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy () Yhdistä ulkoinen komponentti ("...", "DemoVK", ulkoisen komponentin tyyppi. Alkuperäinen); DemoComp = Uusi("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Raportti(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Raportti(String(DemoComp.Test)); DemoComp.Test = "Petya"; Raportti(String(DemoComp.Test)); Raportti(String(DemoComp.TypeCheck)); Menettelyn loppu
Käynnistyksen seurauksena saamme viestisarjan:
3
Vasja
Peter
22

Toinen ja kolmas viesti ovat tulosta edellisessä vaiheessa asetettujen ominaisuuksien lukemisesta. Ensimmäinen ja toinen viesti sisältävät viimeisen ominaisuusjoukon tyyppikoodin. 3 vastaa kokonaislukuarvoa, 22 merkkijonoarvoa. Tyyppien ja niiden koodien vastaavuus selvitetään tiedostosta tyypit.h, joka sijaitsee ITS-levyllä.

Menetelmien luettelon laajentaminen

Tehtävä:
  1. Laajenna ulkoisen komponentin toimintoja seuraavilla toiminnoilla:
  2. Tutki tapoja toteuttaa ulkoisia komponenttimenetelmiä
  3. Lisää funktiomenetelmä Toiminto1, joka ottaa kaksi merkkijonoa ("Parametri1" ja "Parametri2") parametrina. Tuloksena on merkkijono, kuten: "Tarkistaa. Parametri1, Parametri2"
  4. Varmista, että tekemäsi muutokset toimivat.

Määrittääkseen luotavan komponentin menetelmät kehittäjän on otettava käyttöön seuraavat menetelmät AddInNative-kirjastokoodissa:
GetNMethods, FindMethod, GetMethodName
Suunniteltu hankkimaan vastaava määrä menetelmiä, etsi menetelmän numero ja nimi. Samanlainen kuin vastaavat ominaisuuksien menetelmät
Hanki NParams
Palauttaa menetelmäparametrien määrän määritetyllä järjestysnumerolla; jos menetelmä, jolla on tämä numero, puuttuu tai sillä ei ole parametreja, palauttaa arvon 0
GetParamDefValue
Palauttaa määritetyn menetelmän määritetyn parametrin oletusarvon
HasRetVal
Palauttaa lipun siitä, onko menetelmällä, jolla on määritetty järjestysarvo, palautusarvo: true menetelmille, joilla on palautusarvo ja väärä muuten
CallAsProc
väärä, tapahtuu ajonaikainen virhe ja 1C: Enterprise -moduulin suoritus lopetetaan. 1C: Enterprise varaa ja vapauttaa muistin parametrijoukolle.
CallAsFunc
Suorittaa menetelmän määritetyllä järjestysnumerolla. Jos menetelmä palaa väärä, tapahtuu ajonaikainen virhe ja 1C: Enterprise -moduulin suoritus lopetetaan. 1C: Enterprise varaa muistin parametrijoukolle. Jos palautusarvo on merkkijono tai binääritietotyyppi, komponentti varaa muistia funktiolle AllocMemory muistinhallinta, kirjoittaa sinne dataa ja tallentaa tämän osoitteen rakenteen vastaavaan kenttään. 1C: Yritys vapauttaa tämän muistin soittamalla Vapaa muisti.
Menetelmien täydellinen kuvaus, mukaan lukien luettelo parametreista, on kuvattu yksityiskohtaisesti ITS-levyllä toimitetussa dokumentaatiossa.
Tarkastellaanpa edellä kuvattujen menetelmien toteutusta.
Komponenttikoodissa määritellään kaksi taulukkoa:
static wchar_t *g_MethodNames = (L"Ota käyttöön", L"Poista", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Ota käyttöön", L"Poista käytöstä", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
ja luettelointi:
enum Methods ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Aina viimeinen );
Niitä käytetään funktioissa GetNMethods, FindMethod Ja GetMethodName, analogisesti ominaisuuksien kuvauksen kanssa.
menetelmät Hanki NParams, GetParamDefValue, HasRetVal Työkonekytkin palauttaa vaaditun arvon hyväksytyistä parametreista ja sovelluslogiikasta riippuen. Menetelmä HasRetVal sen koodissa on luettelo vain menetelmistä, jotka voivat palauttaa tuloksen. Heille hän palaa totta. Kaikille teräsmenetelmille palautukset väärä.
menetelmät CallAsProc Ja CallAsFunc sisältävät menetelmän suoraan suoritettavan koodin.
Jos haluat lisätä menetelmän, jota voidaan kutsua vain funktiona, sinun on tehtävä seuraavat muutokset ulkoisen komponentin lähdekoodiin:
  1. Lisää menetelmän nimi taulukoihin g_MethodNames Ja g_MethodNamesRu(tiedosto AddInNative.cpp)
  2. Lisää merkityksellinen menetelmätunniste Methods-luetteloon (tiedosto AddInNative.h)
  3. Tee muutokset toimintokoodiin Hanki NParams ohjelman logiikan mukaisesti
  4. Tee tarvittaessa muutoksia menetelmäkoodiin GetParamDefValue, jos haluat käyttää menetelmäparametrien oletusarvoja.
  5. Tee muutoksia toimintoon HasRetVal
  6. Tee muutoksia funktioiden logiikkaan CallAsProc tai CallAsFunc, sijoittamalla menetelmän suoraan suoritettavan koodin sinne
Esitellään taulukot g_MethodNames Ja g_MethodNamesRu, sekä listaus menetelmät lomakkeeseen:
static wchar_t *g_MethodNames = (L"Ota käyttöön", L"Poista", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Ota käyttöön", L"Poista käytöstä", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Enum Methods ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Aina viimeinen );
Muokataan funktiota Hanki Nprops niin, että se palauttaa "Testi"-menetelmän parametrien määrän:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; oletus: return 0; ) return 0; )
Tehdään muutoksia funktioon:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) (TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case e MethStartTimer: tapaus eMethStopTimer: tapaus eMethTest : / / Parametriarvoja ei ole oletusarvoisesti: return false;
Kiitos lisätyn linjan
tapaus eMethTest:
jos yksi tai useampi argumentti puuttuu, vastaavilla parametreilla on tyhjä arvo ( VTYPE_EMPTY). Jos tarvitset parametrille oletusarvon, aseta se osiossa eMethTest toimintokytkimen lausunto CAddInNative::GetParamDefValue.
Koska testimenetelmä voi palauttaa arvon, sinun on tehtävä muutoksia funktiokoodiin HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; oletus: return false; ) return false; )
Ja lisää menetelmän suoritettava koodi funktioon CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetArray, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( case eMethLoadT case:eMethLoadT; case eMethLoadP; if (!lSizeArray || !paParams) return s1 = (paParams) -> pwstrVal ;
Käännetään komponentti ja tuodaan konfigurointikoodi lomakkeeseen:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy () Yhdistä ulkoinen komponentti ("...", "DemoVK", ulkoisen komponentin tyyppi. Alkuperäinen); DemoComp = Uusi("AddIn.DemoVK.SomeName"); kaista = DemoComp.Test("Hei", "Maailma!"); Raportti(per); Menettelyn loppu
Konfiguroinnin käynnistämisen jälkeen saamme viestin: "Hei, maailma!", joka osoittaa, että menetelmä toimi onnistuneesti.

Ajastin

Tehtävä:
  1. Tutki ajastimen toteutusta demo-VK:ssa
  2. Muokkaa StartTimer-menetelmää lisäämällä parametreihin mahdollisuus välittää ajastimen vasteaika (millisekunteina)
  3. Varmista, että tekemäsi muutokset toimivat.

WinAPI:ssa voit käyttää sanomaa työskennelläksesi ajan kanssa WM_TIMER. Tämä viesti lähetetään ohjelmallesi aikavälillä, jonka määritit ajastimen luomisen yhteydessä.
Voit luoda ajastimen käyttämällä toimintoa Aseta ajastin:
UINT SetTimer(HWND hWnd, // ikkunakuvaus UINT nIDevent, // ajastimen tunniste (numero) UINT nElapse, // viive TIMERPROC lpTimerFunc); // osoitin toimintoon
Käyttöjärjestelmä lähettää viestin WM_TIMER ohjelmaan argumentissa määritetyllä aikavälillä nElapse(millisekunteina). Viimeisessä parametrissa voit määrittää toiminnon, joka suoritetaan aina, kun ajastin laukeaa. Tämän funktion otsikon pitäisi näyttää tältä (nimi voi olla mikä tahansa):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Tarkastellaanpa ajastimen käyttöönottoa demo-VC:ssä.
Koska harkitsemme ulkoisen komponentin kehittämistä Windows-käyttöjärjestelmäperheelle, emme harkitse ajastimen käyttöönottoa muissa käyttöjärjestelmissä. Erityisesti GNU/Linux-käyttöjärjestelmässä toteutus eroaa funktion syntaksista Aseta ajastin Ja TimerProc.
Suoritettava koodi kutsuu menetelmää Aseta ajastin, jolle funktio välitetään MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
Luodun ajastimen tunnus sijoitetaan muuttujaan m_uiTimer jotta se voidaan poistaa käytöstä myöhemmin.
Toiminto MyTimerProc seuraavasti:
VOID CALLBACK MyTimerProc(HWND hwnd, // ajastinviestien ikkunan kahva UINT uMsg, // WM_TIMER viesti UINT idEvent, // ajastimen tunniste DWORD dwTime // nykyinen järjestelmäaika) ( if (!pAsyncEvent) return; wchar_t "ComponentNative", *what = L"Ajastin"; wchar_t *wstime = uusi wchar_t; , what, wstime);
Toiminnon ydin on, että menetelmää kutsutaan Ulkoinen tapahtuma, joka lähettää viestin 1C: Enterprise -järjestelmään.
Laajentaa menetelmän toimivuutta Aloitusajastin Toimitaan seuraavasti:
Metodikoodin muuttaminen Hanki NParams joten se on menetelmää varten eMethStartTimer palautti arvon 1:
case eMethStartTimer: paluu 1;
Tässä on menetelmäkoodi CallAsProc lomakkeeseen:
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;
Nyt tarkistetaan toimivuus. Tätä varten kirjoitamme koodin määrityksen hallittavaan sovellusmoduuliin:
muuttuja DemoComp; Toimenpide, kun järjestelmä käynnistyy() Yhdistä ulkoinen komponentti("...", "DemoVK", ulkoisen komponentin tyyppi.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Menettelyn loppu
Konfiguroinnin aloittamisen jälkeen ohjelma vastaanottaa viestejä 2 sekunnin välein, mikä osoittaa, että ajastin toimii oikein.

Vuorovaikutus 1C: Enterprise -järjestelmän kanssa

Vuorovaikutukseen ulkoisen komponentin ja 1C: Enterprise -järjestelmän välillä, tiedostossa kuvatut IAddInDefBase-luokan menetelmät AddInDefBase.h. Listaamme yleisimmin käytetyt:
Virheilmoituksen luominen
virtuaalinen bool ADDIN_API AddError (allekirjoittamaton lyhyt wcode, const WCHAR_T* lähde, const WCHAR_T* descr, pitkä koodi)
wcode, scode- virhekoodit (luettelo virhekoodeista ja kuvaukset löytyvät ITS-levyltä)
lähde- virheen lähde
descr- virheen kuvaus
Viestin lähettäminen 1C: Enterprise -järjestelmään
virtuaalinen bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- viestin lähde
wszMessage- Viestin teksti
wszData- siirretyt tiedot
Viestien sieppaus suoritetaan External Event Processing -menettelyllä
Ulkoisen komponentin rekisteröinti 1C: Enterprise -järjestelmässä
virtuaalinen bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- komponentin nimi.
Nämä menetelmät riittävät täydelliseen vuorovaikutukseen VK:n ja 1C:n välillä. Jotta ulkoinen komponentti vastaanottaa tietoja 1C: Enterprise -järjestelmästä ja päinvastoin, ulkoinen komponentti lähettää erityisen viestin, jonka 1C-järjestelmä sieppaa ja tarvittaessa kutsuu ulkoisen komponentin menetelmiä tietojen lähettämiseksi takaisin .

tVariantin tietotyyppi

Kun tietoja vaihdetaan ulkoisen komponentin ja 1C: Enterprise -järjestelmän välillä, käytetään tVariant-tietotyyppiä. Se on kuvattu Types.h-tiedostossa, joka löytyy ITS-levyltä:
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 uintt.2 _t errCode: wchar_tVal; struct tmVal; __VARIANT_NAME_2/*iface*/; ) __VARIANT_NAME_1 ; mittataulukko pvarVal TYPEVAR vt);
Tyyppi tVariantti on rakenne, joka sisältää:
  • seos (liitto), joka on tarkoitettu suoraan tietojen tallentamiseen
  • tietotyypin tunniste
Yleensä työskentely tyyppisten muuttujien kanssa tVariantti tapahtuu seuraavan algoritmin mukaan:
  1. Muuttujaan tällä hetkellä tallennettujen tietojen tyypin määrittäminen
  2. Siirry vastaavaan sekoituskenttään päästäksesi suoraan tietoihin
Tyypin käyttäminen tVariantti yksinkertaistaa merkittävästi 1C: Enterprise -järjestelmän ja ulkoisten komponenttien vuorovaikutusta

Sovellus

"Esimerkit" -hakemisto sisältää esimerkkejä artikkelista
esimerkit/1 - käynnistä demokomponentti
esimerkit/2 - esittely kiinteistöluettelon laajentamisesta
esimerkit/3 - esitys menetelmäluettelon laajentamisesta
Jokainen hakemisto sisältää VS 2008 -projektin ja valmiin 1C-kokoonpanon.

Tämä artikkeli on omistettu ulkoisten komponenttien kanssa työskentelemiseen, nimittäin niiden yhdistämiseen. Tällä hetkellä 1C Enterprisen ominaisuuksien laajentamiseksi käytetään kahta ulkoisten komponenttien teknologiaa:

  • 1 Native API:n käyttäminen
  • 2 COM-tekniikan käyttö
Tässä artikkelissa päätin korostaa natiivi API-komponenttien kanssa työskentelemistä.
Joten aloitetaan yksinkertaisesta monimutkaiseen:
Ote ITS:stä

1. Oletetaan, että VK:mme sijaitsee tietyssä hakemistossa levyllä:

Voidaan käyttää "Thick Client (tavallinen sovellus)";

Tämä on yksinkertaisin esimerkki alkuperäiskomponentin kanssa työskentelystä. Huomaa, että tämän tyyppinen komponentti ei vaadi rekisteröintiä järjestelmään, mikä yksinkertaistaa huomattavasti hallintoa.

2. Edellä käsitelty esimerkki ei ole ollenkaan realistinen. Useimmiten komponentti sijoitetaan asetteluun. Asettelussa on oltava zip-arkisto komponenttitiedostoineen ja MANIFEST.xml-tiedosto
Esimerkkiluettelotiedosto:

3. Kun työskentelet ohuella ja web-asiakkaalla, muista käyttää menetelmää.
Lainaus ITS:stä:

Selitys:
%APPDATA%\1C\1Cv82\ExtCompT- hakemisto komponenttien asennusta varten Thick- ja Thin-asiakkaille.
%APPDATA%\Roaming\Mozilla\Extensions- hakemistolaajennukset (minun tapauksessani) Mozilla FF/
Kun käytät menetelmää Aseta ulkoinen komponentti(), käytetystä asiakkaasta riippuen laajennukset puretaan sopivaan hakemistoon.

Esimerkki ulkoisen komponentin asennusmenettelystä:

Asenna ulkoinen komponentti- menetelmää tulee kutsua vain komponentin alkuasennuksen aikana ja siinä tapauksessa, että komponentin asennettu versio on päivitettävä.

Ohut ja paksut asiakkaat:
Riittää, kun ulkoisen komponentin asennus suoritetaan uudelleen menetelmällä Asenna ulkoinen komponentti().

Kun kyseessä on web-asiakas päivittääksesi komponentin:

  • On tarpeen poistaa laajennus verkkoselaimen lisäosien kanssa työskentelymekanismin kautta (Mozilla FF)
  • Käytä menetelmää Asenna ulkoinen komponentti
Voit yhdistää VK:n seuraavasti:

Jos komponenttia ei ole asennettu, tehdään poikkeus.

2. Joissakin tapauksissa komponentti on asennettava väliaikaisesta tallennustilasta (tiedosto on saatu kolmannen osapuolen lähteestä, ulkoisesta käsittelystä), tässä tapauksessa ensimmäiset parametrit menetelmissä Yhdistä ulkoinen komponentti ja Asenna ulkoinen komponentti ovat väliaikaisessa varastossa olevan arkiston osoite. Alla on esimerkki siitä, kuinka se toimii:

&OnClient VariableAddressArchiveComponent; &OnClient-muuttujakomponentti; &OnClient Procedure OnOpen(Failure) // osoite, sisältää merkkijonon (navigointilinkki zip-arkiston binääritietoihin // väliaikaisessa tallennustilassa) ComponentArchiveAddress = GetArchiveAddressInTemporaryStorage(); EndProcedure // WhenOpen() &OnServer // menetelmät ConnectExternalComponent, SetExternalComponent voi ottaa // ensimmäisenä parametrina merkkijonon muodossa "navigointilinkki" // (URL-osoite ulkoiseen komponenttiin, joka on pakattu ZIP-arkistoon, muodossa, joka on samanlainen kuin // GetNavigationLink ). Funktio GetArchiveAddressInTemporaryStorage()ProcessingObject = FormAttributesValue("ProcessingObject"); Arkistolinkki = PlaceInTemporaryStorage(ProcessingObject.GetLayout("MIKO_phone_IP"), Uusi yksilöllinen tunniste); ReturnLinkToArchive; EndFunction // GetArchiveAddressInTemporaryStorage() &OnClient // Proseduuri tulee kutsua vain kerran, jos komponenttia ei ole vielä asennettu // tai se on päivitettävä. Poikkeusraportti("Ulkoisen komponentin asennus epäonnistui."); EndAttempt; Toimenpiteen loppu // InstallComponent() &OnClient // päämenettely komponentin alustamiseksi Toimenpide Initialize(Command) Yritä yhdistää ulkoinen komponentti(ComponentArchiveAddress,"Comp" ,ExternalComponentType.Native); Komponentti = Uusi("AddIn.Comp.MIKO_phone_IP"); Exception Report("Alustuspoikkeus. Komponenttia ei ehkä ole vielä asennettu."); EndAttempt; Menettelyn loppu