Nuove versioni di “1C: Trade Management”: aggiornamento senza sviluppo. La contabilità operativa viene regolamentata


Ciò è dovuto ad alcune peculiarità della funzione di contesto globale ConnectExternalComponent() .

Spesso i programmatori hanno problemi a connettere componenti esterni (ad esempio driver per apparecchiature commerciali) quando gli utenti lavorano con 1C, connettendosi al server tramite un terminale.

In questo caso, gli utenti vedono, ad esempio, questa immagine:

Mentre quando si lavora da computer locali non ci sono problemi con il collegamento di componenti esterni.

A cosa è collegato questo? Questo perché quando gli utenti lavorano tramite un server terminal, hanno meno diritti rispetto a quando lavorano su un computer locale.

Puoi verificarlo facilmente se accedi al server terminal con un account con diritti amministrativi.

Il motivo di questa differenza è che 1C non può registrare un componente esterno nel registro quando l'utente lavora nel terminale con diritti normali, perché un utente normale non dispone dell'autorizzazione per scrivere nel ramo del registro di sistema HKEY_CLASSES_ROOT.

Le pubblicazioni sul tema del collegamento di componenti esterni al terminale offrono diversi metodi per risolvere questo problema.

Ad esempio, questi:

1. Avvia 1C per la prima volta con diritti amministrativi.

Questa opzione non funziona sempre. Spiegherò perché di seguito.

2. Concedere agli utenti terminali ordinari il permesso di scrivere nel ramo del registro di sistema HKEY_CLASSES_ROOT.

È meglio che gli utenti non sufficientemente “avanzati” non lo facciano, altrimenti potrebbero esserci problemi.

3. Utilizzando vari gadget, registra VK per conto di un utente con diritti completi.

Non va neanche bene.

Allora qual è il modo migliore per uscire da questa situazione?

Offro la mia soluzione a questo problema. Secondo me: semplice e bello.

Durante la ricerca di questo problema, mi sono posto la domanda: perché 1C sta tentando di registrare VK utilizzando un nuovo percorso? Dopotutto, è già registrata nel sistema.

Il punto si è rivelato essere che nelle tipiche configurazioni 1C (ad esempio "Gestione commerciale") viene utilizzata la seguente sintassi per il metodo del contesto globale Connect External Component():

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

Come puoi vedere, il driver VC è collegato dal layout "ATOLBarcode Scanner Driver" della directory "Attrezzatura connessa".

Cosa succede allora?

1C salva il componente nella cartella temporanea dell'utente, ad esempio "C:\Documents and Settings\Utente\Impostazioni locali\Temp\1032\v8_4_12.tmp"

e tenta di registrarlo nel ramo del registro HKEY_CLASSES_ROOT esattamente lungo questa strada.

Sul terminale, gli utenti ordinari non hanno i diritti per modificare questo ramo del registro, quindi il componente non si connette a loro.

Ora parliamo di come uscire da questa situazione.

Il metodo del contesto globale ConnectExternalComponent() dispone di diverse opzioni di sintassi. Questo è ciò che useremo.

Quindi, passo dopo passo:

1. Registrare il componente esterno utilizzando l'utilità regsvr32.exe sul server terminal nella cartella C:\WINDOWS\SYSTEM32 per un sistema operativo a 32 bit o nella cartella C:\WINDOWS\SYSWOW64 per un sistema operativo a 64 bit.

2. Utilizzare una delle due opzioni di sintassi aggiuntive per il metodo ConnectExternalComponent():

Opzione 1:

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

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

Opzione 2:

ProgID = "AddIn.Scaner45";

ConnettiComponenteEsterno(ProgID);

OggettoDriver = Nuovo(ProgID);

A mio parere è preferibile l’opzione numero 2.

Allo stesso tempo, 1C non tenta di registrare nuovamente il VK utilizzando un nuovo percorso nel registro e quindi tutti i problemi vengono risolti.

Bene, questo è tutto. Buona fortuna per il lavoro!

[è necessario registrarsi per visualizzare il collegamento]

Domanda: Componente esterno Api nativo in C++ per Linux (Ubuntu x64) su 1C 8.3


Sto scrivendo a VK, ma non riesco a connettermi a 1c su Ubuntu. Anche l'exe 1s non si connette. Quindi una domanda a riguardo:

1) Sto provando a connettere VK dall'esempio VNCOMPS fornito nell'articolo

(il link si trova alla fine: “Copia”).
C'è un makefile all'interno del progetto NativeApi. Con il suo aiuto sto costruendo una libreria .so su Ununtu.
Ma quando “Collega componente esterno” 1c si blocca.
Allo stesso modo, se costruisco usando "build.sh" (nella radice del progetto).

Nel makefile stesso cambio il flag da m32 a m64, perché 1c e il sistema x64 stesso. (con il parametro m32 non si connette comunque)
Ecco un esempio di chiamata VK da 1C 8.3:
Connessione completata = ConnettiComponenteEsterno("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); C'è un articolo proprio su questo argomento.
Ma, per quanto vedo, tutti questi punti sono già stati presi in considerazione e corretti nell'esempio VNCOMPS.

Ma essenzialmente è una questione di parametri di compilazione. Un componente esterno MB a 32 bit si connette normalmente a un 1c a 32 bit, ma l'ho distribuito su Ubuntu x64 1c enterprise83 8.3.5-1486 amd64. E voglio incontrarla su VK.

Qualcuno ha qualche idea su come risolvere questo problema?)
L'esempio VNCOMPS dovrebbe funzionare, ma i parametri di creazione devono essere modificati oppure la piattaforma stessa su cui sto testando non è corretta.

Risposta: Mi chiedo, è possibile scrivere un componente esterno in Java?

Domanda: Impossibile collegare il componente esterno (nativo).


Ho compilato un esempio con ITS, per sistemi a 64 e 32 bit.

Mi collego così:
Risultato della connessione = ConnectExternalComponent(KDLLPath, "Comp", ExternalComponentType.Native); La connessione funziona su un PC, ma non sull'altro. C'è una differenza nel sistema operativo. Dove viene stabilita la connessione c'è Win7, dove non c'è Win10. Allo stesso tempo, sul PC dove il mio componente non funziona, funzionano i componenti standard.

Testato su diverse piattaforme (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).

Come posso capire perché non si connette?

Risposta: vc_redist dimenticato?

Domanda: 1C8 e un componente esterno di tipo Native


Buon pomeriggio.
Ho una configurazione BP 3.0.50.12 e desidero implementarvi la pesatura dell'azienda Vesy-Soft utilizzando UniServerAuto.
Gli sviluppatori hanno compilato il componente in Native per Windows 32 e 64 e lo hanno archiviato con il file maifest. C'è anche un esempio per 1C di come può essere calcolato il peso. In esso, utilizzando un layout con dati binari, è indicato questo archivio, a quanto ho capito. Nell'esempio va tutto bene: il componente viene installato, collegato, quindi viene stabilita la connessione e viene letto il peso.
Ma non appena inizi a trasferirlo su 1C, il peso non viene letto. Tutto sembra scritto in modo semplice, ma non capisco dove sia il rastrello.
Chi ha un po' di tempo aiuta, guarda con un occhio, forse la soluzione è in superficie, ma sto andando da qualche parte nel posto sbagliato e sto facendo la cosa sbagliata. Non ho mai dovuto lavorare con la tecnologia nativa prima...

E in allegato c'è il mio testo in elaborazione

Risposta:

Beh, ho delle novità...
Ho appena iniziato a vedere passo dopo passo a che punto avrebbe iniziato a fallire. Per fare ciò ho creato un database vuoto e l'ho elaborato con il comando. Per analogia con l'esempio del fornitore, ho trasferito il layout in una nuova configurazione: funziona la seconda volta. Quelli. la prima volta no, la seconda sì. Da qui l'idea che nelle nostre lavorazioni sarebbe stato comunque necessario separare il collegamento tra il componente e l'oggetto secondo procedure diverse.
Poi l'ho trasferito nel mio database collegando il layout: funziona. Uff, va bene.... Ma vorrei senza apportare modifiche alla configurazione, quindi andiamo avanti

Sto cercando di aggiungere il layout all'elaborazione. Le sue dimensioni aumentano immediatamente da 10kb a 3mb e si nota un notevole rallentamento del funzionamento: non è adatto. Sto iniziando a scavare verso il collegamento di componenti tramite dll. Quelli. essenzialmente lo stesso da dove ho iniziato. Ma ce n'è uno "MA": durante la ricerca del nome della dll nella cartella dell'utente, ho notato che questa dll si trova dove (a quanto ho capito) vengono sommate le dll registrate in 1C:
C:\Utenti\UTENTE\AppData\Roaming\1C\1cv8\ExtCompT
Di conseguenza, non è necessario utilizzare il percorso completo della DLL, è sufficiente inserire semplicemente il suo nome:
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

Provo... giura alla registrazione, ma restituisce il risultato della pesatura. Si scopre che la DLL è già registrata e ciò significa che devi solo collegarla. Lo rimuovo e funziona tutto.
Riassumendo:
1. Nell'elaborazione della pesatura la procedura All'Apertura prevedeva il collegamento di un componente esterno ed il collegamento ad un oggetto.
2. Percorso della dll non l'ho scritto, ho solo indicato il suo nome.

Ora sono seduto e penso, quando è stata installata la DLL in 1C? Al momento dell'installazione del software? Difficilmente... Al momento dell'esecuzione della configurazione sviluppatore di questa DLL, dove viene installata quando viene aperto il modulo? Non lo so, ma mi sembra vicino... Cosa ne pensi?
E in secondo luogo, in un posto nuovo, quando è necessario installare lo stesso terminale, cosa è necessario fare affinché tutto funzioni? Dovrei installare completamente il software, eseguire la configurazione del fornitore per verificare il funzionamento e poi (in teoria) la mia elaborazione dovrebbe funzionare? Qualcosa è in qualche modo complicato... Oppure dovrei installare il componente esterno una volta durante l'elaborazione dopo aver installato il software?

Mi piacerebbe sentire la tua opinione su questo argomento...

Domanda: Component.dll esterno


Buon giorno a tutti.
Una domanda.
Un componente dll che funziona alla grande in 1C 7.7
1s 8.1 non vuole avviarsi affatto...
Ho provato a incollarlo in C:\Program Files\1cv81\bin\cache1c.dll
Ho provato a registrarmi utilizzando regsvr32 "C:\Program Files\1cv81\bin\cache1c.dll"
Registra senza problemi.
Quando voglio accedervi, ricevo un messaggio di errore:

Errore durante il caricamento del componente esterno! cache1c.dll
Procedura PulsanteEseguiPremi(Pulsante) Tentativo di caricare il componente esterno( "C:\Programmi\1cv81\bin\cache1c.dll"); Rapporto sulle eccezioni ( "Errore durante il caricamento del componente esterno!"+ "cache1c.dll" ); Finetentativo; Tentativo // Ottenere l'oggetto componente. // m = Nuovo ("cache1c.GTMcmd" ); m = Nuovo COMObject("cache1c.GTMcmd"); Rapporto eccezioni(); Finetentativo; FineProcedura

Risposta:È banale fino all'impossibile...
È necessario fare una pausa tra le chiamate (millisecondi)...
Procedura ButtonExecutePress(Button) Tentativo // Ottieni un oggetto componente. m = Nuovo COMObject("cache1c.GTMcmd" ); Rapporto sulle eccezioni ( "Impossibile creare l'oggetto componente esterno"); Finetentativo; m.RemoteHost = "192.168.1.101"; m.PortaRemota = 6330; m.Connetti(); m.Pausa(100); ...... eccetera
Per 1c 7.7 - questo non è necessario, risulta che la gestione è più veloce.

Domanda: Lavorare con un componente esterno con un server 1C...


Buon pomeriggio,

Esiste un componente esterno scritto in C++, il cui compito è ottenere informazioni da un database esterno e restituire il risultato della query sotto forma di tabella di valori in 1C.
Per generare una tabella di valori al momento attuale, viene utilizzata l'interfaccia IDispatch* pBackConnection, ricevuta come parametro nella funzione Init(). Successivamente, utilizzo semplicemente le funzioni 1C per creare una tabella di valori, riempirla e restituirla al secondo parametro in CallAsFunc(...).
I problemi sono iniziati con il passaggio ai thin client 1C. Lato server il componente esterno non si avvia realmente. Puoi eseguirlo sul lato client, ma sembra tutto una stampella e non rientra nella logica generale "client-server" in 1C. Ad esempio, il cliente non capisce cos'è una tabella di valori, problemi con variabili "globali", sessioni, ecc.
NativeAPI è ancora più limitata a questo riguardo.
Ballare con un tamburello ha portato al fatto che sono riuscito a lanciare un componente esterno sotto il server 1C, MA il lavoro continua finché non si tenta di chiamare Invoke su pBackConnection. La versione a 64 bit del server 8.2 tenta di fare qualcosa finché non scade, la versione a 32 bit (VK è naturalmente anche a 32 bit) cade immediatamente.
Presumo che il server 1C non supporti questa modalità operativa.
Di conseguenza sorgono domande: è temporaneo o la logica 1C si riduce all'annullamento di questo schema di lavoro? Se è impossibile creare strutture 1C interne (una tabella di valori) in questo modo, esiste, in linea di principio, una descrizione di cosa sia una tabella di valori a livello di sistema per provare a crearla in C++, riempirlo e poi inserirlo semplicemente in 1C come parametro di ritorno? Vorrei almeno avere una direzione in cui scavare.

Grazie.

Risposta:

Scrivi una cosa e ne intendi un'altra.
Nell'ambiente 1C, dichiarare variabili che saranno visibili in sessioni diverse non è ora impossibile e prima non esisteva tale possibilità. Un'altra sessione è un processo fisicamente diverso.
Una sessione è una sessione che si connette a un database, ad es. sessione utente. Oppure stai mettendo qualcosa di tuo in questo concetto?

All'interno di una sessione era possibile, ed è ora possibile, dichiarare variabili nel modulo di sessione che vivranno e saranno visibili all'interno della sessione da luoghi diversi... in realtà ce ne sono 4.
- Modulo di sessione;
- Modulo di domanda regolare;
- Modulo applicativo gestito;
- Modulo di connessione esterno.

Beh, ovviamente, devi ricordare il contesto. Il contesto del server non è direttamente accessibile dal lato client e viceversa.

Infatti, l’architettura 1C prevede che lo scambio di dati avverrà come segue:
- tramite parametri/ritorni di procedure/funzioni;
- tramite i cosiddetti parametri di sessione (non possono essere oggetti, ma effettivamente visibili nella palette).

Una tabella nel modulo... è collegata a qualche tabella di oggetti (elaborazione, ad esempio)? o no. Se sì, allora è disponibile sul server (&OnServer) e modificabile lì....

Eppure sì, la Value Table non è disponibile nell'UV lato client. Bene, questo è ciò che ha deciso 1C.

Dai! Funziona con Excel, funziona con FSO e un sacco di altre cose, ma non funziona qui. Cattura l'errore e analizza....

Tentativo
...
le tue azioni
...
Eccezione
str = DescrizioneErrore();
Finetentativo;

Con le moderne funzionalità hardware, questo non è affatto un argomento.

Puramente la tua opinione personale. Non ha nulla a che fare con la realtà. Non in alcun modo. Ripeto ancora una volta, 1C funziona benissimo con COM. Sia con in-proc che out-proc.

Fornisci il codice che utilizzi per scaricare e contatta VK.

A proposito, VK... nel tuo caso è COM o API nativa?
Se COM, lo registri come... tramite regsvr32... come "risolvi" il problema della profondità di bit?

Domanda: Installazione di un componente esterno


Per favore dimmi come installare un componente esterno. Quando si esegue il codice seguente, viene generato un errore. Nel layout trova NameDecl.dll

Tentativo di SetExternalComponent("GeneralLayout.Layout"); Fine eccezioneTry;
Errore: installazione del componente esterno non riuscita!

Risposta: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native) restituisce FALSE.
New("AddIn.NameDecl.CNameDecl", Unfined) = (()): digitare undefinito (AddIn.NameDecl.NameDecl)

Domanda: La DLL nativa non si connette a 1c 8.1 (fptrwin32_fz54_9_11_0_5549.dll)


Ciao.
1C ha aggiornato la dll per i registratori di cassa online atol per ffd 1.05 (inclusa nell'elaborazione di manutenzione fptrwin32_fz54_9_11_0_5549.dll).
Ho un vecchio 1C 8.1. A differenza di 8.2, non supporta il lavoro con apparecchiature esterne allo stesso modo di 8.2, quindi devi prima registrare la dll in Windows e quindi collegarla solo a 1C?

ProgID = "AddIn.IntegrationComponent.ATOL_KKT_1C83_V9"; CaricaComponenteEsterno("C:\fptrwin32_fz54_9_11_0_5549.dll"); ConnectExternalComponent(progID); Driver = Nuovo(ProgID);

Tuttavia, la vecchia elaborazione era scritta in com "tecnologia" e quella nuova è nativa. Di conseguenza, durante la registrazione di regsvr32 viene visualizzato un errore:
Il modulo viene caricato, ma il punto di ingresso DllRegisterServer non viene trovato. E suggerisce di verificare che questo file sia il file dll o OCX corretto.
Qualcuno ha riscontrato una situazione simile e come ne è uscito? Capisco che 7.7 avrà un problema simile.
Codice 8.2:

Layout = GetLayout("Componente Integrazione"); Indirizzo = PlaceInTemporaryStorage(Layout); ConnectExternalComponent(Indirizzo, "IntegrationComponent", ExternalComponentType.Native); Driver = New("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

1C8.2:
ConnettiComponenteEsterno(<Местоположение>, <Имя>, <Тип>)
1C8.1:
ConnettiComponenteEsterno(<Идентификатор объекта>)
Opzioni:
<Идентификатор объекта>(necessario)
Tipo: corda. ProgID (Identificatore Programmatico) dell'oggetto componente esterno. Deve corrispondere alle informazioni presenti nel database di registrazione del sistema (Registro).
Descrizione:
Connette gli oggetti del componente esterno a 1C:Enterprise.
Non disponibile sul server 1C:Enterprise. Non utilizzato nel modulo di connessione esterno.
Nota:
I componenti esterni sono compatibili con i componenti 1C:Enterprise 7.7.
Esempio:
Tentativo
ConnectExternalComponent("AddinObject.Scanner");
Report("Il componente per lo scanner dei codici a barre è stato caricato");
Eccezione
Report("Il componente per lo scanner dei codici a barre non è caricato");
EndAttempt

C'è un modo per connettere questa DLL alla 8.1 o no?

Grazie!

Risposta:

Recentemente ho riscontrato anch'io questo problema. Non è stato possibile convertire a una versione successiva di 1c perché... dll con cui funziona questa configurazione ha semplicemente smesso di funzionare e 1c si è bloccato con un errore.
Ho risolto il problema come segue:
Ho creato un database 8.3 vuoto in cui ho elaborato l'inizializzazione del componente e poi da 8.1 tramite una connessione COM sono entrato nel database precedentemente creato e lì ho inizializzato il componente. Poi, già nella 8.1, ho richiamato i metodi di questo componente.
Ovviamente questa è una stampella, ma non ho ancora trovato altra via d'uscita(

Esempio di codice 8.3:
Esportazione driver variabile;
Funzione ConnectionComponentsKKT() Esportazione
Tentativo

Layout = GetLayout("Componente Integrazione");
Indirizzo = PlaceInTemporaryStorage(Layout);
ConnectExternalComponent(Indirizzo, "IntegrationComponent", ExternalComponentType.Native);
Driver = Nuovo("AddIn.IntegrationComponent.SMDrvFR1C20");
Risultato = Vero;​

Eccezione

Risultato = Falso;​

Finetentativo;
Risultato restituito
EndFunction

Esempio di codice 8.1

Funzione CreaDriverObject(Driver) Esporta

Risultato = Vero;

Tentativo

ConnectionString="File="""Percorso del database""";
ComObject = Nuovo COMObject("V83.ComConnector");
Connetti = ComObject.Connect(ConnectionString);

Elaborazione = Connect.Processing.ConnectExternalComponent.Create();
Risultato della connessione = Processing.ConnectionCCPComponents();
Se il risultato della connessione allora
Driver = Elaborazione.Driver;
FineSe;​

Eccezione
Chiunque abbia fatto ciò o si sia imbattuto in sentenze simili, spieghi il principio stesso utilizzando un semplice esempio. Sembra che tutto sia chiaro con il collegamento di componenti esterni.

// Esempio di riempimento della tabella dei valori TK.Cancella(); Richiesta = Nuova richiesta; Query.Text = "SELEZIONA | Nomenclatura.Link COME Nomenclatura |FROM | Directory.Nomenclature AS Nomenclature"; Richiesta risultato = Richiesta.Execute(); Selezione = Richiesta risultato.Select(); While Selection.Next() Ciclo Pagina = TK.Add(); Fill inPropertyValues(Pagina, Selezione); EndCycle;
Potresti usare questo esempio per spiegare quale parte del codice viene solitamente eliminata? Sarebbe logico togliere la parte con la richiesta, ma poi come possiamo accedere al database dal componente esterno, bypassando la piattaforma? Non ha senso far emergere il testo. Oppure elimina la formazione stessa della parte tabulare. Condividi la tua esperienza con chiunque abbia riscontrato questo problema.

Risposta: E che la parola “Incompatibile” significa sempre la parola “Cattivo”? Sì, mi sembra che se chiamassi il mio stile “1C: La peggiore programmazione su questo motore di scripting che esiste in natura (tradotta in linguaggio letterario)!” e poi probabilmente ci saranno persone che vorranno dare un'occhiata a questa bestia. E sembra un classico: "Non ho letto Pasternak, ma non sono completamente d'accordo con lui!"

Domanda: Collegamento di un componente esterno in 1s 8.3.6 e Win8


È necessario connettere il componente esterno vk_rs232.dll alla configurazione personalizzata. Sembra che sia stato registrato tramite regsvr32.exe. “Sembra” perché ho ricevuto il messaggio che “il componente è registrato, ma c'è qualcosa che non va nel firewall”. Basandomi sulla prima metà del messaggio, scrivo il codice in 1C
AfterConnecting = Nuova descrizione avviso ("AfterConnectingVK", ThisForm); StartInstallingExternalComponents(,"C:\Controller\vk_rs232.dll"); StartConnectingExternalComponents(AfterConnecting,"C:\Controller\vk_rs232.dll","DLL_Scales");
e ottengo l'errore that
"L'installazione di un componente esterno non è riuscita! Potrebbe mancare un componente per l'applicazione client che stai utilizzando!".

E ora non capisco:
1. Forse il componente non è registrato nel registro: come posso verificarlo lì?
2. Forse la sua "versione" non funziona con Win8, anche se ce l'ho a 32 bit.
3. Forse 1C stesso è troppo nuovo, ad es. Di conseguenza, non può funzionare con questa DLL?
4. Beh, è ​​banale: sto scrivendo qualcosa di sbagliato.

Risposta: E tutto ciò mi ha portato al problema successivo. VneshComp è installato, ora devi collegarlo. E qui ci sono entrambe le opzioni
ConnectExternalComponent("C:\Controller\vk_rs232.dll","Libra")
ConnectExternalComponent("GeneralLayout.Layout","Libra")

Opzione di sintassi: Per nome e posizione

Sintassi:

ConnettiComponenteEsterno(<Местоположение>, <Имя>, <Тип>)
Opzioni:

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

Tipo: corda.
La posizione del componente esterno.
La posizione può essere utilizzata:
percorso del file del componente esterno sul file system (non disponibile sul client Web), non un archivio ZIP;
il nome completo del layout in cui sono archiviati i dati binari o l'archivio ZIP;
L'URL del componente esterno, come dati binari o archivio ZIP, in un formato simile a GetNavigationLink.
<Имя>(necessario)

Tipo: corda.
Il nome simbolico del componente esterno da collegare.
Il nome deve seguire le convenzioni di denominazione del linguaggio integrato.
<Тип>(opzionale)

Tipo: TipoComponenteEsterno.
Tipo di componente esterno da collegare.
Non utilizzato se il componente è confezionato in un archivio ZIP.
Descrizione dell'opzione del metodo:

Collega componenti realizzati utilizzando la tecnologia nativa e COM.
Il componente può essere archiviato nell'infobase o nel layout di configurazione come dati binari o in un archivio ZIP.
Per le modalità di avvio "Thin Client" e "Web Client", il componente deve essere prima installato utilizzando il metodo Installa componente esterno.
Opzione di sintassi: Per ID

Sintassi:

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

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

Tipo: corda.
Identificatore dell'oggetto componente esterno sotto forma di ProgID (Programmatic Identifier) ​​del registro di MS Windows (ad esempio: "AddIn.Scanner").
Deve corrispondere alle informazioni presenti nel database di registrazione del sistema (Registro).
Descrizione dell'opzione del metodo:

Il componente deve essere implementato utilizzando la tecnologia COM e registrato nel registro di MS Windows.
Questi componenti sono compatibili con i componenti 1C:Enterprise 7.7.
Attenzione! L'opzione del metodo non funziona sul server e nella connessione esterna.
Valore di ritorno:

Tipo: booleano.
Vero: la connessione è riuscita.
Descrizione:

Collega un componente esterno a 1C:Enterprise.
I componenti esterni possono essere archiviati in infobase o layout di configurazione come archivio ZIP o come dati binari o in un file system.
Quando si lavora su un thin client e un web client, il componente deve essere preinstallato.

Disponibilità:

Thin client, client Web, server, connessione esterna.
Nota:

I componenti esterni possono essere implementati utilizzando la tecnologia API nativa o COM. I componenti realizzati utilizzando la tecnologia COM sono compatibili con i componenti 1C:Enterprise 7.7.
Il client Web può funzionare solo con i componenti dell'infobase confezionati in un archivio.
Il thin client può funzionare con componenti nell'infobase, confezionati in un archivio e componenti posizionati nel file system.
Il Thick Client può gestire tutte le opzioni di archiviazione dei componenti. In questo caso, se un componente viene installato utilizzando il metodo Installa componente esterno, verrà utilizzato il componente installato e, se non installato, il componente verrà ricevuto al momento della connessione.
Il server può funzionare con tutti i componenti. Il componente viene memorizzato nella cache per sessione del server.
Esempio:

Se ConnectExternalComponent("AddinObject.Scanner") Allora
Report("Componente per scanner di codici a barre caricato");
Altrimenti
Report("Il componente per lo scanner dei codici a barre non è caricato");
finisci se;

  • Esercitazione

introduzione

Questo articolo dà un'idea di come funzionano i componenti esterni nel sistema 1C: Enterprise.
Verrà mostrato il processo di sviluppo di un componente esterno per il sistema 1C: Enterprise versione 8.2, in esecuzione sul sistema operativo Windows con una modalità operativa file. Questa opzione viene utilizzata nella maggior parte delle soluzioni progettate per le piccole imprese. VK sarà implementato nel linguaggio di programmazione C++.

Componenti esterni "1C: Enterprise"

"1C: Enterprise" è un sistema estensibile. I componenti esterni (EC) vengono utilizzati per espandere la funzionalità del sistema. Dal punto di vista dello sviluppatore, un VC è un oggetto esterno che ha proprietà e metodi e può anche generare eventi per l'elaborazione da parte del sistema 1C: Enterprise.
I componenti esterni possono essere utilizzati per risolvere una classe di problemi difficili o addirittura impossibili da implementare nel linguaggio di programmazione integrato in 1C: Enterprise. In particolare, questa classe comprende attività che richiedono un'interazione di basso livello con il sistema operativo, ad esempio per lavorare con apparecchiature specifiche.
Il sistema 1C: Enterprise utilizza due tecnologie per la creazione di componenti esterni:
  • utilizzando l'API nativa
  • utilizzando la tecnologia COM
Date le restrizioni indicate, la differenza tra le due tecnologie sopra menzionate è insignificante, quindi considereremo lo sviluppo di videogiochi utilizzando l'API nativa. Se necessario, gli sviluppi implementati possono essere applicati allo sviluppo di software per computer utilizzando la tecnologia COM e anche, con piccole modifiche, applicati per l'uso nel sistema 1C: Enterprise con altre opzioni operative diverse dalla modalità operativa file.
struttura VK
Il componente esterno del sistema 1C: Enterprise è presentato sotto forma di una libreria DLL. Il codice della libreria descrive la classe discendente IComponentBase. La classe creata deve definire metodi responsabili dell'implementazione delle funzioni del componente esterno. I metodi sovrascritti verranno descritti più dettagliatamente di seguito man mano che viene presentato il materiale.

Avvio di una demo VK

Compito:
  1. Assemblare un componente esterno fornito con un abbonamento ITS e destinato a dimostrare le principali capacità del meccanismo del componente esterno in 1C
  2. Collega il componente demo alla configurazione 1C
  3. Assicurati che le funzioni dichiarate funzionino correttamente
Compilazione
La demo VK si trova sul disco di abbonamento ITS nella directory "/VNCOMP82/example/NativeAPI".
Per creare la demo VC utilizzeremo Microsoft Visual Studio 2008. Altre versioni di questo prodotto non supportano il formato di progetto Visual Studio utilizzato.


Apri il progetto AddInNative. Nelle impostazioni del progetto includiamo la directory con i file header necessari per costruire il progetto. Per impostazione predefinita, si trovano sul disco ITS nella directory /VNCOMP82/include.
Il risultato della compilazione è il file /bind/AddInNative.dll. Questa è la libreria compilata per la connessione alla configurazione 1C.
Collegamento di VK alla configurazione 1C
Creiamo una configurazione 1C vuota.
Di seguito è riportato il codice per il modulo dell'applicazione gestita.
variabile DemoComp; Procedura all'avvio del sistema() Connetti il ​​componente esterno("...\bind\AddInNative.dll", "DemoVK", Componente esterno Type.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); FineProcedura
Se non è stato segnalato alcun errore durante l'avvio della configurazione 1C, il VK è stato connesso correttamente.
Come risultato dell'esecuzione del codice precedente, un oggetto appare nella visibilità globale della configurazione DemoComp, che dispone di proprietà e metodi definiti nel codice del componente esterno.
Dimostrazione della funzionalità integrata
Controlliamo la funzionalità della demo VK. Per fare ciò, proviamo a impostare e leggere alcune proprietà, chiamare alcuni metodi VK e anche ricevere ed elaborare il messaggio VK.
La documentazione fornita sul disco ITS indica le seguenti funzionalità del demo VC:
  1. Gestione dello stato dell'oggetto componente
    Metodi: Accendere, Spegnere
    Proprietà: Incluso
  2. Controllo del temporizzatore
    Ogni secondo il componente invia un messaggio al sistema 1C: Enterprise con parametri Componente, Timer e una linea di contatore dell'orologio di sistema.
    Metodi: StartTimer, StopTimer
    Proprietà: C'è un timer
  3. Metodo MostraInStatusLine, che visualizza il testo passato al metodo come parametri nella riga di stato
  4. Metodo Carica l'immagine. Carica un'immagine dal file specificato e la trasferisce al sistema 1C: Enterprise sotto forma di dati binari.
Assicuriamoci che queste funzioni funzionino. Per fare ciò, esegui il seguente codice:
variabile DemoComp; Procedura all'avvio del sistema() ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Rapporto (DemoComp.Abilitato); DemoComp.Enable(); Rapporto (DemoComp.Abilitato); DemoComp.StartTimer(); Fine della procedura Elaborazione eventi esterni (fonte, evento, dati) Report (fonte + " " + evento + " " + dati); FineProcedura
Il risultato dell'esecuzione della configurazione è mostrato nell'immagine


Il pannello "Messaggi" visualizza i risultati delle chiamate ai metodi DemoComp.Disable() E Demo.Comp.Enable(). Le righe successive nello stesso pannello contengono i risultati dell'elaborazione dei messaggi ricevuti da VK - Fonte, Evento E Dati rispettivamente.

Nome del componente esterno personalizzato

Attività: modificare il nome del componente esterno in uno arbitrario.
La sezione precedente utilizzava l'identificatore AddInNativeExtension, il cui significato non è stato spiegato. In questo caso AddInNativeExtension- questo è il nome dell'estensione.
Il codice VK definisce un metodo RegisterExtensionAs, restituendo il nome al sistema 1C: Enterprise, necessario per la successiva registrazione di VK nel sistema. Si consiglia di specificare un identificatore che in una certa misura riveli l'essenza del componente esterno.
Ecco il codice completo del metodo RegisterExtensionAs con il nome dell'estensione cambiato:
bool CAddInNative::RegisterExtensionAs(WCHAR_T** wsExtensionName) ( wchar_t *wsExtension = L"SomeName"; int iActualSize = ::wcslen(wsExtension) + 1; WCHAR_T* dest = 0; if (m_iMemory) ( if(m_iMemory->AllocMemory ((void**)wsExtensionName, iActualSize * sizeof(WCHAR_T))) ::convToShortWchar(wsExtensionName, iActualSize) return false;
Nell'esempio fornito, il nome VK viene modificato in QualcunoNome. Quindi quando colleghi VK devi specificare un nuovo nome:
DemoComp = New("AddIn.DemoVK.SomeName");

Espansione dell'elenco delle proprietà VK

Compito:
  1. Studiare l'implementazione delle proprietà VK
  2. Aggiungi una proprietà di lettura/scrittura di tipo stringa
  3. Aggiungi una proprietà di stringa di lettura/scrittura che memorizza il tipo di dati dell'ultimo set di proprietà. Non viene eseguita alcuna azione quando si imposta il valore della proprietà

Per determinare le proprietà del componente da creare, lo sviluppatore deve implementare i seguenti metodi nel codice della libreria AddInNative.cpp:
OttieniNProps
Restituisce il numero di proprietà di questa estensione, 0 se non sono presenti proprietà
TrovaProp
Restituisce il numero seriale della proprietà il cui nome viene passato nei parametri
OttieniNomeProp
Restituisce il nome della proprietà tramite il numero di serie e l'identificatore della lingua passato
OttieniPropVal
Restituisce il valore della proprietà con il numero ordinale specificato
SetPropVal
Imposta il valore della proprietà con il numero ordinale specificato
IsPropReadable
Restituisce il flag di leggibilità della proprietà con il numero di sequenza specificato
IsPropWritable
Restituisce il flag di scrivibilità della proprietà con il numero di sequenza specificato


Consideriamo l'implementazione dei metodi della classe sopra CDdInNative.
Nella demo VC sono definite 2 proprietà: Incluso E C'è un timer (È abilitato E ÈTimerPresente).
Nell'ambito globale del codice della libreria, sono definiti due array:
wchar_t statico *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Abilitato", L"È presente un timer");
che memorizzano nomi di proprietà russi e inglesi. Nel file di intestazione AddInNative.h l'enumerazione è definita:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Sempre ultimo );
ePropIsEnabled E ePropIsTimerPresent, aventi rispettivamente i valori 0 e 1, vengono utilizzati per sostituire i numeri seriali degli immobili con identificatori significativi. ePropLast, che ha valore 2, viene utilizzato per ottenere il numero di proprietà (utilizzando il metodo GetNProps). Questi nomi vengono utilizzati solo all'interno del codice componente e non sono disponibili dall'esterno.
I metodi FindProp e GetPropName eseguono ricerche nell'array g_PropNames E g_PropNamesRu.
Per memorizzare i valori dei campi nel modulo libreria, la classe CAddInNative dispone di proprietà che memorizzano il valore delle proprietà del componente. Metodi OttieniPropVal E SetPropVal return e imposta il valore di queste proprietà di conseguenza.
Metodi IsPropReadable E IsPropWritable e ritorno VERO O falso, a seconda del numero ordinale passato della proprietà in conformità con la logica dell'applicazione.
Per aggiungere una proprietà personalizzata è necessario:

  1. Aggiungi il nome della proprietà da aggiungere agli array g_PropNames E g_PropNamesRu(file AddInNative.cpp)
  2. Elencare Oggetti di scena(file AddInNative.h) Prima ePropLast aggiungere un nome che identifichi in modo univoco la proprietà da aggiungere
  3. Organizzare la memoria per memorizzare i valori delle proprietà (creare campi dei componenti del modulo che memorizzano i valori corrispondenti)
  4. Apportare modifiche ai metodi OttieniPropVal E SetPropVal per interagire con la memoria allocata nel passaggio precedente
  5. In conformità con la logica dell'applicazione, apportare modifiche ai metodi IsPropReadable E IsPropWritable
I punti 1, 2, 5 non necessitano di spiegazione. I dettagli sull'implementazione di questi passaggi possono essere trovati studiando l'appendice all'articolo.
Diamo nomi alle proprietà del test Test E Tipo di controllo rispettivamente. Quindi, come risultato del passaggio 1, abbiamo:
wchar_t statico *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Abilitato", L"È presente un timer", L"Test", L"Verifica tipo");
Trasferimento Oggetti di scena sarà simile a:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Sempre ultimo );
Per semplificare notevolmente il codice, utilizzeremo STL C++. In particolare, per lavorare con le corde WCHAR, colleghiamo la libreria wstring.
Per salvare il valore di un metodo Test, definiamo nella classe CDdInNative nell'ambito di un campo privato:
prova stringa1;
Per trasferire i parametri della stringa tra 1C: Enterprise e componenti esterni, viene utilizzato il gestore della memoria 1C: Enterprise. Diamo uno sguardo più da vicino al suo lavoro. Le funzioni vengono utilizzate rispettivamente per allocare e liberare memoria AllocMemory E Memoria libera, definito nel file ImemoryManager.h. Se è necessario passare un parametro stringa al sistema 1C: Enterprise, il componente esterno deve allocargli memoria chiamando la funzione AllocMemory. Il suo prototipo è simile a questo:
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
Dove pMemoria- l'indirizzo del puntatore in cui verrà inserito l'indirizzo dell'area di memoria allocata,
ulCountByte- dimensione dell'area di memoria allocata.
Un esempio di allocazione di memoria per una stringa:
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);
Per comodità di lavorare con i tipi di dati stringa, descriveremo la funzione wstring_to_p. Riceve una stringa wstring come parametro. Il risultato della funzione è una struttura piena tVariante. Codice funzione:
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)); restituisce vero)
Quindi la sezione case corrispondente dell'istruzione switch del metodo OttieniPropVal assumerà la forma:
case ePropTest1: wstring_to_p(test1, pvarPropVal); rottura;
Metodo SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) restituisce false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); rottura;
Per implementare la seconda proprietà, definiamo un campo di classe CaddInNative
uint8_t ultimo_tipo;
in cui salveremo il tipo dell'ultimo valore trasferito. Per fare ciò, aggiungi il comando al metodo CaddInNative::SetPropVal:
last_type = TV_VT(varPropVal);
Ora, quando richiederemo di leggere il valore della seconda proprietà, restituiremo il valore ultimo_tipo, cosa richiede l'attività designata.
Verifichiamo la funzionalità delle modifiche apportate.
Per fare ciò, presentiamo l'aspetto della configurazione 1C come segue:
variabile DemoComp; Procedura all'avvio del sistema() Connetti il ​​componente esterno("...", "DemoVK", Componente esterno Type.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.TypeCheck = 1; Report(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Report(String(DemoComp.Test)); DemoComp.Test = "Petya"; Report(String(DemoComp.Test)); Rapporto(String(DemoComp.TypeCheck)); FineProcedura
A seguito del lancio riceveremo una sequenza di messaggi:
3
Vasya
Peter
22

Il secondo e il terzo messaggio sono il risultato della lettura della proprietà impostata nel passaggio precedente. Il primo e il secondo messaggio contengono il codice tipo dell'ultimo set di proprietà. 3 corrisponde ad un valore intero, 22 ad un valore stringa. La corrispondenza dei tipi e dei loro codici è stabilita nel file tipi.h, che si trova sul disco ITS.

Ampliamento dell'elenco dei metodi

Compito:
  1. Estendi la funzionalità del componente esterno con la seguente funzionalità:
  2. Esplora i modi per implementare i metodi dei componenti esterni
  3. Aggiungi un metodo di funzione Funzione1, che accetta due stringhe (“Parametro1” e “Parametro2”) come parametro. Il risultato è una stringa del tipo: “Checking. Parametro1, Parametro2"
  4. Assicurati che le modifiche apportate funzionino.

Per definire le modalità del componente in creazione, lo sviluppatore deve implementare nel codice della libreria AddInNative i seguenti metodi:
Ottieni metodi N, Trovametodo, OttieniNomeMetodo
Progettato per ottenere il numero corrispondente di metodi, cercare il numero e il nome del metodo. Simile ai metodi corrispondenti per le proprietà
GetNParams
Restituisce il numero di parametri del metodo con il numero di sequenza specificato; se un metodo con questo numero è assente o non ha parametri, restituisce 0
GetParamDefValue
Restituisce il valore predefinito del parametro specificato del metodo specificato
HasRetVal
Restituisce il flag se il metodo con il valore restituito ordinale specificato ha un valore restituito: true per i metodi con un valore restituito e falso Altrimenti
CallAsProc
falso, si verifica un errore di runtime e l'esecuzione del modulo 1C: Enterprise viene terminata. La memoria per l'array di parametri viene allocata e rilasciata da 1C: Enterprise.
CallAsFunc
Esegue il metodo con il numero di sequenza specificato. Se il metodo restituisce falso, si verifica un errore di runtime e l'esecuzione del modulo 1C: Enterprise viene terminata. La memoria per l'array di parametri è allocata da 1C: Enterprise. Se il valore restituito è una stringa o un tipo di dati binario, il componente alloca memoria con la funzione AllocMemory gestore della memoria, scrive lì i dati e memorizza questo indirizzo nel campo corrispondente della struttura. 1C: L'azienda libererà questa memoria chiamando Memoria libera.
Una descrizione completa dei metodi, compreso l'elenco dei parametri, è descritta in dettaglio nella documentazione fornita sul disco ITS.
Diamo un'occhiata all'implementazione dei metodi sopra descritti.
Nel codice del componente sono definiti due array:
static wchar_t *g_MethodNames = (L"Abilita", L"Disabilita", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Abilita", L"Disabilita", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
ed enumerazione:
Metodi enum ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Sempre ultimo);
Sono utilizzati nelle funzioni Ottieni metodi N, Trovametodo E OttieniNomeMetodo, per analogia con la descrizione delle proprietà.
Metodi GetNParams, GetParamDefValue, HasRetVal implementare l'interruttore, a seconda dei parametri passati e della logica dell'applicazione, restituisce il valore richiesto. Metodo HasRetVal nel suo codice ha un elenco di soli metodi che possono restituire un risultato. Per loro ritorna VERO. Per tutti i metodi di reso in acciaio falso.
Metodi CallAsProc E CallAsFunc contenere il codice direttamente eseguibile del metodo.
Per aggiungere un metodo che può essere chiamato solo come funzione, è necessario apportare le seguenti modifiche al codice sorgente del componente esterno:
  1. Aggiungi il nome del metodo agli array g_MethodNames E g_MethodNamesRu(file AddInNative.cpp)
  2. Aggiungere un identificatore di metodo significativo all'enumerazione Methods (file AddInNative.h)
  3. Apportare modifiche al codice funzione GetNParams secondo la logica del programma
  4. Se necessario, apportare modifiche al codice del metodo GetParamDefValue, se si desidera utilizzare i valori predefiniti dei parametri del metodo.
  5. Apportare modifiche alla funzione HasRetVal
  6. Apportare modifiche alla logica delle funzioni CallAsProc O CallAsFunc, inserendo lì il codice direttamente eseguibile del metodo
Presentiamo gli array g_MethodNames E g_MethodNamesRu, nonché l'elenco Metodi al modulo:
static wchar_t *g_MethodNames = (L"Abilita", L"Disabilita", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Abilita", L"Disabilita", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Metodi Enum ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Sempre ultimo );
Modifichiamo la funzione OttieniNProps in modo che restituisca il numero di parametri del metodo “Test”:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( case eMethShowInStatusLine: return 1; case eMethLoadPicture: return 1; case eMethTest: return 2; default: return 0; ) return 0; )
Apportiamo modifiche alla funzione:
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum) ( case eMethEnable: case eMethDisable: case eMethShowInStatusLine: case eMethStartTimer : case eMethStopTime r: caso eMethTest : // Non ci sono valori dei parametri per default break; default: return false;
Grazie alla linea aggiunta
caso eMethTest:
se mancano uno o più argomenti, i parametri corrispondenti avranno un valore vuoto ( VTYPE_EMPTY). Se hai bisogno di un valore predefinito per un parametro, dovresti impostarlo nella sezione eMethTest istruzione di cambio funzione CAddInNative::GetParamDefValue.
Poiché il metodo Test può restituire un valore, è necessario apportare modifiche al codice della funzione HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: return true; default: return false; ) return false; )
E aggiungi il codice eseguibile del metodo alla funzione CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( case eMethLoadPicture: ... break; case eMethTest: if (!lSizeArray || !paParams) restituisce false; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstring_to_p(std::wstring(s1+s2), pvarRetValue ; ;
Compiliamo il componente e riportiamo il codice di configurazione nel form:
variabile DemoComp; Procedura all'avvio del sistema() Connetti il ​​componente esterno("...", "DemoVK", Componente esterno Type.Native); DemoComp = New("AddIn.DemoVK.SomeName"); corsia = DemoComp.Test("Ciao," "Mondo!"); Rapporto(per); FineProcedura
Dopo aver avviato la configurazione, riceveremo il messaggio: “Hello, World!”, che indica che il metodo ha funzionato con successo.

Timer

Compito:
  1. Studia l'implementazione del timer nella demo VK
  2. Modificare il metodo “StartTimer” aggiungendo la possibilità di passare nei parametri l'intervallo di risposta del timer (in millisecondi)
  3. Assicurati che le modifiche apportate funzionino.

In WinAPI è possibile utilizzare il messaggio per lavorare con il tempo WM_TIMER. Questo messaggio verrà inviato al tuo programma all'intervallo di tempo impostato durante la creazione del timer.
Per creare un timer, utilizzare la funzione ImpostaTimer:
UINT SetTimer(HWND hWnd, // descrittore finestra UINT nIDevent, // identificatore timer (numero) UINT nElapse, // ritardo TIMERPROC lpTimerFunc); // puntatore alla funzione
Il sistema operativo invierà un messaggio WM_TIMER nel programma con l'intervallo specificato nell'argomento nTrascorrere(in millisecondi). Nell'ultimo parametro è possibile specificare una funzione che verrà eseguita ogni volta che si attiva il timer. L'intestazione di questa funzione dovrebbe assomigliare a questa (il nome può essere qualsiasi cosa):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Consideriamo l'implementazione di un timer nella demo VC.
Poiché stiamo considerando il processo di sviluppo di un componente esterno per la famiglia di sistemi operativi Windows, non prenderemo in considerazione l'implementazione del timer in altri sistemi operativi. Per il sistema operativo GNU/Linux, in particolare, l'implementazione differirà nella sintassi della funzione ImpostaTimer E TimerProc.
Il codice eseguibile chiama il metodo ImpostaTimer, a cui viene passata la funzione MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
L'ID del timer creato viene inserito in una variabile m_uiTimer in modo che possa essere disabilitato in seguito.
Funzione MyTimerProc come segue:
VOID CALLBACK MyTimerProc(HWND hwnd, // handle della finestra per i messaggi del timer UINT uMsg, // messaggio WM_TIMER UINT idEvent, // identificatore del timer DWORD dwTime // ora del sistema corrente) ( if (!pAsyncEvent) return; wchar_t *who = L "ComponentNative", *what = L"Timer"; wchar_t *wstime = new wchar_t; if (wstime) ( wmemset(wstime, 0, TIME_LEN); ::_ultow(dwTime, wstime, 10); pAsyncEvent->ExternalEvent(who , cosa, wstime); elimina wstime;
L'essenza della funzione è che il metodo viene chiamato Evento esterno, che invia un messaggio al sistema 1C: Enterprise.
Per espandere la funzionalità del metodo StartTimer Facciamo quanto segue:
Modifica del codice del metodo GetNParams quindi è per il metodo eMethStartTimer valore restituito 1:
caso eMethStartTimer: ritorno 1;
Ecco il codice del metodo CallAsProc al modulo:
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;
Ora controlliamo la funzionalità. Per fare ciò, scriveremo il codice nel modulo dell'applicazione gestita della configurazione:
variabile DemoComp; Procedura all'avvio del sistema() Connetti il ​​componente esterno("...", "DemoVK", Componente esterno Type.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); FineProcedura
Dopo aver avviato la configurazione, il programma riceverà messaggi ad intervalli di 2 secondi, che indicano che il timer funziona correttamente.

Interazione con il sistema 1C: Enterprise

Per interagire tra il componente esterno e il sistema 1C: Enterprise, metodi della classe IAddInDefBase, descritti nel file AddInDefBase.h. Elenchiamo quelli più comunemente utilizzati:
Generazione di un messaggio di errore
virtual bool ADDIN_API AddError(wcode breve senza segno, sorgente const WCHAR_T*, descr const WCHAR_T*, scode lungo)
wcode, codice- codici di errore (un elenco dei codici di errore con le descrizioni è disponibile sul disco ITS)
fonte- fonte di errore
descr- descrizione dell'errore
Invio di un messaggio al sistema 1C: Enterprise
virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- fonte del messaggio
wszMessage- Messaggio di testo
wszData- dati trasmessi
L'intercettazione dei messaggi viene effettuata dalla procedura di elaborazione degli eventi esterni
Registrazione di un componente esterno nel sistema 1C: Enterprise
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszNomeProfilo- Nome del componente.
Questi metodi sono sufficienti per la piena interazione tra VK e 1C. Per ricevere dati da un componente esterno dal sistema 1C: Enterprise e viceversa, il componente esterno invia un messaggio speciale, che a sua volta viene intercettato dal sistema 1C e, se necessario, richiama i metodi del componente esterno per ritrasmettere i dati .

tTipo di dati Variant

Quando si scambiano dati tra il componente esterno e il sistema 1C: Enterprise, viene utilizzato il tipo di dati tVariant. È descritto nel file types.h, che può essere trovato sul disco ITS:
struct _tVariant ( _ANONYMOUS_UNION union ( int8_t i8Val; int16_t shortVal; int32_t lVal; int intVal; unsigned int uintVal; int64_t llVal; uint8_t ui8Val; uint16_t ushortVal; uint32_t ulVal; uint64_t ; int32_t errCode; float fltVal ;bVal; wchar_t wchVal; struct tm tmVal; void* pInterfaceVal; __VARIANT_NAME_2/*iface*/; uint32_t strLen ; //conteggio di byte ) __VARIANT_NAME_3/*str*/; NOME_1 ; array dimensionale in pvarVal TYPEVAR vt);
Tipo tVarianteè una struttura che comprende:
  • miscela (unione) destinata direttamente alla memorizzazione dei dati
  • identificatore del tipo di dati
In generale, si lavora con variabili di tipo tVariante avviene secondo il seguente algoritmo:
  1. Determinare il tipo di dati attualmente memorizzati in una variabile
  2. Accedi al campo della miscela corrispondente per accedere direttamente ai dati
Utilizzando il tipo tVariante semplifica in modo significativo l'interazione del sistema 1C: Enterprise e dei componenti esterni

Applicazione

La directory "examples" contiene esempi per l'articolo
esempi/1: avvia il componente demo
esempi/2 - dimostrazione dell'espansione dell'elenco delle proprietà
esempi/3 - dimostrazione dell'espansione dell'elenco dei metodi
Ogni directory contiene un progetto VS 2008 e una configurazione 1C già pronta.