Neue Veröffentlichungen von „1C: Trade Management“: Update ohne Entwicklung. Die betriebliche Rechnungslegung wird reguliert


Dies ist auf einige Besonderheiten der globalen Kontextfunktion ConnectExternalComponent() zurückzuführen.

Programmierer haben häufig Probleme beim Anschluss externer Komponenten (z. B. Treiber für kommerzielle Geräte), wenn Benutzer mit 1C arbeiten und über ein Terminal eine Verbindung zum Server herstellen.

In diesem Fall sehen Benutzer beispielsweise dieses Bild:

Beim Arbeiten von lokalen Computern aus gibt es hingegen keine Probleme beim Anschluss externer Komponenten.

Womit hängt das zusammen? Dies liegt daran, dass Benutzer bei der Arbeit über einen Terminalserver weniger Rechte haben als bei der Arbeit an einem lokalen Computer.

Sie können dies leicht überprüfen, wenn Sie sich mit einem Konto mit Administratorrechten am Terminalserver anmelden.

Der Grund für diesen Unterschied liegt darin, dass 1C keine externe Komponente in der Registrierung registrieren kann, wenn der Benutzer mit normalen Rechten im Terminal arbeitet, weil Ein normaler Benutzer hat keine Schreibberechtigung für den Systemregistrierungszweig HKEY_CLASSES_ROOT.

Veröffentlichungen zum Thema Anschluss externer Komponenten im Terminal bieten vielfältige Lösungsansätze für dieses Problem.

Zum Beispiel diese:

1. Starten Sie 1C zum ersten Mal mit Administratorrechten.

Diese Option funktioniert nicht immer. Warum das so ist, erkläre ich weiter unten.

2. Erteilen Sie normalen Terminalbenutzern die Berechtigung, in den Systemregistrierungszweig zu schreiben HKEY_CLASSES_ROOT.

Nicht ausreichend fortgeschrittene Benutzer sollten dies nicht tun, da es sonst zu Problemen kommen kann.

3. Registrieren Sie VK mithilfe verschiedener Gadgets im Namen eines Benutzers mit vollen Rechten.

Es ist auch nicht gut.

Was ist also der beste Weg, aus dieser Situation herauszukommen?

Ich biete meine Lösung für dieses Problem an. Meiner Meinung nach - einfach und schön.

Während ich dieses Problem untersuchte, stellte ich mir die Frage: Warum versucht 1C überhaupt, VK über einen neuen Pfad zu registrieren? Schließlich ist sie bereits im System registriert.

Es stellte sich heraus, dass in typischen 1C-Konfigurationen (zum Beispiel „Trade Management“) die folgende Syntax für die globale Kontextmethode Connect External Component() verwendet wird:

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

Wie Sie sehen können, ist der Treiber VC über das Layout „ATOLBarcode Scanner Driver“ des Verzeichnisses „Connected Equipment“ verbunden.

Was passiert dann?

1C speichert die Komponente im temporären Ordner des Benutzers, zum Beispiel „C:\Dokumente und Einstellungen\Benutzer\Lokale Einstellungen\Temp\1032\v8_4_12.tmp“

und versucht, es im Registrierungszweig zu registrieren HKEY_CLASSES_ROOT genau auf diesem Weg.

Auf dem Terminal haben normale Benutzer keine Rechte, diesen Registrierungszweig zu ändern, daher stellt die Komponente keine Verbindung zu ihnen her.

Lassen Sie uns nun darüber sprechen, wie Sie aus dieser Situation herauskommen.

Die globale Kontextmethode ConnectExternalComponent() verfügt über mehrere Syntaxoptionen. Das werden wir nutzen.

Also, Schritt für Schritt:

1. Registrieren Sie die externe Komponente mit dem Dienstprogramm regsvr32.exe auf dem Terminalserver im Ordner C:\WINDOWS\SYSTEM32 für ein 32-Bit-Betriebssystem oder im Ordner C:\WINDOWS\SYSWOW64 für ein 64-Bit-Betriebssystem.

2. Verwenden Sie eine von zwei zusätzlichen Syntaxoptionen für die ConnectExternalComponent()-Methode:

Variante 1:

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

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

Option 2:

ProgID = "AddIn.Scaner45";

ConnectExternalComponent(ProgID);

DriverObject = New(ProgID);

Meiner Meinung nach ist Option Nummer 2 vorzuziehen.

Gleichzeitig versucht 1C nicht, den VK über einen neuen Pfad in der Registrierung erneut zu registrieren und somit sind alle Probleme gelöst.

Nun, das ist alles. Viel Glück im Job!

[Sie müssen sich registrieren, um den Link anzuzeigen]

Frage: Externe Komponente Native Api in C++ für Linux (Ubuntu x64) auf 1C 8.3


Ich schreibe an VK, kann aber unter Ubuntu keine Verbindung zu 1c herstellen. Selbst die ausführbare Datei von 1c stellt keine Verbindung her. Also eine Frage dazu:

1) Ich versuche, VK anhand des im Artikel angegebenen VNCOMPS-Beispiels zu verbinden

(Link finden Sie ganz am Ende: „Kopieren“).
Im NativeApi-Projekt gibt es ein Makefile. Mit seiner Hilfe baue ich eine .so-Bibliothek auf Ununtu auf.
Aber wenn „Externe Komponente anschließen“ stürzt 1c ab.
Ebenso, wenn ich mit „build.sh“ (im Stammverzeichnis des Projekts) baue.

Im Makefile selbst ändere ich das Flag von m32 auf m64, weil 1c und das x64-System selbst. (mit Parameter m32 verbindet es sich sowieso nicht)
Hier ist ein Beispiel für den Aufruf von VK aus 1C 8.3:
Verbindung fertig = ConnectExternalComponent("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); Es gibt gerade einen Artikel zu diesem Thema.
Aber meines Erachtens wurden alle diese Punkte bereits im VNCOMPS-Beispiel berücksichtigt und korrigiert.

Aber im Wesentlichen geht es um Kompilierungsparameter. Eine externe MB-32-Bit-Komponente stellt normalerweise eine Verbindung zu einem 32-Bit-1c her, aber ich habe sie auf Ubuntu x64 1c Enterprise83 8.3.5-1486 amd64 bereitgestellt. Und ich möchte sie auf VK treffen.

Hat jemand eine Idee, wie man dieses Problem lösen kann?)
Das VNCOMPS-Beispiel sollte funktionieren, aber die Build-Parameter müssen angepasst werden, oder die Plattform selbst, auf der ich teste, ist falsch.

Antwort: Ich frage mich, ob es möglich ist, eine externe Komponente in Java zu schreiben.

Frage: Externe Komponente (nativ) kann nicht angeschlossen werden


Ich habe ein Beispiel mit ITS kompiliert, für 64- und 32-Bit-Systeme.

Ich verbinde es so:
Verbindungsergebnis = ConnectExternalComponent(KDLLPath, "Comp", ExternalComponentType.Native); Auf einem PC funktioniert die Verbindung, auf dem anderen jedoch nicht. Es gibt einen Unterschied im Betriebssystem. Wo die Verbindung hergestellt wird, gibt es Win7, wo es kein Win10 gibt. Gleichzeitig funktionieren auf dem PC, auf dem meine Komponente nicht funktioniert, Standardkomponenten.

Getestet auf verschiedenen Plattformen (8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).

Wie kann ich verstehen, warum keine Verbindung hergestellt wird?

Antwort: vc_redist vergessen?

Frage: 1C8 und eine externe Komponente vom Typ Native


Guten Tag.
Ich habe eine BP 3.0.50.12-Konfiguration und möchte darin Wägungen der Firma Vesy-Soft mit UniServerAuto implementieren.
Die Entwickler haben die Komponente in Native für Windows 32 und 64 kompiliert und mit der Maifest-Datei archiviert. Für 1C gibt es auch ein Beispiel, wie das Gewicht berechnet werden kann. Darin wird anhand eines Layouts mit Binärdaten dieses Archiv angegeben, so wie ich es verstehe. Im Beispiel ist alles in Ordnung: Die Komponente wird eingebaut, angeschlossen, dann wird die Verbindung hergestellt und das Gewicht abgelesen.
Aber sobald man mit der Übertragung auf 1C beginnt, wird das Gewicht nicht abgelesen. Alles scheint einfach geschrieben zu sein, aber ich verstehe nicht, wo der Rechen ist.
Wer ein bisschen Zeit hat – helft, schaut mit einem Auge rein, vielleicht liegt die Lösung an der Oberfläche, aber ich gehe irgendwo an die falsche Stelle und mache das Falsche. Ich musste noch nie mit nativer Technologie arbeiten ...

Und im Anhang ist mein Bearbeitungstext

Antwort:

Nun, ich habe Neuigkeiten...
Ich begann Schritt für Schritt zu erkennen, an welchem ​​Punkt es anfangen würde zu scheitern. Dazu habe ich eine leere Datenbank erstellt und diese mit dem Befehl verarbeitet. Analog zum Beispiel des Anbieters habe ich das Layout auf eine neue Konfiguration übertragen – beim zweiten Mal klappt es. Diese. Beim ersten Mal nein, aber beim zweiten Mal ja. Daraus entstand die Idee, dass es in unserer Bearbeitung dennoch notwendig wäre, die Verbindung von Bauteil und Objekt nach unterschiedlichen Verfahren zu trennen.
Dann habe ich es mit der Anbindung des Layouts in meine Datenbank übertragen - es funktioniert. Puh, das ist gut.... Aber ich möchte es ohne Änderungen an der Konfiguration vornehmen, also machen wir weiter

Ich versuche, das Layout zur Verarbeitung hinzuzufügen. Seine Größe erhöht sich sofort von 10 KB auf 3 MB und es ist eine deutliche Verlangsamung des Betriebs zu bemerken – es ist nicht geeignet. Ich fange an, mich mit der Verbindung von Komponenten per DLL zu befassen. Diese. im Wesentlichen das Gleiche, wo ich angefangen habe. Aber es gibt ein „ABER“: Bei der Suche nach dem DLL-Namen im Ordner des Benutzers ist mir aufgefallen, dass sich diese DLL dort befindet, wo (soweit ich es verstehe) die in 1C registrierten DLLs zusammengefasst sind:
C:\Benutzer\USER\AppData\Roaming\1C\1cv8\ExtCompT
Dementsprechend ist es nicht notwendig, den vollständigen Pfad zur DLL anzugeben, Sie können einfach ihren Namen eingeben:
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

Ich versuche... es flucht bei der Registrierung, gibt aber das Wiegeergebnis zurück. Es stellt sich heraus, dass die DLL bereits registriert ist und Sie sie nur noch verbinden müssen. Ich entferne es und alles funktioniert.
Etwas zusammenfassen:
1. Bei der Wägeverarbeitung umfasste der AtOpening-Vorgang den Anschluss einer externen Komponente und einen Anschluss an ein Objekt.
2. Pfad zur DLL Ich habe ihn nicht geschrieben, sondern nur seinen Namen angegeben.

Jetzt sitze ich und denke: Wann wurde die DLL in 1C installiert? Zum Zeitpunkt der Softwareinstallation? Kaum ... Wo ist die Entwicklerkonfiguration dieser DLL zum Zeitpunkt des Starts installiert, wenn das Formular geöffnet wird? Ich weiß es nicht, aber es kommt mir nahe... Was denkst du?
Und zweitens: Was muss an einem neuen Ort getan werden, damit alles funktioniert, wenn das gleiche Terminal installiert werden muss? Sollte ich die Software vollständig installieren, die Herstellerkonfiguration ausführen, um den Betrieb zu überprüfen, und sollte dann (theoretisch) meine Verarbeitung funktionieren? Irgendetwas ist irgendwie kompliziert ... Oder sollte ich „Externe Komponente installieren“ einmal in meiner Verarbeitung nach der Installation der Software ausführen?

Ich würde gerne Ihre Meinung zu diesem Thema hören ...

Frage: Externe Komponente.dll


Guten Tag allerseits.
Eine Frage.
Eine DLL-Komponente, die in 1C 7.7 hervorragend funktioniert
1s 8.1 will überhaupt nicht booten...
Ich habe versucht, es in C:\Programme\1cv81\bin\cache1c.dll einzufügen
Ich habe versucht, mich mit regsvr32 „C:\Programme\1cv81\bin\cache1c.dll“ zu registrieren.
Registriert sich ohne Probleme.
Wenn ich darauf zugreifen möchte, erhalte ich eine Fehlermeldung:

Fehler beim Laden der externen Komponente! Cache1c.dll
Prozedur ButtonExecutePress(Button) Versuch, externe Komponente zu laden( „C:\Programme\1cv81\bin\cache1c.dll“); Ausnahmebericht( „Fehler beim Laden der externen Komponente!“+ "cache1c.dll" ); EndAttempt; Versuch // Komponentenobjekt abrufen. // m = New ("cache1c.GTMcmd" ); m = Neues COMObject("cache1c.GTMcmd" ); Ausnahmebericht(); EndAttempt; Ende des Verfahrens

Antwort: Es ist banal bis zur Unmöglichkeit...
Sie müssen zwischen den Anrufen eine Pause einlegen (Millisekunden) ...
Prozedur ButtonExecutePress(Button) Versuch // Ein Komponentenobjekt abrufen. m = Neues COMObject("cache1c.GTMcmd" ); Ausnahmebericht( „Fehler beim Erstellen des externen Komponentenobjekts“); EndAttempt; m.RemoteHost = "192.168.1.101"; m.RemotePort = 6330; m.Connect(); m.Pause(100); ...... usw
Für 1c 7.7 ist dies nicht erforderlich, es stellt sich heraus, dass die Handhabung schneller ist.

Frage: Arbeiten mit einer externen Komponente mit einem 1C-Server...


Guten Tag,

Es gibt eine in C++ geschriebene externe Komponente, deren Aufgabe darin besteht, Informationen aus einer externen Datenbank abzurufen und das Abfrageergebnis in Form einer Wertetabelle in 1C zurückzugeben.
Um eine Wertetabelle zum aktuellen Zeitpunkt zu erstellen, wird die Schnittstelle IDispatch* pBackConnection verwendet, die als Parameter in der Funktion Init() empfangen wird. Als nächstes verwende ich einfach 1C-Funktionen, um eine Wertetabelle zu erstellen, sie zu füllen und sie an den zweiten Parameter in CallAsFunc(...) zurückzugeben.
Die Probleme begannen mit der Umstellung auf 1C Thin Clients. Auf der Serverseite startet die externe Komponente nicht wirklich. Sie können es auf der Clientseite ausführen, aber es sieht alles wie Krücken aus und fällt aus der allgemeinen „Client-Server“-Logik in 1C. Beispielsweise versteht der Kunde nicht, was eine Wertetabelle ist, Probleme mit „globalen“ Variablen, Sitzungen usw.
NativeAPI ist in dieser Hinsicht noch eingeschränkter.
Das Tanzen mit einem Tamburin führte dazu, dass ich eine externe Komponente unter dem 1C-Server starten konnte, ABER die Arbeit geht weiter, bis versucht wird, Invoke auf pBackConnection aufzurufen. Die 64-Bit-Version des 8.2-Servers versucht etwas zu tun, bis es zu einer Zeitüberschreitung kommt, die 32-Bit-Version (VK ist natürlich auch 32-Bit) bricht sofort ab.
Ich gehe davon aus, dass der 1C-Server diese Betriebsart nicht unterstützt.
Dementsprechend stellen sich Fragen: Ist dies vorübergehend oder läuft die 1C-Logik darauf hinaus, dieses Arbeitsprogramm abzubrechen? Wenn es auf diese Weise nicht möglich ist, interne 1C-Strukturen (eine Wertetabelle) zu erstellen, gibt es grundsätzlich eine Beschreibung dessen, was eine Wertetabelle auf Systemebene ist, um zu versuchen, sie in C++ zu erstellen? ausfüllen und dann einfach als Rückgabeparameter in 1C einfügen? Ich möchte zumindest eine Richtung bekommen, in die ich graben soll.

Danke.

Antwort:

Du schreibst das eine und meinst das andere.
In der 1C-Umgebung ist es jetzt nicht unmöglich, Variablen zu deklarieren, die in verschiedenen Sitzungen sichtbar sind, und zuvor gab es diese Möglichkeit nicht. Eine weitere Sitzung ist ein physisch anderer Prozess.
Eine Sitzung ist eine Sitzung, die eine Verbindung zu einer Datenbank herstellt, d. h. Benutzersitzung. Oder bringen Sie etwas Eigenes in dieses Konzept ein?

Innerhalb einer Sitzung war es möglich und ist es jetzt auch möglich, Variablen im Sitzungsmodul zu deklarieren, die innerhalb der Sitzung von verschiedenen Orten aus leben und sichtbar sind ... tatsächlich gibt es vier davon.
- Sitzungsmodul;
- Regelmäßiges Bewerbungsmodul;
- Verwaltetes Anwendungsmodul;
- Externes Verbindungsmodul.

Nun, natürlich müssen Sie sich den Kontext merken. Der Serverkontext ist auf der Clientseite nicht direkt zugänglich und umgekehrt.

Tatsächlich sieht die 1C-Architektur vor, dass der Datenaustausch wie folgt abläuft:
- mittels Parametern/Rückgaben von Prozeduren/Funktionen;
- mittels der sogenannten Sitzungsparameter (können keine Objekte sein, sind aber tatsächlich in der Palette sichtbar).

Eine Tabelle im Formular ... ist sie mit einer Objekttabelle (z. B. Verarbeitung) verbunden? oder nicht. Wenn ja, dann ist es auf dem Server (&OnServer) verfügbar und kann dort bearbeitet werden....

Und doch ist die Wertetabelle auf der Clientseite nicht im UV verfügbar. Nun, das hat 1C entschieden.

Nun ja! Es funktioniert mit Excel, es funktioniert mit FSO und vielen anderen Dingen, aber hier funktioniert es nicht. Erkennen Sie den Fehler und analysieren Sie ihn....

Versuchen
...
eure Aktionen
...
Ausnahme
str = ErrorDescription();
EndAttempt;

Bei modernen Hardware-Fähigkeiten ist dies überhaupt kein Argument.

Rein Ihre persönliche Meinung. Hat nichts mit der Realität zu tun. Auf keinen Fall. Ich wiederhole es noch einmal: 1C funktioniert hervorragend mit COM. Sowohl mit In-Proc als auch Out-Proc.

Bitte geben Sie den Code an, den Sie zum Herunterladen verwenden, und kontaktieren Sie VK.

Übrigens, VK... ist es in Ihrem Fall COM oder Native API?
Wenn COM, dann registrieren Sie es als ... über regsvr32 ... wie „lösen“ Sie dann das Problem der Bittiefe?

Frage: Installation einer externen Komponente


Bitte erklären Sie mir, wie eine externe Komponente installiert wird. Beim Ausführen des folgenden Codes wird ein Fehler ausgegeben. Suchen Sie im Layout nach NameDecl.dll

Der Versuch, SetExternalComponent("GeneralLayout.Layout"); Ausnahme EndTry ;
Fehler: Die Installation der externen Komponente ist fehlgeschlagen!

Antwort: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native) gibt FALSE zurück.
New("AddIn.NameDecl.CNameDecl", Undefiniert) = (()): Typ undefiniert (AddIn.NameDecl.NameDecl)

Frage: Die native DLL stellt keine Verbindung zu 1c 8.1 her (fptrwin32_fz54_9_11_0_5549.dll)


Guten Tag.
1C hat die DLL für Online-Registrierkassen auf FFD 1.05 aktualisiert (in der Wartungsverarbeitung fptrwin32_fz54_9_11_0_5549.dll enthalten).
Ich habe ein altes 1C 8.1. Im Gegensatz zu 8.2 wird die Arbeit mit externen Geräten nicht wie 8.2 unterstützt. Sie müssen also zuerst die DLL in Windows registrieren und sie dann nur mit 1C verbinden.

ProgID = "AddIn.IntegrationComponent.ATOL_KKT_1C83_V9"; LoadExternalComponent("C:\fptrwin32_fz54_9_11_0_5549.dll"); ConnectExternalComponent(progID); Treiber = Neu(ProgID);

Allerdings wurde die alte Verarbeitung in com-„Technologie“ geschrieben und die neue ist nativ. Dementsprechend kommt es bei der Registrierung von regsvr32 zu einem Fehler:
Das Modul wird geladen, aber der DllRegisterServer-Einstiegspunkt wird nicht gefunden. Außerdem wird empfohlen, zu überprüfen, ob es sich bei dieser Datei um die richtige DLL- oder OCX-Datei handelt.
Hat jemand eine ähnliche Situation erlebt und wie sind Sie da rausgekommen? Ich verstehe, dass 7.7 ein ähnliches Problem haben wird.
Code 8.2:

Layout = GetLayout("IntegrationComponent"); Adresse = PlaceInTemporaryStorage(Layout); ConnectExternalComponent(Address, "IntegrationComponent", ExternalComponentType.Native); Driver = New("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

1C 8.2:
ConnectExternalComponent(<Местоположение>, <Имя>, <Тип>)
1C 8.1:
ConnectExternalComponent(<Идентификатор объекта>)
Optionen:
<Идентификатор объекта>(erforderlich)
Typ: Zeichenfolge. ProgID (Programmatic Identifier) ​​​​des externen Komponentenobjekts. Muss mit den Informationen in der Registrierungsdatenbank des Systems (Registry) übereinstimmen.
Beschreibung:
Verbindet externe Komponentenobjekte mit 1C:Enterprise.
Nicht verfügbar auf dem 1C:Enterprise-Server. Wird im externen Verbindungsmodul nicht verwendet.
Notiz:
Externe Komponenten sind mit 1C:Enterprise 7.7-Komponenten kompatibel.
Beispiel:
Versuchen
ConnectExternalComponent("AddinObject.Scanner");
Report("Die Komponente für den Barcodescanner wurde geladen");
Ausnahme
Report("Die Komponente für den Barcodescanner ist nicht geladen");
EndAttempt

Gibt es eine Möglichkeit, diese DLL mit 8.1 zu verbinden oder nicht?

Danke!

Antwort:

Auch ich bin kürzlich auf dieses Problem gestoßen. Eine Umstellung auf eine spätere Version von 1c war nicht möglich, weil... dll, mit der diese Konfiguration funktioniert, funktionierte einfach nicht mehr und 1c stürzte mit einem Fehler ab.
Ich habe das Problem wie folgt gelöst:
Ich habe eine leere 8.3-Datenbank erstellt, in der ich die Initialisierung der Komponente durchgeführt habe und habe dann ab 8.1 über eine COM-Verbindung auf die zuvor erstellte Datenbank zugegriffen und dort die Komponente initialisiert. Dann habe ich bereits in 8.1 die Methoden dieser Komponente aufgerufen.
Natürlich ist das eine Krücke, aber ich habe noch keinen anderen Ausweg gefunden(

Codebeispiel 8.3:
Export variabler Treiber;
Funktion ConnectionComponentsKKT() Exportieren
Versuchen

Layout = GetLayout("IntegrationComponent");
Adresse = PlaceInTemporaryStorage(Layout);
ConnectExternalComponent(Address, "IntegrationComponent", ExternalComponentType.Native);
Driver = New("AddIn.IntegrationComponent.SMDrvFR1C20");
Ergebnis = Wahr;​

Ausnahme

Ergebnis = Falsch;​

EndAttempt;
Ergebnis zurückgeben
EndFunction

Codebeispiel 8.1

Funktion CreateDriverObject(Driver) Export

Ergebnis = Wahr;

Versuchen

ConnectionString="File="""Pfad zur Datenbank""";
ComObject = New COMObject("V83.ComConnector");
Connect = ComObject.Connect(ConnectionString);

Processing = Connect.Processing.ConnectExternalComponent.Create();
Verbindungsergebnis = Processing.ConnectionCCPComponents();
Wenn die Verbindung zustande kommt, dann
Driver = Processing.Driver;
EndIf;​

Ausnahme
Wer dies schon einmal gemacht hat oder auf ähnliche Urteile gestoßen ist, erklärt das Prinzip selbst anhand eines einfachen Beispiels. Beim Anschluss externer Komponenten scheint alles klar zu sein.

// Beispiel für das Ausfüllen der Wertetabelle TK.Clear(); Anfrage = Neue Anfrage; Query.Text = "SELECT | Nomenklatur.Link WIE Nomenklatur |VON | Directory.Nomenclature AS Nomenclature"; Request Result = Request.Execute(); Selection = Request Result.Select(); While Selection.Next() Cycle Page = TK.Add(); Fill inPropertyValues(Page, Selection); EndCycle;
Könnten Sie anhand dieses Beispiels erklären, welcher Teil des Codes normalerweise entfernt wird? Es wäre logisch, den Teil mit der Anfrage zu entfernen, aber wie können wir dann von der externen Komponente aus unter Umgehung der Plattform auf die Datenbank zugreifen? Es hat keinen Sinn, den Text herauszubringen. Oder nehmen Sie die eigentliche Formation des tabellarischen Teils heraus. Teilen Sie Ihre Erfahrungen mit jedem, der dies erlebt hat.

Antwort: Und dass das Wort „Inkompatibel“ immer das Wort „Schlecht“ bedeutet? Ja, es kommt mir so vor, als würde ich meinen Stil „1C: Die schlechteste Programmierung auf dieser Skript-Engine, die es in der Natur gibt (übersetzt in die Literatursprache)“ nennen! und dann wird es wahrscheinlich Leute geben, die sich dieses Biest ansehen wollen. Und es sieht aus wie ein Klassiker: „Ich habe Pasternak nicht gelesen, aber ich bin völlig anderer Meinung als er!“

Frage: Anschließen einer externen Komponente in 1s 8.3.6 und Win8


Sie müssen die externe Komponente vk_rs232.dll mit der selbstgeschriebenen Konfiguration verbinden. Es scheint über regsvr32.exe registriert worden zu sein. „Es scheint“, weil ich die Meldung erhalten habe, dass „die Komponente registriert ist, aber mit der Firewall etwas nicht stimmt.“ Basierend auf der ersten Hälfte der Nachricht schreibe ich den Code in 1C
AfterConnecting = Neue Warnungsbeschreibung("AfterConnectingVK", ThisForm); StartInstallingExternalComponents(,"C:\Controller\vk_rs232.dll"); StartConnectingExternalComponents(AfterConnecting,"C:\Controller\vk_rs232.dll","DLL_Scales");
und ich bekomme die Fehlermeldung, dass
„Die Installation einer externen Komponente ist fehlgeschlagen! Möglicherweise fehlt eine Komponente für die von Ihnen verwendete Clientanwendung!“

Und jetzt verstehe ich nicht:
1. Eventuell ist die Komponente nicht in der Registry registriert – wie kann ich das dort überprüfen?
2. Möglicherweise funktioniert seine „Version“ nicht unter Win8, obwohl ich eine 32-Bit-Version habe.
3. Vielleicht ist 1C selbst zu neu, d.h. Dementsprechend kann es mit dieser DLL nicht funktionieren?
4. Nun, es ist trivial – ich schreibe etwas Falsches.

Antwort: Und das alles führte mich zum nächsten Problem. VneshComp ist installiert, jetzt müssen Sie es verbinden. Und hier gibt es beide Möglichkeiten
ConnectExternalComponent("C:\Controller\vk_rs232.dll","Libra")
ConnectExternalComponent("GeneralLayout.Layout","Libra")

Syntaxoption: Nach Name und Ort

Syntax:

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

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

Typ: Zeichenfolge.
Der Standort der externen Komponente.
Der Standort kann verwendet werden:
Pfad zur externen Komponentendatei im Dateisystem (nicht verfügbar auf dem Webclient), kein ZIP-Archiv;
der vollständig qualifizierte Name des Layouts, in dem die Binärdaten oder das ZIP-Archiv gespeichert sind;
Die URL zur externen Komponente, als Binärdaten oder ZIP-Archiv, in einem Format ähnlich wie GetNavigationLink.
<Имя>(erforderlich)

Typ: Zeichenfolge.
Der symbolische Name der externen Komponente, die angeschlossen werden soll.
Der Name muss den Namenskonventionen der integrierten Sprache entsprechen.
<Тип>(Optional)

Typ: ExternalComponentType.
Typ der anzuschließenden externen Komponente.
Wird nicht verwendet, wenn die Komponente in einem ZIP-Archiv verpackt ist.
Beschreibung der Methodenoption:

Verbindet Komponenten, die mit Native- und COM-Technologie erstellt wurden.
Die Komponente kann in der Infobase oder im Konfigurationslayout als Binärdaten oder in einem ZIP-Archiv gespeichert werden.
Für die Startmodi „Thin Client“ und „Web Client“ muss die Komponente zunächst mit der Methode „Externe Komponente installieren“ installiert werden.
Syntaxoption: Nach ID

Syntax:

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

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

Typ: Zeichenfolge.
Identifikator des externen Komponentenobjekts in Form von ProgID (Programmatic Identifier) ​​der MS Windows-Registrierung (zum Beispiel: „AddIn.Scanner“).
Muss mit den Informationen in der Registrierungsdatenbank des Systems (Registry) übereinstimmen.
Beschreibung der Methodenoption:

Die Komponente muss mithilfe der COM-Technologie implementiert und in der MS Windows-Registrierung registriert sein.
Diese Komponenten sind mit 1C:Enterprise 7.7-Komponenten kompatibel.
Aufmerksamkeit! Die Methodenoption funktioniert nicht auf dem Server und in der externen Verbindung.
Rückgabewert:

Typ: Boolesch.
Stimmt – die Verbindung war erfolgreich.
Beschreibung:

Verbindet eine externe Komponente mit 1C:Enterprise.
Externe Komponenten können in Infobase- oder Konfigurationslayouts als ZIP-Archiv oder als Binärdaten oder in einer Dateisystemdatei gespeichert werden.
Beim Arbeiten an einem Thin Client und einem Web Client muss die Komponente vorinstalliert sein.

Verfügbarkeit:

Thin Client, Webclient, Server, externe Verbindung.
Notiz:

Externe Komponenten können mithilfe der Native API- oder COM-Technologie implementiert werden. Mit COM-Technologie hergestellte Komponenten sind mit 1C:Enterprise 7.7-Komponenten kompatibel.
Der Webclient kann nur mit Komponenten in der Infobase arbeiten, die in einem Archiv verpackt sind.
Der Thin Client kann mit Komponenten in der Infobase, gepackt in einem Archiv, und Komponenten im Dateisystem arbeiten.
Der Thick Client beherrscht alle Komponentenspeichermöglichkeiten. Wenn in diesem Fall eine Komponente mit der Methode „Externe Komponente installieren“ installiert wird, wird die installierte Komponente verwendet. Wenn sie nicht installiert ist, wird die Komponente zum Zeitpunkt der Verbindung empfangen.
Der Server kann mit allen Komponenten arbeiten. Die Komponente wird pro Serversitzung zwischengespeichert.
Beispiel:

Wenn ConnectExternalComponent("AddinObject.Scanner") dann
Report("Komponente für Barcode-Scanner geladen");
Ansonsten
Report("Die Komponente für den Barcodescanner ist nicht geladen");
endIf;

  • Lernprogramm

Einführung

Dieser Artikel gibt einen Einblick in die Funktionsweise externer Komponenten im 1C: Enterprise-System.
Der Prozess der Entwicklung einer externen Komponente für das 1C: Enterprise-System Version 8.2, das unter Windows mit einem Dateibetriebsmodus läuft, wird gezeigt. Diese Option wird in den meisten Lösungen für kleine Unternehmen verwendet. VK wird in der Programmiersprache C++ implementiert.

Externe Komponenten „1C: Enterprise“

„1C: Enterprise“ ist ein erweiterbares System. Zur Erweiterung der Funktionalität des Systems werden externe Komponenten (EC) eingesetzt. Aus Entwicklersicht ist ein VC ein externes Objekt, das über Eigenschaften und Methoden verfügt und auch Ereignisse zur Verarbeitung durch das 1C: Enterprise-System generieren kann.
Mithilfe externer Komponenten können eine Klasse von Problemen gelöst werden, die in der in 1C: Enterprise integrierten Programmiersprache nur schwer oder gar nicht zu implementieren sind. Diese Klasse umfasst insbesondere Aufgaben, die eine Interaktion auf niedriger Ebene mit dem Betriebssystem erfordern, beispielsweise um mit bestimmten Geräten zu arbeiten.
Das 1C: Enterprise-System verwendet zwei Technologien zur Erstellung externer Komponenten:
  • Verwendung der nativen API
  • unter Verwendung der COM-Technologie
Angesichts der gegebenen Einschränkungen ist der Unterschied zwischen den beiden oben genannten Technologien unbedeutend, daher werden wir die Entwicklung von Videospielen unter Verwendung der Native API in Betracht ziehen. Bei Bedarf können die umgesetzten Entwicklungen auf die Entwicklung von Computersoftware unter Verwendung der COM-Technologie angewendet werden und mit geringfügigen Modifikationen auch für den Einsatz im 1C: Enterprise-System mit anderen Betriebsoptionen als dem Dateibetriebsmodus angewendet werden.
VK-Struktur
Die externe Komponente des 1C: Enterprise-Systems wird in Form einer DLL-Bibliothek dargestellt. Der Bibliothekscode beschreibt die Nachkommenklasse IComponentBase. Die erstellte Klasse muss Methoden definieren, die für die Implementierung der Funktionen der externen Komponente verantwortlich sind. Die überschriebenen Methoden werden im Folgenden im Rahmen der Präsentation des Materials ausführlicher beschrieben.

Starten einer Demo-VK

Aufgabe:
  1. Stellen Sie eine externe Komponente zusammen, die mit einem ITS-Abonnement geliefert wird und die Hauptfunktionen des externen Komponentenmechanismus in 1C demonstrieren soll
  2. Verbinden Sie die Demokomponente mit der 1C-Konfiguration
  3. Stellen Sie sicher, dass die deklarierten Funktionen ordnungsgemäß funktionieren
Zusammenstellung
Der Demo-VK befindet sich auf der ITS-Abonnementdiskette im Verzeichnis „/VNCOMP82/example/NativeAPI“.
Zum Erstellen der Demo-VC verwenden wir Microsoft Visual Studio 2008. Andere Versionen dieses Produkts unterstützen das verwendete Visual Studio-Projektformat nicht.


Öffnen Sie das AddInNative-Projekt. In den Projekteinstellungen fügen wir das Verzeichnis mit den Header-Dateien hinzu, die zum Erstellen des Projekts erforderlich sind. Standardmäßig befinden sie sich auf der ITS-Platte im Verzeichnis /VNCOMP82/include.
Das Ergebnis des Builds ist die Datei /bind/AddInNative.dll. Dies ist die kompilierte Bibliothek für die Verbindung zur 1C-Konfiguration.
Verbinden von VK mit der 1C-Konfiguration
Lassen Sie uns eine leere 1C-Konfiguration erstellen.
Unten finden Sie den Code für das verwaltete Anwendungsmodul.
Variable DemoComp; Vorgehensweise beim Systemstart() Externe Komponente verbinden("...\bind\AddInNative.dll", "DemoVK", External Component Type.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); Ende des Verfahrens
Wenn beim Starten der 1C-Konfiguration kein Fehler gemeldet wurde, wurde die VK erfolgreich verbunden.
Als Ergebnis der Ausführung des obigen Codes erscheint ein Objekt in der globalen Sichtbarkeit der Konfiguration DemoComp, das über Eigenschaften und Methoden verfügt, die im Code der externen Komponente definiert sind.
Demonstration der integrierten Funktionalität
Lassen Sie uns die Funktionalität des Demo-VK überprüfen. Versuchen wir dazu, einige Eigenschaften festzulegen und zu lesen, einige VK-Methoden aufzurufen und auch die VK-Nachricht zu empfangen und zu verarbeiten.
Die auf der ITS-Diskette bereitgestellte Dokumentation gibt die folgende Funktionalität des Demo-VC an:
  1. Verwalten des Komponentenobjektstatus
    Methoden: Anmachen, Ausschalten
    Eigenschaften: Inbegriffen
  2. Timer-Steuerung
    Jede Sekunde sendet die Komponente eine Nachricht mit Parametern an das 1C: Enterprise-System Komponente, Timer und eine Systemtaktzählerleitung.
    Methoden: StartTimer, Timer stoppen
    Eigenschaften: Es gibt einen Timer
  3. Methode ShowInStatusLine, das in der Statuszeile den Text anzeigt, der als Parameter an die Methode übergeben wurde
  4. Methode Bild hochladen. Lädt ein Bild aus der angegebenen Datei und überträgt es in Form von Binärdaten an das 1C: Enterprise-System.
Stellen wir sicher, dass diese Funktionen funktionieren. Führen Sie dazu den folgenden Code aus:
Variable DemoComp; Vorgehensweise beim Systemstart() ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Report(DemoComp.Enabled); DemoComp.Enable(); Report(DemoComp.Enabled); DemoComp.StartTimer(); Ende des Verfahrens Verfahren Externe Ereignisverarbeitung (Quelle, Ereignis, Daten) Bericht (Quelle + " " + Ereignis + " " + Daten); Ende des Verfahrens
Das Ergebnis der Ausführung der Konfiguration wird im Bild angezeigt


Im Bereich „Nachrichten“ werden die Ergebnisse von Methodenaufrufen angezeigt DemoComp.Disable() Und Demo.Comp.Enable(). Nachfolgende Zeilen im selben Panel enthalten die Ergebnisse der Verarbeitung von Nachrichten, die von VK empfangen wurden – Quelle, Ereignis Und Daten jeweils.

Benutzerdefinierter Name der externen Komponente

Aufgabe: Ändern Sie den Namen der externen Komponente in einen beliebigen Namen.
Im vorherigen Abschnitt wurde der Bezeichner verwendet AddInNativeExtension, dessen Bedeutung nicht erklärt wurde. In diesem Fall AddInNativeExtension- Dies ist der Name der Erweiterung.
Der VK-Code definiert eine Methode RegisterExtensionAs, Rückgabe des Namens an das 1C: Enterprise-System, was für die spätere Registrierung des VK im System erforderlich ist. Es wird empfohlen, einen Bezeichner anzugeben, der in gewissem Maße das Wesen der externen Komponente verrät.
Hier ist der vollständige Code der Methode RegisterExtensionAs mit geändertem Erweiterungsnamen:
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;
Im angegebenen Beispiel wird der VK-Name in geändert IrgendeinName. Dann müssen Sie beim Verbinden von VK einen neuen Namen angeben:
DemoComp = New("AddIn.DemoVK.SomeName");

Erweiterung der Liste der VK-Eigenschaften

Aufgabe:
  1. Studieren Sie die Implementierung von VK-Eigenschaften
  2. Fügen Sie eine Lese-/Schreibeigenschaft vom Typ „String“ hinzu
  3. Fügen Sie eine Zeichenfolgeneigenschaft mit Lese-/Schreibzugriff hinzu, die den Datentyp des letzten Eigenschaftssatzes speichert. Beim Festlegen des Eigenschaftswerts wird keine Aktion ausgeführt

Um die Eigenschaften der zu erstellenden Komponente zu bestimmen, muss der Entwickler die folgenden Methoden im Code der AddInNative.cpp-Bibliothek implementieren:
GetNProps
Gibt die Anzahl der Eigenschaften dieser Erweiterung zurück, 0, wenn keine Eigenschaften vorhanden sind
FindProp
Gibt die Seriennummer der Eigenschaft zurück, deren Name in den Parametern übergeben wird
GetPropName
Gibt den Eigenschaftsnamen anhand seiner Seriennummer und der übergebenen Sprachkennung zurück
GetPropVal
Gibt den Wert der Eigenschaft mit der angegebenen Ordnungszahl zurück
SetPropVal
Legt den Wert der Eigenschaft mit der angegebenen Ordnungszahl fest
IsPropReadable
Gibt das Lesbarkeitsflag der Eigenschaft mit der angegebenen Sequenznummer zurück
IsPropWritable
Gibt das Beschreibbarkeitsflag der Eigenschaft mit der angegebenen Sequenznummer zurück


Betrachten wir die Implementierung der oben genannten Klassenmethoden CAddInNative.
In der Demo-VC sind 2 Eigenschaften definiert: Inbegriffen Und Es gibt einen Timer (Aktiviert Und IsTimerPresent).
Im globalen Bereich des Bibliothekscodes sind zwei Arrays definiert:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Enabled", L"There is a Timer");
die russische und englische Eigenschaftsnamen speichern. In der Header-Datei AddInNative.h Die Aufzählung ist definiert:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Immer zuletzt );
ePropIsEnabled Und ePropIsTimerPresent, jeweils mit den Werten 0 und 1, werden verwendet, um die Seriennummern von Eigenschaften durch aussagekräftige Bezeichner zu ersetzen. ePropLast, das den Wert 2 hat, wird verwendet, um die Anzahl der Eigenschaften zu ermitteln (mithilfe der GetNProps-Methode). Diese Namen werden nur innerhalb des Komponentencodes verwendet und sind von außen nicht verfügbar.
Die Methoden FindProp und GetPropName führen Array-Suchen durch g_PropNames Und g_PropNamesRu.
Um die Werte der Felder im Bibliotheksmodul zu speichern, verfügt die CAddInNative-Klasse über Eigenschaften, die den Wert der Komponenteneigenschaften speichern. Methoden GetPropVal Und SetPropVal zurückgeben und den Wert dieser Eigenschaften entsprechend festlegen.
Methoden IsPropReadable Und IsPropWritable und zurück WAHR oder FALSCH, abhängig von der übergebenen Ordnungszahl der Eigenschaft entsprechend der Anwendungslogik.
Um eine benutzerdefinierte Eigenschaft hinzuzufügen, müssen Sie Folgendes tun:

  1. Fügen Sie den Namen der Eigenschaft hinzu, die zu Arrays hinzugefügt wird g_PropNames Und g_PropNamesRu(Datei AddInNative.cpp)
  2. Auflisten Requisiten(Datei AddInNative.h) Vor ePropLast Fügen Sie einen Namen hinzu, der die hinzugefügte Eigenschaft eindeutig identifiziert
  3. Organisieren Sie den Speicher zum Speichern von Eigenschaftswerten (erstellen Sie Modulkomponentenfelder, in denen die entsprechenden Werte gespeichert werden).
  4. Nehmen Sie Änderungen an Methoden vor GetPropVal Und SetPropVal um mit dem im vorherigen Schritt zugewiesenen Speicher zu interagieren
  5. Nehmen Sie entsprechend der Anwendungslogik Änderungen an den Methoden vor IsPropReadable Und IsPropWritable
Die Punkte 1, 2, 5 bedürfen keiner Erläuterung. Einzelheiten zur Umsetzung dieser Schritte finden Sie im Anhang des Artikels.
Geben wir den Testeigenschaften Namen Prüfen Und Typprüfung jeweils. Dann haben wir als Ergebnis von Schritt 1:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L „Aktiviert“, L „Es gibt einen Timer“, L „Test“, L „Typprüfung“);
Überweisen Requisiten wird aussehen wie:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Immer zuletzt );
Um den Code deutlich zu vereinfachen, verwenden wir STL C++. Insbesondere für die Arbeit mit Saiten WCHAR, lasst uns die Bibliothek verbinden wstring.
Um einen Methodenwert zu speichern Prüfen, definieren wir in der Klasse CAddInNative im Rahmen eines privaten Bereichs:
Zeichenfolge test1;
Um String-Parameter zwischen 1C: Enterprise und externen Komponenten zu übertragen, wird der 1C: Enterprise-Speichermanager verwendet. Werfen wir einen genaueren Blick auf seine Arbeit. Die Funktionen werden zum Zuweisen bzw. Freigeben von Speicher verwendet AllocMemory Und Freier Speicher in der Datei definiert ImemoryManager.h. Wenn es notwendig ist, einen String-Parameter an das 1C:Enterprise-System zu übergeben, muss die externe Komponente durch Aufrufen der Funktion Speicher dafür zuweisen AllocMemory. Sein Prototyp sieht so aus:
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
Wo pSpeicher- die Adresse des Zeigers, in den die Adresse des zugewiesenen Speicherbereichs eingefügt wird,
ulCountByte- Größe des zugewiesenen Speicherbereichs.
Ein Beispiel für die Speicherzuweisung für einen String:
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);
Um die Arbeit mit String-Datentypen zu erleichtern, beschreiben wir die Funktion wstring_to_p. Als Parameter erhält es einen wstring-String. Das Ergebnis der Funktion ist eine gefüllte Struktur tVariante. Funktionscode:
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)); true zurückgeben)
Dann der entsprechende case-Abschnitt der switch-Anweisung der Methode GetPropVal wird die Form annehmen:
case ePropTest1: wstring_to_p(test1, pvarPropVal); brechen;
Methode SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) return false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); brechen;
Um die zweite Eigenschaft zu implementieren, definieren wir ein Klassenfeld CaddInNative
uint8_t last_type;
in dem wir den Typ des zuletzt übertragenen Werts speichern. Fügen Sie dazu den Befehl zur CaddInNative::SetPropVal-Methode hinzu:
last_type = TV_VT(varPropVal);
Wenn wir nun anfordern, den Wert der zweiten Eigenschaft zu lesen, geben wir den Wert zurück last_type, was die vorgesehene Aufgabe erfordert.
Lassen Sie uns die Funktionalität der vorgenommenen Änderungen überprüfen.
Stellen wir uns dazu das Erscheinungsbild der 1C-Konfiguration wie folgt vor:
Variable DemoComp; Vorgehensweise beim Systemstart() Connect External Component("...", "DemoVK", External Component 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)); Report(String(DemoComp.TypeCheck)); Ende des Verfahrens
Als Ergebnis des Starts erhalten wir eine Reihe von Nachrichten:
3
Wasja
Peter
22

Die zweite und dritte Meldung sind das Ergebnis des Lesens der im vorherigen Schritt festgelegten Eigenschaft. Die erste und zweite Nachricht enthalten den Typcode des letzten Eigenschaftssatzes. 3 entspricht einem ganzzahligen Wert, 22 einem String-Wert. Die Entsprechung der Typen und ihrer Codes wird in der Datei festgelegt Typen.h, die sich auf der ITS-Platte befindet.

Erweiterung der Methodenliste

Aufgabe:
  1. Erweitern Sie die Funktionalität der externen Komponente um die folgende Funktionalität:
  2. Entdecken Sie Möglichkeiten zur Implementierung externer Komponentenmethoden
  3. Fügen Sie eine Funktionsmethode hinzu Funktion1, das zwei Zeichenfolgen („Parameter1“ und „Parameter2“) als Parameter akzeptiert. Das Ergebnis ist eine Zeichenfolge wie: „Überprüfen. Parameter1, Parameter2"
  4. Stellen Sie sicher, dass die von Ihnen vorgenommenen Änderungen funktionieren.

Um die Methoden der zu erstellenden Komponente zu definieren, muss der Entwickler die folgenden Methoden im AddInNative-Bibliothekscode implementieren:
GetNMethods, FindMethod, GetMethodName
Um die entsprechende Anzahl von Methoden zu erhalten, suchen Sie nach der Nummer und dem Namen der Methode. Ähnlich den entsprechenden Methoden für Eigenschaften
GetNParams
Gibt die Anzahl der Methodenparameter mit der angegebenen Sequenznummer zurück; Wenn eine Methode mit dieser Nummer fehlt oder keine Parameter hat, wird 0 zurückgegeben
GetParamDefValue
Gibt den Standardwert des angegebenen Parameters der angegebenen Methode zurück
HasRetVal
Gibt das Flag zurück, ob die Methode mit dem angegebenen ordinalen Rückgabewert einen Rückgabewert hat: true für Methoden mit einem Rückgabewert und FALSCH sonst
CallAsProc
FALSCH, tritt ein Laufzeitfehler auf und die Ausführung des 1C: Enterprise-Moduls wird abgebrochen. Speicher für das Parameterarray wird von 1C: Enterprise zugewiesen und freigegeben.
CallAsFunc
Führt die Methode mit der angegebenen Sequenznummer aus. Wenn die Methode zurückkehrt FALSCH, tritt ein Laufzeitfehler auf und die Ausführung des 1C: Enterprise-Moduls wird abgebrochen. Speicher für das Parameterarray wird von 1C: Enterprise zugewiesen. Wenn der Rückgabewert ein String oder ein binärer Datentyp ist, reserviert die Komponente Speicher mit der Funktion AllocMemory Speichermanager, schreibt dort Daten und speichert diese Adresse im entsprechenden Feld der Struktur. 1C: Das Unternehmen gibt diesen Speicher per Anruf frei Freier Speicher.
Eine vollständige Beschreibung der Methoden, einschließlich einer Liste der Parameter, ist in der Dokumentation auf der ITS-Diskette ausführlich beschrieben.
Betrachten wir die Implementierung der oben beschriebenen Methoden.
Im Komponentencode sind zwei Arrays definiert:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
und Aufzählung:
enum-Methoden ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // Immer zuletzt );
Sie werden in Funktionen verwendet GetNMethods, FindMethod Und GetMethodName, analog zur Beschreibung von Eigenschaften.
Methoden GetNParams, GetParamDefValue, HasRetVal Der Implementierungsschalter gibt abhängig von den übergebenen Parametern und der Anwendungslogik den erforderlichen Wert zurück. Methode HasRetVal In seinem Code gibt es eine Liste der einzigen Methoden, die ein Ergebnis zurückgeben können. Für sie kehrt er zurück WAHR. Für alle Stahlmethodenrückgaben FALSCH.
Methoden CallAsProc Und CallAsFunc enthalten direkt ausführbaren Code der Methode.
Um eine Methode hinzuzufügen, die nur als Funktion aufgerufen werden kann, müssen Sie folgende Änderungen am Quellcode der externen Komponente vornehmen:
  1. Methodennamen zu Arrays hinzufügen g_MethodNames Und g_MethodNamesRu(Datei AddInNative.cpp)
  2. Fügen Sie der Methodenaufzählung (Datei) einen aussagekräftigen Methodenbezeichner hinzu AddInNative.h)
  3. Nehmen Sie Änderungen am Funktionscode vor GetNParams nach Programmlogik
  4. Nehmen Sie bei Bedarf Änderungen am Methodencode vor GetParamDefValue, wenn Sie die Standardwerte der Methodenparameter verwenden möchten.
  5. Nehmen Sie Änderungen an der Funktion vor HasRetVal
  6. Nehmen Sie Änderungen an der Logik von Funktionen vor CallAsProc oder CallAsFunc und platziert dort den direkt ausführbaren Code der Methode
Lassen Sie uns die Arrays präsentieren g_MethodNames Und g_MethodNamesRu, sowie Auflistung Methoden zum Formular:
static wchar_t *g_MethodNames = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); static wchar_t *g_MethodNamesRu = (L"Enable", L"Disable", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test");

Enum-Methoden ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Immer zuletzt );
Lassen Sie uns die Funktion bearbeiten GetNProps damit die Anzahl der Parameter der Methode „Test“ zurückgegeben wird:
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; )
Nehmen wir Änderungen an der Funktion vor:
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 : Fall eMethStopTimer: Fall eMethTest : // Es gibt standardmäßig keine Parameterwerte break default: return false;
Dank der hinzugefügten Zeile
Fall eMethTest:
Wenn ein oder mehrere Argumente fehlen, haben die entsprechenden Parameter einen leeren Wert ( VTYPE_EMPTY). Wenn Sie einen Standardwert für einen Parameter benötigen, sollten Sie ihn im Abschnitt festlegen eMethTest Funktionswechselanweisung CAddInNative::GetParamDefValue.
Da die Testmethode einen Wert zurückgeben kann, müssen Sie Änderungen am Funktionscode vornehmen HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( case eMethLoadPicture: case eMethTest: true zurückgeben; Standard: false zurückgeben; ) false zurückgeben; )
Und fügen Sie der Funktion den ausführbaren Code der Methode hinzu 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) return false; s2 = (paParams+1) -> pwstring_to_p(std::wstring(s1+s2), pvarRetValue); ;
Lassen Sie uns die Komponente kompilieren und den Konfigurationscode in das Formular bringen:
Variable DemoComp; Vorgehensweise beim Systemstart() Connect External Component("...", "DemoVK", External Component Type.Native); DemoComp = New("AddIn.DemoVK.SomeName"); Lane = DemoComp.Test("Hallo", "Welt!"); Bericht(pro); Ende des Verfahrens
Nach dem Start der Konfiguration erhalten wir die Meldung „Hello, World!“, die anzeigt, dass die Methode erfolgreich funktioniert hat.

Timer

Aufgabe:
  1. Studieren Sie die Implementierung des Timers im Demo-VK
  2. Ändern Sie die Methode „StartTimer“, indem Sie die Möglichkeit hinzufügen, in den Parametern das Timer-Antwortintervall (in Millisekunden) zu übergeben.
  3. Stellen Sie sicher, dass die von Ihnen vorgenommenen Änderungen funktionieren.

In WinAPI können Sie die Nachricht verwenden, um mit der Zeit zu arbeiten WM_TIMER. Diese Nachricht wird in dem Zeitintervall, das Sie beim Erstellen des Timers festgelegt haben, an Ihr Programm gesendet.
Um einen Timer zu erstellen, verwenden Sie die Funktion SetTimer:
UINT SetTimer(HWND hWnd, // Fensterdeskriptor UINT nIDevent, // Timer-ID (Nummer) UINT nElapse, // Verzögerung TIMERPROC lpTimerFunc); // Zeiger auf Funktion
Das Betriebssystem sendet eine Nachricht WM_TIMER in das Programm mit dem im Argument angegebenen Intervall ein nElapse(in Millisekunden). Im letzten Parameter können Sie eine Funktion angeben, die bei jedem Auslösen des Timers ausgeführt wird. Der Header dieser Funktion sollte so aussehen (der Name kann beliebig sein):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Betrachten wir die Implementierung eines Timers in der Demo-VC.
Da wir über die Entwicklung einer externen Komponente für die Windows-Betriebssystemfamilie nachdenken, werden wir die Implementierung des Timers in anderen Betriebssystemen nicht in Betracht ziehen. Insbesondere für GNU/Linux-Betriebssysteme unterscheidet sich die Implementierung in der Syntax der Funktion SetTimer Und TimerProc.
Der ausführbare Code ruft die Methode auf SetTimer, an den die Funktion übergeben wird MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
Die ID des erstellten Timers wird in einer Variablen abgelegt m_uiTimer damit es später deaktiviert werden kann.
Funktion MyTimerProc wie folgt:
VOID CALLBACK MyTimerProc(HWND hwnd, // Handle des Fensters für Timer-Nachrichten UINT uMsg, // WM_TIMER-Nachricht UINT idEvent, // Timer-ID DWORD dwTime // aktuelle Systemzeit) ( 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 , was, wstime); delete wstime;
Der Kern der Funktion besteht darin, dass die Methode aufgerufen wird Externes Ereignis, das eine Nachricht an das 1C: Enterprise-System sendet.
Um die Funktionalität der Methode zu erweitern StartTimer Machen wir Folgendes:
Ändern des Methodencodes GetNParams damit es für die Methode ist eMethStartTimer Rückgabewert 1:
case eMethStartTimer: return 1;
Hier ist der Methodencode CallAsProc zum Formular:
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;
Lassen Sie uns nun die Funktionalität überprüfen. Dazu schreiben wir den Code in das verwaltete Anwendungsmodul der Konfiguration:
Variable DemoComp; Vorgehensweise beim Systemstart() Connect External Component("...", "DemoVK", External Component Type.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); Ende des Verfahrens
Nach dem Start der Konfiguration erhält das Programm im Abstand von 2 Sekunden Meldungen, die darauf hinweisen, dass der Timer ordnungsgemäß funktioniert.

Interaktion mit dem 1C: Enterprise-System

Zur Interaktion zwischen der externen Komponente und dem 1C: Enterprise-System werden Methoden der IAddInDefBase-Klasse verwendet, die in der Datei beschrieben sind AddInDefBase.h. Wir listen die am häufigsten verwendeten auf:
Generieren einer Fehlermeldung
virtual bool ADDIN_API AddError(unsigned short wcode, const WCHAR_T* source, const WCHAR_T* descr, long scode)
wcode, Code- Fehlercodes (eine Liste der Fehlercodes mit Beschreibungen finden Sie auf der ITS-Diskette)
Quelle- Fehlerquelle
Beschreibung- Fehlerbeschreibung
Senden einer Nachricht an das 1C: Enterprise-System
virtual bool ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszSource- Nachrichtenquelle
wszMessage- Nachrichtentext
wszData- übermittelte Daten
Das Abfangen von Nachrichten erfolgt durch das Verfahren zur externen Ereignisverarbeitung
Registrierung einer externen Komponente im 1C: Enterprise-System
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfileName- Komponentenname.
Diese Methoden reichen für eine vollständige Interaktion zwischen VK und 1C aus. Um Daten von einer externen Komponente aus dem 1C:Enterprise-System zu empfangen und umgekehrt, sendet die externe Komponente eine spezielle Nachricht, die wiederum vom 1C-System abgefangen wird und ggf. die Methoden der externen Komponente aufruft, um Daten zurückzusenden .

tVariant-Datentyp

Beim Datenaustausch zwischen der externen Komponente und dem 1C:Enterprise-System wird der Datentyp tVariant verwendet. Es ist in der Datei „types.h“ beschrieben, die sich auf der ITS-Festplatte befindet:
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; wchar_t wchVal; struct tmVal; void* pInterfaceVal; __VARIANT_NAME_2/*iface*/; //count of bytes __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; //count of symbol ) VARIANT_NAME_1 ;dimensionales Array in pvarVal TYPEVAR vt);
Typ tVariante ist eine Struktur, die Folgendes umfasst:
  • Mischung (Vereinigung), die direkt zur Datenspeicherung bestimmt ist
  • Datentyp-ID
Im Allgemeinen wird mit Variablen vom Typ gearbeitet tVariante erfolgt nach folgendem Algorithmus:
  1. Bestimmen des aktuell in einer Variablen gespeicherten Datentyps
  2. Greifen Sie auf das entsprechende Mischungsfeld zu, um direkt auf die Daten zuzugreifen
Verwendung des Typs tVariante vereinfacht das Zusammenspiel des 1C: Enterprise-Systems und externer Komponenten erheblich

Anwendung

Das Verzeichnis „examples“ enthält Beispiele für den Artikel
Beispiele/1 – Starten Sie die Demo-Komponente
Beispiele/2 – Demonstration der Erweiterung der Eigenschaftsliste
Beispiele/3 – Demonstration der Erweiterung der Methodenliste
Jedes Verzeichnis enthält ein VS 2008-Projekt und eine vorgefertigte 1C-Konfiguration.