DIE KLINGEL

Es gibt diejenigen, die diese Nachricht vor Ihnen gelesen haben.
Abonnieren Sie, um die neuesten Artikel zu erhalten.
Email
Name
Familien-oder Nachname
Wie möchten Sie The Bell lesen?
Kein Spam

Frage: Externe native API-Komponente in C++ für Linux (Ubuntu x64) auf 1С 8.3


Ich schreibe VK, ich kann keine Verbindung zu 1s auf Ubuntu herstellen. Auch das Beispiel von 1s ist nicht verbunden. Also eine Frage dazu:

1) Ich versuche, VK aus dem im Artikel angegebenen VNCOMPS-Beispiel zu verbinden

(den Link finden Sie ganz am Ende: "Kopieren").
Intern hat das NativeApi-Projekt ein Makefile. Damit baue ich die .so-Bibliothek auf Ununtu.
Aber bei "Connect the External Component" 1 hebt 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 dem m32-Parameter wird es sowieso nicht abgeholt)
Hier ist ein Beispiel für den Aufruf von VK von 1C 8.3:
ConnectionDone = Schließen Sie eine externe Komponente an("/home/alexeyubuntux64-20 gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); Es gibt einen Artikel nur zu diesem Thema.
Aber, soweit ich sehen kann, wurden alle diese Punkte bereits im VNCOMPS-Beispiel berücksichtigt und korrigiert.

Aber eigentlich geht es um die Parameter der Zusammenstellung. Die externe 32-Bit-MB-Komponente verbindet sich normalerweise mit 32-Bit 1c, aber ich habe sie auf Ubuntu x64 1c enterprise83 8.3.5-1486 amd64 bereitgestellt. Und ich möchte VK zu ihr abholen.

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

Antworten: Ist es interessanterweise möglich, eine externe Komponente in Java zu schreiben?

Frage: Externe Komponente (Native) ist nicht angeschlossen


Kompiliert ein Beispiel mit ITS, für 64- und 32-Bit-Systeme.

Ich verbinde so:
ConnectionResult = ConnectExternalComponent(CDLLPath, "Comp", ExternalComponentType.Native); Ein PC verbindet sich, der andere nicht. Es gibt einen Unterschied im Betriebssystem. Wo die Verbindung hingeht, ist Win7, wo kein Win10 ist. Gleichzeitig funktionieren Standardkomponenten auf einem PC, auf dem meine Komponente nicht funktioniert.

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

Wie kann man verstehen, warum es keine Verbindung herstellt?

Antworten: vc_redist nicht vergessen?

Frage: 1C8 und eine externe Komponente vom Typ Native


Guten Tag.
Es besteht eine Konfiguration von BP 3.0.50.12 und der Wunsch, Wägungen der Firma Scales-Soft mit UniServerAuto zu implementieren.
Die Entwickler haben die Native-Komponente für Windows 32 und 64 kompiliert und mit der maifest-Datei in ein Archiv gelegt. Es gibt auch ein Beispiel für 1C, wie das Gewicht berechnet werden kann. Darin wird mit Hilfe eines Layouts mit binären Daten dieses Archiv angezeigt, 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 Sie beginnen, sich auf 1C zu übertragen, wird das Gewicht nicht gelesen. Es scheint, dass alles einfach geschrieben ist, aber ich verstehe nicht, wo der Rechen ist.
Wer ein wenig Zeit hat - Hilfe, schaut mit einem Auge hin, vielleicht liegt die Lösung an der Oberfläche, aber ich laufe irgendwo am falschen Ort und mache etwas falsch. Ich habe noch nie mit nativer Technologie gearbeitet...

Und im Anhang ist mein Bearbeitungstext

Antworten:

Nun, ich habe Neuigkeiten...
Ich habe gerade angefangen, mir Schritt für Schritt anzusehen, ab wann es anfängt zu scheitern. Dazu habe ich eine leere Datenbank erstellt und mit dem Befehl verarbeitet. Analog zum Beispiel des Anbieters habe ich das Layout auf eine neue conf übertragen - beim zweiten Mal funktioniert es. Diese. Beim ersten Mal nein, beim zweiten Mal ja. Daraus entstand die Überlegung, dass es bei der Verarbeitung noch notwendig wäre, die Verbindung von Bauteil und Objekt nach unterschiedlichen Verfahren zu trennen.
Dann habe ich es mit einer Anlagenverbindung in meine Datenbank übertragen - es funktioniert. Puh, es ist schon gut .... Aber ich möchte es ohne Änderungen an der Konfiguration vornehmen, also lass uns weitermachen

Ich versuche, ein Layout zur Verarbeitung hinzuzufügen. Seine Größe steigt sofort von 10 KB auf 3 MB und es wird eine erhebliche Verlangsamung festgestellt - es passt nicht. Ich fange an, in Richtung Verbindung einer Komponente durch DLL zu graben. Diese. im Grunde dasselbe, wo Sie angefangen haben. Aber es gibt ein "ABER": Als ich nach dem Namen der DLL im Ordner des Benutzers suchte, bemerkte ich, dass diese DLL dort liegt, wo (so wie ich es verstehe) die in 1C registrierten DLLs hinzugefügt werden:
C:\Users\USER\AppData\Roaming\1C\1cv8\ExtCompT
Dementsprechend ist es nicht erforderlich, den vollständigen Pfad zur DLL zu verwenden, Sie können einfach ihren Namen schreiben:
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

Ich versuche ... schwört auf die Registrierung, gibt aber das Ergebnis des Wiegens zurück. Es stellt sich heraus, dass die DLL bereits registriert ist, was bedeutet, dass Sie sie nur verbinden müssen. Ich entferne es und alles funktioniert.
Ich fasse zusammen:
1. In der Verarbeitung des Wiegens in der Prozedur Beim Öffnen habe ich die Verbindung einer externen Komponente und die Verbindung zum Objekt hinzugefügt.
2. Den Pfad zur DLL habe ich nicht geschrieben, ich habe nur ihren Namen angegeben.

Jetzt sitze ich und denke, wann wurde die DLL in 1C installiert? Zum Zeitpunkt der Softwareinstallation? Wohl kaum... Wo wird diese DLL zum Zeitpunkt der Ausführung der Entwicklerkonfiguration beim Öffnen des Formulars eingestellt? Ich weiß es nicht, aber es kommt mir nahe... Was denkst du?
Und zweitens, wenn an einem neuen Ort dasselbe Terminal installiert werden muss, was muss getan werden, damit alles funktioniert? Die Software komplett installieren, die Konfiguration des Anbieters ausführen, um die Arbeit zu überprüfen, und dann sollte (theoretisch) meine Verarbeitung funktionieren? Etwas kompliziert ... Oder nach der Installation der Software in meiner Verarbeitung InstallExternalComponent einmal ausführen?

Ich würde gerne eure Meinung dazu hören...

Frage: Externe Komponente.dll


Guten Tag allerseits.
Eine Frage.
dll-Komponente, die in 1C 7.7 einwandfrei funktioniert
in 1s 8.1 will überhaupt nicht booten ...
Habe es versucht und in C:\Program Files\1cv81\bin\cache1c.dll eingefügt
Ich habe versucht, mich mit regsvr32 "C:\Program Files\1cv81\bin\cache1c.dll" zu registrieren
Registriert ohne Probleme.
Wenn ich versuche, darauf zuzugreifen, erhalte ich eine Fehlermeldung:

Fehler beim Laden der externen Komponente! cache1c.dll
Prozedur Ausführen ButtonClick(Button) Versuch externe Komponente zu laden( "C:\Programme\1cv81\bin\cache1c.dll"); Ausnahmebericht( "Fehler beim Laden der externen Komponente!"+ "cache1c.dll"); Ende des Versuchs; Versuch // Komponentenobjekt abrufen. // m = Neu ("cache1c.GTMcmd" ); m = Neues COMObject("cache1c.GTMcmd" ); Ausnahmebericht(); Ende des Versuchs; EndProzedur

Antworten: Banal bis zur Unmöglichkeit...
Es ist notwendig, Pausen zwischen Anrufen (Millisekunden) aufrechtzuerhalten...
Prozedur ButtonExecuteClick(Button) Attempt // Ruft das Komponentenobjekt ab. m = Neues COMObject("cache1c.GTMcmd" ); Ausnahmebericht( "Externes Komponentenobjekt konnte nicht erstellt werden"); Ende des Versuchs; m.RemoteHost = "192.168.1.101" ; m.RemotePort = 6330; m.Connect(); m.pause(100); ...... usw
Für 1s 7.7 - ist dies nicht erforderlich, es stellt sich heraus, dass die Handhabung schneller ist.

Frage: Die Arbeit einer externen Komponente mit dem 1C-Server ...


Guten Tag,

Es gibt eine in C ++ geschriebene externe Komponente, deren Aufgabe es ist, Informationen aus einer externen Datenbank zu erhalten und das Ergebnis der Abfrage in Form einer Wertetabelle in 1C zurückzugeben.
Um im aktuellen Moment eine Wertetabelle zu bilden, wird die Schnittstelle IDispatch* pBackConnection verwendet, die als Parameter in der Funktion Init() empfangen wird. Außerdem bilde ich einfach mit den 1C-Funktionen eine Wertetabelle, fülle sie aus und gebe sie an den zweiten Parameter in CallAsFunc (...) zurück.
Die Probleme begannen mit der Umstellung auf 1C-Thin-Clients. Serverseitig 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 heraus. Beispielsweise versteht der Client nicht, was eine Wertetabelle ist, Probleme mit "globalen" Variablen, Sitzungen usw.
NativeAPI ist in dieser Hinsicht noch stärker verkürzt.
Das Tanzen mit einem Tamburin führte dazu, dass ich eine externe Komponente unter dem 1C-Server starten konnte, ABER die Arbeit passiert, bis versucht wird, Invoke auf pBackConnection aufzurufen. Die 64-Bit-Version des Servers 8.2 versucht so lange etwas zu tun, bis es bei einem Timeout abfällt, die 32-Bit-Version (VK ist natürlich auch 32-Bit) fällt einfach gleich ab.
Ich gehe davon aus, dass der 1C-Server diese Betriebsart nicht bedient.
Dementsprechend stellen sich Fragen, ist es vorübergehend oder reduziert sich die Logik von 1C auf die Abschaffung dieses Arbeitsschemas? Wenn es unmöglich ist, interne Strukturen von 1C (Wertetabelle) auf diese Weise zu erstellen, gibt es im Prinzip eine Beschreibung dessen, was eine Wertetabelle auf Systemebene ist, um zu versuchen, sie in C + zu erstellen +, ausfüllen und dann einfach 1C als Rückgabeparameter schieben? Ich möchte zumindest eine Richtung bekommen, in die ich graben muss.

Vielen Dank.

Antworten:

Du schreibst das eine und meinst das andere.
In der 1C-Umgebung ist das Deklarieren von Variablen, die in verschiedenen Sitzungen sichtbar sind, jetzt nicht unmöglich und war vorher nicht möglich. Eine andere Sitzung ist ein physikalisch anderer Prozess.
Sitzung ist eine Datenbankverbindungssitzung, d. h. Benutzersitzung. Oder setzen Sie etwas Eigenes und dieses Konzept um?

Innerhalb einer Sitzung war es möglich, und es ist jetzt möglich, Variablen im Sitzungsmodul zu deklarieren, die innerhalb der Sitzung von verschiedenen Stellen leben und sichtbar sein werden ... eigentlich gibt es 4 davon.
- Sitzungsmodul;
- Reguläres Bewerbungsmodul;
- Verwaltetes Anwendungsmodul;
- Externes Anschlussmodul.

Und natürlich müssen Sie sich an den Kontext erinnern. Der Serverkontext ist auf der Clientseite nicht direkt zugänglich und umgekehrt.

Im Allgemeinen sieht die 1C-Architektur vor, dass der Datenaustausch fortgesetzt wird:
- durch Parameter/Rückgaben von Prozeduren/Funktionen;
- mittels der sogenannten Session-Parameter (das können keine Objekte sein, man kann es tatsächlich in der Palette sehen).

Die Tabelle auf dem Formular... und sie ist mit irgendeiner Objekttabelle verbunden (zum Beispiel Verarbeitungen)? oder nicht. Wenn ja, dann ist es auch auf dem Server (&AtServer) verfügbar und dort editierbar....

Und ja, die ValueTable ist clientseitig nicht in UV verfügbar. Nun, 1C hat sich so entschieden.

Nun ja! Hier funktioniert es mit Excel, es funktioniert mit FSO und allem anderen, aber hier funktioniert es nicht. Fehler abfangen und analysieren....

Versuchen
...
eure Aktionen
...
Ausnahme
str = Beschreibungsfehler ();
Ende des Versuchs;

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

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

Geben Sie den Code ein, den Sie hochladen, und bewerben Sie sich bei 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 Bittiefenproblem?

Frage: Installieren einer externen Komponente


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

Versuch, SetExternalComponent("GeneralLayout.Layout"); Ausnahme EndTry ;
Fehler: Plugin-Installation fehlgeschlagen!

Antworten: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native) gibt FALSE zurück,
New("AddIn.NameDecl.CNameDecl", Undefined) = (()): Typ nicht definiert (AddIn.NameDecl.NameDecl)

Frage: Native DLL ist nicht mit 1s 8.1 verbunden (fptrwin32_fz54_9_11_0_5549.dll)


Guten Tag.
1C aktualisierte die dll für Online-Registrierkassen atol für fdd 1.05 (in der Wartungsverarbeitung fptrwin32_fz54_9_11_0_5549.dll enthalten).
Ich habe einen alten 1C 8.1. Im Gegensatz zu 8.2 unterstützt es nicht die Arbeit mit externen Geräten auf die gleiche Weise wie 8.2, also müssen Sie 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);

Die alte Verarbeitung wurde jedoch in "Technologie" com und die neue native geschrieben. Dementsprechend gibt regsvr32 bei der Registrierung einen Fehler aus:
Das Modul wurde geladen, aber der DllRegisterServer-Einstiegspunkt wurde nicht gefunden. Und schlägt vor, zu überprüfen, ob diese Datei die richtige DLL- oder OCX-Datei ist.
Wer stand vor einer ähnlichen Situation, wie sind Sie herausgekommen? Ich verstehe, dass ein ähnliches Problem in 7.7 sein wird.
Code 8.2:

Layout = GetLayout("IntegrationComponent"); Adresse = PlaceInTempStorage(Layout); ConnectExternalComponent(Adresse, "IntegrationComponent", ExternalComponentType.Native); Treiber = New("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

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

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

Vielen Dank!

Antworten:

Ich hatte dieses Problem auch vor kurzem. Eine Umstellung auf eine neuere Version von 1s war nicht möglich. dll, mit der diese Konfiguration funktioniert, funktionierte einfach nicht mehr und 1c fiel mit einem Fehler aus.
Das Problem wurde folgendermaßen gelöst:
Ich habe eine leere Datenbank 8.3 erstellt, in der ich die Initialisierung der Komponente bearbeitet habe und dann ab 8.1 per 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:
Rem-Treiberexport;
Funktion ConnectionComponentsCCP() Export
Versuchen

Layout = GetLayout("IntegrationComponent");
Adresse = PlaceInTempStorage(Layout);
ConnectExternalComponent(Adresse, "IntegrationComponent", ExternalComponentType.Native);
Treiber = New("AddIn.IntegrationComponent.SMDrvFR1C20");
Ergebnis = wahr;​

Ausnahme

Ergebnis = falsch;​

Ende des Versuchs;
Ergebnis zurückgeben
Endfunktionen

Codebeispiel 8.1

Funktion CreateDriverObject(Driver) Export

Ergebnis = wahr;

Versuchen

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

Processing = Connect.Processing.ConnectingExternalComponent.Create();
ConnectionResult = Processing.ConnectingKKT-Komponenten ();
Wenn Ergebnis verbindet, dann
Treiber = Processing.Driver;
EndIf;​

Ausnahme
Jeder, der dies getan hat oder ähnliche Probleme hatte, bitte erklären. einfaches Beispiel das Prinzip selbst. Mit dem Anschluss externer Komponenten scheint alles klar zu sein.

// Ein Beispiel für das Füllen der Wertetabelle TK.Clear(); Anfrage = Neue Anfrage; Abfrage.Text = "AUSWÄHLEN | Nomenklatur Link WIE Nomenklatur |VON | Directory.Nomenclature AS Nomenclature"; QueryResult = Query.Execute(); Sampling = QueryResult.Select(); While Sampling.Next() Loop Str = TK.Add(); FillPropertyValues(Pr, Sampling); EndCycle;
Können Sie anhand dieses Beispiels erklären, welcher Teil des Codes normalerweise herausgenommen wird? Es wäre logisch, den Teil mit der Anfrage herauszunehmen, aber wie können wir dann von der externen Komponente aus auf die Datenbank zugreifen und die Plattform umgehen? Der Text ist sinnlos. Oder nehmen Sie die Bildung des tabellarischen Teils heraus. Bitte teilen Sie Ihre Erfahrungen damit.

Antworten: Und dass das Wort "Inkompatibel" immer das Wort "Schlecht" bedeutet? Ja, es scheint mir, dass, wenn ich meinen Stil „1C: Die schlechteste Programmierung auf dieser Skript-Engine, die in der Natur existiert (übersetzt in eine Literatursprache)!“ nenne. und dann wird es bestimmt diejenigen 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!“ :)

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


Es ist notwendig, die vk_rs232.dll ExternalComponent mit der selbst geschriebenen Konfiguration zu verbinden. Wie über regsvr32.exe registriert. "Es scheint", weil ich eine Meldung erhalten habe, dass "die Komponente registriert ist, aber etwas mit der Firewall nicht stimmt". Ausgehend von der ersten Hälfte der Nachricht schreibe ich den Code in Einsen
AfterConnection = New NotificationDescription("AfterConnectionVK",ThisForm); StartExternalComponentInstallation(,"C:\Controller\vk_rs232.dll"); StartConnectingExternalComponent(AfterConnecting,"C:\Controller\vk_rs232.dll","DLL_Scale");
und ich bekomme den Fehler, dass
"Installation der externen Komponente fehlgeschlagen! Möglicherweise fehlt die Komponente für die von Ihnen verwendete Client-Anwendung!".

Und jetzt verstehe ich nicht
1. Eventuell ist die Komponente nicht in der Registry registriert - wie kann ich das dort überprüfen?
2. Vielleicht funktioniert seine "Version" nicht unter Win8, obwohl ich es 32-Bit habe.
3. Vielleicht ist 1s selbst zu neu, d.h. kann dementsprechend nicht mit dieser dll arbeiten?
4. Nun, es ist banal - ich schreibe etwas falsch.

Antworten: Und all das führte mich zum nächsten Problem. VneshComp installiert, jetzt müssen Sie es verbinden. Und hier sind beide Optionen.
ConnectExternalComponent("C:\Controller\vk_rs232.dll","Waagen")
ConnectExternalComponent("GeneralLayout.Layout","Scale")

Syntaxoption: Nach Name und Ort

Syntax:

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

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

Typ: Zeichenkette.
Die Position der externen Komponente.
Ort kann verwendet werden:
Pfad zur Datei der externen Komponente im Dateisystem (nicht im Webclient verfügbar), kein ZIP-Archiv;
Vollständiger Name ein Layout, das binäre Daten oder ein ZIP-Archiv speichert;
Die URL zur externen Komponente, in Form von Binärdaten oder einem ZIP-Archiv, in einer , ähnlich wie bei GetNaviLink.
<Имя>(erforderlich)

Typ: Zeichenkette.
Der symbolische Name der steckbaren externen Komponente.
Der Name muss den Namenskonventionen der eingebauten Sprache folgen.
<Тип>(Optional)

Typ: ExternalComponent-Typ.
Der Typ der anzuschließenden externen Komponente.
Wird nicht verwendet, wenn die Komponente in einem ZIP-Archiv gepackt ist.
Beschreibung der Verfahrensvariante:

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

Syntax:

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

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

Typ: Zeichenkette.
Objektidentifikator der externen Komponente in Form von ProgID (Programmatic Identifier) ​​​​der MS Windows-Registrierung (zum Beispiel: "AddIn.Scanner").
Muss mit den Informationen in der Systemregistrierungsdatenbank (Registry) übereinstimmen.
Beschreibung der Verfahrensvariante:

Die Komponente muss unter Verwendung der COM-Technologie implementiert und in der MS Windows-Registrierung registriert werden.
Diese Komponenten sind mit 1C:Enterprise 7.7-Komponenten kompatibel.
Aufmerksamkeit! Die Variante des Verfahrens funktioniert nicht auf dem Server und in der äußeren Verbindung.
Rückgabewert:

Typ: Boolesch.
Richtig - die Verbindung war erfolgreich.
Beschreibung:

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

Verfügbarkeit:

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

Externe Komponenten können mit nativer API oder COM-Technologie implementiert werden. Mit COM-Technologie hergestellte Komponenten sind mit 1C:Enterprise 7.7-Komponenten kompatibel.
Der Web-Client kann nur mit Komponenten in einer Infobase arbeiten, die in ein Archiv gepackt sind.
Der Thin Client kann mit Komponenten in der Infobase arbeiten, die in einem Archiv gepackt sind, und mit Komponenten, die sich im Dateisystem befinden.
Der Thick Client kann mit allen Speichermöglichkeiten für Komponenten arbeiten. Wenn in diesem Fall die Komponente mit der InstallExternalComponent-Methode installiert wird, wird die installierte Komponente verwendet, und wenn sie nicht installiert ist, wird die Komponente zum Zeitpunkt der Verbindung empfangen.
Der Server kann mit allen Komponenten arbeiten. Die Komponente wird für die Serversitzung zwischengespeichert.
Beispiel:

If ConnectExternalComponent("AddinObject.Scanner") Then
alert("Barcode-Scanner-Komponente geladen");
Andernfalls
alert("Barcode-Scanner-Komponente nicht geladen");
EndIf;

  • Lernprogramm

Einführung

Dieser Artikel gibt eine Vorstellung davon, wie externe Komponenten im 1C:Enterprise-System funktionieren.
Der Prozess der Entwicklung einer externen Komponente für das System 1C:Enterprise Version 8.2, das unter dem Windows-Betriebssystem mit einer Dateiversion der Arbeit läuft, wird gezeigt. Diese Option wird in den meisten Lösungen für kleine Unternehmen verwendet. Der VC wird in der Programmiersprache C++ implementiert.

Externe Komponenten "1C: Enterprise"

"1C: Enterprise" ist ein erweiterbares System. Zur Erweiterung Funktionalität System verwendet externe Komponenten (VC). Aus der Sicht eines Entwicklers 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.
Externe Komponenten können verwendet werden, um eine Klasse von Aufgaben zu lösen, die mit der in 1C: Enterprise integrierten Programmiersprache schwierig oder sogar unmöglich zu implementieren sind. Diese Klasse umfasst insbesondere Aufgaben, die eine Interaktion auf niedriger Ebene mit dem Betriebssystem erfordern, beispielsweise um mit bestimmter Hardware zu arbeiten.
Das 1C:Enterprise-System verwendet zwei Technologien zum Erstellen externer Komponenten:
  • mit nativer API
  • mit COM-Technologie
Angesichts der Einschränkungen zwischen den beiden oben genannten Technologien ist der Unterschied unbedeutend, daher werden wir die Entwicklung von VK unter Verwendung der nativen API in Betracht ziehen. Die implementierten Entwicklungen können bei Bedarf auf die Entwicklung von VC mit COM-Technologie angewendet werden und mit geringfügigen Änderungen auch für die Verwendung im 1C: Enterprise-System mit anderen Betriebsoptionen als dem Dateimodus verwendet werden.
VK-Struktur
Die externe Komponente des 1C:Enterprise-Systems wird als DLL-Bibliothek präsentiert. Der Bibliothekscode beschreibt die abgeleitete Klasse IComponentBase. In der zu erstellenden Klasse müssen die Methoden definiert werden, die für die Implementierung der Funktionen der externen Komponente verantwortlich sind. Die überschriebenen Methoden werden später im Verlauf der Präsentation des Materials ausführlicher beschrieben.

Starten der Demo VK

Eine Aufgabe:
  1. Stellen Sie die externe Komponente zusammen, die mit dem ITS-Abonnement geliefert wird und dazu dient, die Hauptfunktionen des Mechanismus der externen Komponente in 1C zu demonstrieren
  2. Verbinden Sie die Demo-Komponente mit der 1C-Konfiguration
  3. Stellen Sie sicher, dass die deklarierten Funktionen ordnungsgemäß funktionieren
Zusammenstellung
Die Demo-VC befindet sich auf der ITS-Abonnementdiskette im Verzeichnis „/VNCOMP82/example/NativeAPI“.
Zum Zusammenstellen des Demo-VK 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 verbinden wir das Verzeichnis mit den Header-Dateien, die zum Erstellen des Projekts erforderlich sind. Sie befinden sich standardmäßig auf der ITS-Platte im Verzeichnis /VNCOMP82/einschließen.
Das Build-Ergebnis ist eine Datei /bind/AddInNative.dll. Dies ist die kompilierte Bibliothek zum Verbinden mit der 1C-Konfiguration.
Verbinden von VK mit der 1C-Konfiguration
Lassen Sie uns eine leere Konfiguration 1C erstellen.
Es folgt der Code für das verwaltete Anwendungsmodul.
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...\bind\AddInNative.dll", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); EndProzedur
Wenn beim Starten der 1C-Konfiguration kein Fehler gemeldet wurde, wurde der VK erfolgreich verbunden.
Als Ergebnis der Ausführung des obigen Codes erscheint ein Objekt in der globalen Sichtbarkeit der Konfiguration DemoComp Eine mit Eigenschaften und Methoden, die im externen Bean-Code definiert sind.
Demonstration der eingebetteten Funktionalität
Lassen Sie uns die Leistung des Demo-VK überprüfen. Versuchen wir dazu, einige Eigenschaften zu setzen und zu lesen, einige VK-Methoden aufzurufen und auch eine VK-Nachricht zu empfangen und zu verarbeiten.
Die auf der ITS-Diskette mitgelieferte Dokumentation gibt die folgende Funktionalität des Demo-VC an:
  1. Zustandsverwaltung von Komponentenobjekten
    Methoden: Einschalten, Ausschalten
    Eigenschaften: Inbegriffen
  2. Zeitsteuerung
    Jede Sekunde sendet die Komponente eine Nachricht mit Parametern an das 1C: Enterprise-System Komponente, Timer und eine Systemuhr-Zählerkette.
    Methoden: StartTimer, StopTimer
    Eigenschaften: Es gibt eine Zeitschaltuhr
  3. Methode ShowInStatusLine, die in der Statusleiste den als Parameter an die Methode übergebenen Text anzeigt
  4. Methode Bild hochladen. Lädt ein Bild aus der angegebenen Datei und überträgt es als Binärdaten an das 1C:Enterprise-System.
Stellen wir sicher, dass diese Funktionen funktionieren. Dazu führen wir den folgenden Code aus:
var DemoComp; SystemStart() Prozedur ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); Benachrichtigen (DemoComp. Aktiviert); DemoComp.Enable(); Benachrichtigen (DemoComp. Aktiviert); DemoComp.StartTimer(); EndProcedure ProcedureExternalEventHandler(Source, Event, Data) Report(Source + " " + Event + " " + Data); EndProzedur
Das Ergebnis der Ausführung der Konfiguration wird im Bild angezeigt


Die Ergebnisse von Methodenaufrufen werden im Bereich „Meldungen“ angezeigt DemoComp.Disable() und Demo.Comp.Enable(). Die nachfolgenden Zeilen auf demselben Panel enthalten die Ergebnisse der Verarbeitung von Nachrichten, die von VK empfangen wurden - Quelle, Vorfall und Daten beziehungsweise.

Beliebiger externer Komponentenname

Aufgabe: Ändern Sie den Namen der externen Komponente in einen beliebigen Namen.
Im vorherigen Abschnitt wurde der Bezeichner verwendet AddInNativeExtension, deren Bedeutung nicht erklärt wurde. In diesem Fall AddInNativeExtension ist der Name der Erweiterung.
Der VC-Code definiert ein Verfahren RegisterExtensionAs, der den Namen an das 1C: Enterprise-System zurückgibt, der für die spätere Registrierung des VC im System erforderlich ist. Es empfiehlt sich, einen Identifikator anzugeben, der gewissermaßen 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, wsExtension, iActualSize); true zurückgeben; ) false zurückgeben; )
Im obigen Beispiel wurde der VK-Name geändert in Irgendein Name. Dann müssen Sie beim Verbinden des VK einen neuen Namen angeben:
DemoComp = New("AddIn.DemoVK.SomeName");

Erweiterung der Liste der VK-Eigenschaften

Eine Aufgabe:
  1. Untersuchen Sie die Implementierung von VC-Eigenschaften
  2. Fügen Sie eine Lese-/Schreibeigenschaft eines Zeichenfolgentyps hinzu
  3. Fügen Sie eine Zeichenfolgentyp-Eigenschaft mit Lese-/Schreibzugriff hinzu, die den Datentyp der zuletzt festgelegten Eigenschaft speichert. Beim Festlegen des Eigenschaftswerts wird keine Aktion ausgeführt

Um die Eigenschaften der zu erstellenden Komponente zu definieren, muss der Entwickler die folgenden Methoden im Code der AddInNative.cpp-Bibliothek implementieren:
Holen Sie sich NProps
Gibt die Anzahl der Eigenschaften für diese Erweiterung zurück, 0, wenn keine Eigenschaften vorhanden sind
FindProp
Gibt die Ordnungszahl der Eigenschaft zurück, deren Name in den Parametern übergeben wird
GetPropName
Gibt den Namen der Eigenschaft nach ihrer Ordnungszahl und nach der übergebenen Sprach-ID zurück
GetPropVal
Gibt den Wert der Eigenschaft mit der angegebenen Ordinalzahl zurück
SetPropVal
Legt den Wert der Eigenschaft mit der angegebenen Ordnungszahl fest
IsPropReadable
Gibt das Lesbarkeits-Flag der Eigenschaft mit der angegebenen Ordnungszahl zurück
IsPropWritable
Gibt das Eigenschafts-Beschreibbarkeits-Flag mit der angegebenen Sequenznummer zurück


Betrachten Sie die Implementierung der obigen Klassenmethoden CAddInNative.
Der Demo-VC definiert 2 Eigenschaften: Inbegriffen und Es gibt eine Zeitschaltuhr (Aktiviert und IsTimerPresent).
Im globalen Gültigkeitsbereich des Bibliothekscodes sind zwei Arrays definiert:
statisch wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"Aktiviert", L"Es gibt einen Timer");
die die russischen und englischen Namen der Eigenschaften speichern. In Header-Datei AddInNative.h eine Aufzählung ist definiert:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // Immer zuletzt);
ePropIsEnabled und ePropIsTimerPresent, die jeweils die Werte 0 und 1 haben, werden verwendet, um die Ordnungszahlen von Eigenschaften durch aussagekräftige Bezeichner zu ersetzen. ePropLast, das einen Wert von 2 hat, wird verwendet, um die Anzahl der Eigenschaften abzurufen (unter Verwendung der GetNProps-Methode). Diese Namen werden nur innerhalb des Codes der Komponente verwendet und sind von außen nicht zugänglich.
Die Methoden FindProp und GetPropName durchsuchen Arrays g_PropNames und g_PropNames.
Um den Wert der Felder im Bibliotheksmodul zu speichern, verfügt die Klasse CAddInNative über Eigenschaften, die den Wert der Eigenschaften der Komponente speichern. Methoden GetPropVal und SetPropVal jeweils den Wert dieser Eigenschaften zurückgeben und festlegen.
Methoden IsPropReadable und IsPropWritable und zurück Stimmt oder FALSCH, abhängig von der übergebenen Ordnungszahl der Eigenschaft gemäß der Anwendungslogik.
So fügen Sie eine benutzerdefinierte Eigenschaft hinzu:

  1. Fügen Sie den Namen der Eigenschaft hinzu, die zu Arrays hinzugefügt werden soll g_PropNames und g_PropNames(Datei AddInNative.cpp)
  2. Zur Aufzählung Requisiten(Datei AddInNative.h) Vor ePropLast Fügen Sie einen Namen hinzu, der die hinzuzufügende Eigenschaft eindeutig identifiziert
  3. Speicher zum Speichern von Eigenschaftswerten organisieren (Komponentenmodulfelder erstellen, die die entsprechenden Werte speichern)
  4. Nehmen Sie Änderungen an Methoden vor GetPropVal und SetPropVal um mit dem im vorherigen Schritt zugewiesenen Speicher zu interagieren
  5. Nehmen Sie gemäß der Anwendungslogik Änderungen an den Methoden vor IsPropReadable und IsPropWritable
Die Punkte 1, 2, 5 bedürfen keiner Erläuterung. Details zur Umsetzung dieser Schritte finden Sie im Anhang des Artikels.
Nennen wir die Testeigenschaften Prüfen und Geben Sie Prüfen ein beziehungsweise. Dann haben wir als Ergebnis von Absatz 1:
static wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); static wchar_t *g_PropNamesRu = (L"Enabled", L"HasTimer", L"Test", L"CheckType");
Aufzählung Requisiten wird aussehen wie:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // Immer zuletzt);
Um den Code erheblich zu vereinfachen, verwenden wir STL C++. Insbesondere für die Arbeit mit Saiten WCHAR, verbinden Sie die Bibliothek wstring.
Um den Wert einer Methode zu speichern Prüfen, in der Klasse definieren CAddInNative im Geltungsbereich privates Feld:
Stringtest1;
Um String-Parameter zwischen 1C:Enterprise und einer externen Komponente zu übertragen, wird der 1C:Enterprise-Speichermanager verwendet. Schauen wir uns seine Arbeit genauer an. Verwenden Sie die Funktionen, um Speicher zuzuweisen bzw. freizugeben AllocMemory und Freier Speicher, in der Datei definiert MemoryManager.h. Wenn es notwendig ist, einen Zeichenfolgenparameter an das 1C: Enterprise-System zu übergeben, muss die externe Komponente dafür Speicher zuweisen, indem sie die Funktion aufruft AllocMemory. Sein Prototyp sieht so aus:
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
wo pSpeicher- die Adresse des Zeigers, in dem die Adresse des zugewiesenen Speichers platziert wird,
ulCountByte- die Größe des zugewiesenen Speicherbereichs.
Ein Beispiel für die Zuweisung von Speicher für eine Zeichenfolge:
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. Es nimmt einen wstring-String als Parameter. 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)); val -> pstrVal = t1; val -> strLen = str.length(); gib wahr zurück ;)
Dann der entsprechende case-Abschnitt der switch-Anweisung der Methode GetPropVal wird die Form annehmen:
case ePropTest1: wstring_to_p(test1, pvarPropVal); Unterbrechung;
Methode SetPropVal:
Fall ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR) return false; test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); Unterbrechung;
Um die zweite Eigenschaft zu implementieren, definieren wir ein Klassenfeld CaddInNative
uint8_t last_type;
in der wir den Typ des zuletzt übergebenen Werts speichern. Fügen Sie dazu der Methode CaddInNative::SetPropVal den folgenden Befehl 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, die für die vorgesehene Aufgabe erforderlich ist.
Lassen Sie uns die Leistung der vorgenommenen Änderungen überprüfen.
Dazu präsentieren wir Aussehen Konfiguration 1C zur Ansicht:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.CheckType = 1; Report(String(DemoComp.TypeCheck)); DemoComp.Test = "Vasya"; Report(String(DemoComp.Test)); DemoComp.Test = "Petya"; Report(String(DemoComp.Test)); Report(String(DemoComp.TypeCheck)); EndProzedur
Als Ergebnis des Starts erhalten wir eine Reihe von Nachrichten:
3
Wasja
Petja
22

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

Erweiterung der Methodenliste

Eine Aufgabe:
  1. Erweitern Sie die Funktionalität der externen Komponente um folgende Funktionalität:
  2. Erfahren Sie, wie Sie externe Komponentenmethoden implementieren
  3. Methodenfunktion hinzufügen Funktion1, die zwei Zeichenfolgen ("Parameter1" und "Parameter2") als Parameter akzeptiert. Als Ergebnis wird eine Zeichenfolge der Form zurückgegeben: „Check. Parameter1, Parameter2"
  4. Überprüfen Sie, ob die vorgenommenen Änderungen funktionieren.

Um die Methoden der zu erstellenden Komponente zu definieren, muss der Entwickler die folgenden Methoden im Code der AddInNative-Bibliothek implementieren:
GetNMethods, FindMethod, GetMethodName
Um die Anzahl der 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 es keine Methode mit dieser Nummer gibt oder keine Parameter hat, wird 0 zurückgegeben
GetParamDefValue
Gibt den Standardwert des angegebenen Parameters der angegebenen Methode zurück
HasRetVal
Gibt ein Flag zurück, das die Methode mit dem angegebenen Rückgabewert ordinal hat: true für Methoden mit Rückgabewert and FALSCH sonst
CallAsProc
FALSCH, tritt ein Laufzeitfehler auf und die Ausführung des 1C: Enterprise-Moduls wird angehalten. Speicher für das Array von Parametern wird von 1C: Enterprise zugewiesen und freigegeben.
CallAsFunc
Führt die Methode mit der angegebenen Ordinalzahl aus. Wenn die Methode zurückkehrt FALSCH, tritt ein Laufzeitfehler auf und die Ausführung des 1C: Enterprise-Moduls wird angehalten. Der Speicher für das Array von Parametern wird von 1C: Enterprise zugewiesen. Wenn der Rückgabewert vom Typ Zeichenfolge oder Binärdaten ist, weist die Komponente Speicher mit der Funktion zu AllocMemory Speichermanager, schreibt dort Daten und speichert diese Adresse im entsprechenden Feld der Struktur. 1С: Das Unternehmen wird diesen Speicher durch Anruf freigeben Freier Speicher.
Eine vollständige Beschreibung der Methoden, einschließlich der Liste der Parameter, ist in der auf der ITS-Diskette mitgelieferten Dokumentation ausführlich beschrieben.
Betrachten Sie 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 implement switch geben abhängig von den übergebenen Parametern und der Anwendungslogik den erforderlichen Wert zurück. Methode HasRetVal in seinem Code enthält nur eine Liste von Methoden, die ein Ergebnis zurückgeben können. Für sie kehrt es zurück Stimmt. Für alle Stahlmethoden zurück FALSCH.
Methoden CallAsProc und CallAsFunc enthalten direkt ausführbaren Methodencode.
Um eine Methode hinzuzufügen, die nur als Funktion aufgerufen werden kann, müssen Sie folgende Änderungen im Quellcode der externen Komponente vornehmen:
  1. Methodennamen zu Arrays hinzufügen g_Methodennamen und g_Methodennamen(Datei AddInNative.cpp)
  2. Fügen Sie der Aufzählung Methods (file AddInNative.h)
  3. Nehmen Sie Änderungen am Funktionscode vor GetNParams nach Programmlogik
  4. Nehmen Sie ggf. Änderungen am Code der Methode vor GetParamDefValue wenn Sie die Standardwerte der Methodenparameter verwenden möchten.
  5. Nehmen Sie Änderungen an einer Funktion vor HasRetVal
  6. Nehmen Sie Änderungen an der Logik der Funktionen vor CallAsProc oder CallAsFunc, indem Sie dort den direkt ausführbaren Code der Methode platzieren
Lassen Sie uns Arrays bringen g_Methodennamen und g_Methodennamen, sowie Aufzählung Methoden zur Ansicht:
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"LoadImage", L"Test");

Enum-Methoden (eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // Immer zuletzt);
Lassen Sie uns die Funktion bearbeiten Holen Sie sich NProps damit es die Anzahl der Parameter der Methode "Test" zurückgibt:
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( Fall eMethShowInStatusLine: Rückgabe 1; Fall eMethLoadPicture: Rückgabe 1; Fall eMethTest: Rückgabe 2; Standard: Rückgabe 0; ) Rückgabe 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 eMethStartTimer: case eMethStopTimer: case eMethTestTimer: case eMethTestTimer: case : case / Es gibt standardmäßig keine Parameterwerte break; default: return false; ) return false; )
Dank der hinzugefügten Zeile
Fall eMethTest:
in Abwesenheit eines oder mehrerer Argumente haben die entsprechenden Parameter einen leeren Wert ( VTYPE_LEER). Wenn Sie einen Standardwert für einen Parameter benötigen, müssen Sie ihn im Abschnitt angeben eMethTest Funktion Switch-Anweisung CAddInNative::GetParamDefValue.
Da die Methode "Test" 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; default: 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) gibt false zurück; s1 = (paParams) -> pwstrVal; s2 = (paParams+1) -> pwstrVal; wstring_to_p(std::wstring(s1+s2), pvarRetValue); ret = true ; Pause; ) Rückkehr ret; )
Lassen Sie uns die Komponente kompilieren und den Konfigurationscode in das Formular bringen:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); Lane = DemoComp.Test ("Hallo", "Welt!"); Benachrichtigen (trans); EndProzedur
Nach dem Start der Konfiguration erhalten wir eine Nachricht: „Hello, World!“, was darauf hinweist, dass die Methode erfolgreich funktioniert hat.

Timer

Eine Aufgabe:
  1. Studieren Sie die Implementierung des Timers in der Demo VK
  2. Ändern Sie die Methode "StartTimer", indem Sie die Möglichkeit hinzufügen, die Parameter des Timer-Intervalls (in Millisekunden) zu übergeben.
  3. Überprüfen Sie, ob die 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 angeben, an Ihr Programm gesendet.
Um einen Timer zu erstellen, verwenden Sie die Funktion SetTimer:
UINT SetTimer(HWND hWnd, // Fensterhandle UINT nIDevent, // Timer-ID (Nummer) UINT nElapse, // Verzögerung TIMERPROC lpTimerFunc); // Funktionszeiger
Das Betriebssystem sendet eine Nachricht WM_TIMER an das Programm mit dem im Argument angegebenen Intervall nVergehen(in Millisekunden). Im letzten Parameter können Sie eine Funktion angeben, die jedes Mal ausgeführt wird, wenn der Timer ausgelöst wird. Der Header dieser Funktion sollte wie folgt aussehen (der Name kann beliebig sein):
void __stdcall TimerProc (HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
Betrachten Sie die Implementierung des Timers in der Demo-VK.
Da wir den Prozess der Entwicklung einer externen Komponente für die Windows-Betriebssystemfamilie erwägen, werden wir die Implementierung des Timers in anderen nicht berücksichtigen Betriebssysteme. Insbesondere für GNU/Linux OS unterscheidet sich die Implementierung in der Syntax der Funktion SetTimer und TimerProz.
Die Methode wird im ausführbaren Code aufgerufen SetTimer, an die die Funktion übergeben wird MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
Die ID des erstellten Timers wird in eine Variable gestellt m_uiTimer damit Sie es später ausschalten können.
Funktion MyTimerProc folgendermaßen:
VOID CALLBACK MyTimerProc(HWND hwnd, // Handle des Fensters für Timer-Meldungen UINT uMsg, // WM_TIMER-Meldung UINT idEvent, // Timer-Kennung 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); wstime löschen; ) )
Die Essenz der Funktion besteht darin, dass die Methode aufgerufen wird ExternesEreignis, das eine Nachricht an das 1C: Enterprise-System sendet.
Um die Funktionalität des Verfahrens zu erweitern StartTimer machen wir folgendes:
Ändern des Methodencodes GetNParams damit es für die Methode ist eMethStartTimer Rückgabewert 1:
Fall eMethStartTimer: Rückgabe 1;
Hier ist der Methodencode CallAsProc zur Ansicht:
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 im Modul der verwalteten Anwendung der Konfiguration den Code:
var DemoComp; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); EndProzedur
Nach dem Start der Konfiguration erhält das Programm im Abstand von 2 Sekunden Meldungen, die den korrekten Betrieb des Timers anzeigen.

Interaktion mit dem 1C: Enterprise-System

Um zwischen der externen Komponente und dem 1C:Enterprise-System zu interagieren, werden Methoden der in der Datei beschriebenen IAddInDefBase-Klasse verwendet AddInDefBase.h. Wir listen die am häufigsten verwendeten auf:
Generierung von Fehlermeldungen
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 Beschreibung finden Sie auf der ITS-Diskette)
Quelle- Fehlerquelle
Beschr- Fehlerbeschreibung
Senden einer Nachricht an das 1C: Enterprise-System
virtual bool ADDIN_API ExternalEvent (WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wszQuelle- Nachrichtenquelle
wszNachricht- Nachrichtentext
wszDaten- übermittelte Daten
Das Abfangen der Nachricht erfolgt durch die Prozedur HandlingExternalEvent
Registrierung einer externen Komponente im 1C:Enterprise-System
virtual bool ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wszProfilname- Komponentenname.
Diese Methoden sind für die vollständige Interaktion von VK und 1C ausreichend. 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 gegebenenfalls die Methoden der externen Komponente zum Senden aufruft Daten zurück.

tVariant-Datentyp

Beim Datenaustausch zwischen einer 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-Diskette 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; bVal; char chVal; wchar_t wchVal; DATE date; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NAME_2/*iface*/; _ANONYMOUS_STRUCT struct ( char* pstr2_t Lint3 ; / /count of bytes ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //count of symbol ) __VARIANT_NAME_4/*wstr*/; ) __VARIANT_NAME_1; uint32_t cbElements; //Dimension für ein eindimensionales Array in pvarVal TYPEVAR vt; );
Art der tVariante ist eine Struktur, die Folgendes umfasst:
  • Mischung (Vereinigung), die direkt zur Datenspeicherung bestimmt ist
  • Datentypkennung
Im Allgemeinen arbeitet man mit Variablen vom Typ tVariante erfolgt nach folgendem Algorithmus:
  1. Bestimmen des aktuell in einer Variablen gespeicherten Datentyps
  2. Zugriff auf das entsprechende Feld des Gemisches, für den direkten Zugriff auf Daten
Geben Sie die Verwendung ein tVariante vereinfacht das Zusammenspiel des 1C: Enterprise-Systems und einer externen Komponente erheblich

Anwendung

Das Verzeichnis "Beispiele" enthält Beispiele für den Artikel
Beispiele/1 - Führen Sie die Demo-Komponente aus
Beispiele/2 - Demo zur Eigenschaftslistenerweiterung
Beispiele/3 - Demonstration der Methodenlistenerweiterung
Jedes Verzeichnis enthält ein VS 2008-Projekt und eine vorgefertigte 1C-Konfiguration.

Programmierer haben häufig Probleme beim Anschließen externer Komponenten (z. B. Treiber für kommerzielle Geräte), wenn Benutzer mit 1C arbeiten, indem sie über das Terminal eine Verbindung zum Server herstellen.

Gleichzeitig sehen Nutzer beispielsweise das in der Ankündigung des Artikels präsentierte Bild.

Während Sie von lokalen Computern aus arbeiten, gibt es keine Probleme beim Anschluss externer Komponenten.

Womit ist es verbunden? Dies liegt daran, dass Benutzer, wenn sie über den Terminalserver arbeiten, weniger Rechte haben, als wenn sie auf dem lokalen Computer arbeiten.

Dies lässt sich leicht überprüfen, wenn Sie sich unter einem Konto mit Administratorrechten am Terminalserver anmelden.

Der Grund für diesen Unterschied ist, 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 Zweig der Systemregistrierung HKEY_CLASSES_ROOT.

In Veröffentlichungen zum Thema Anschluss externer Komponenten im Endgerät werden verschiedene Methoden zur Lösung dieses Problems angeboten.

Zum Beispiel diese:

1. Führen Sie 1C zum ersten Mal mit Administratorrechten aus.

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

2. Geben Sie normalen Benutzern des Terminals das Recht, in den Zweig der Systemregistrierung zu schreiben HKEY_CLASSES_ROOT.

Unzureichend "fortgeschrittene" Benutzer sollten dies nicht tun, da es sonst zu Problemen kommen kann.

3. Mit verschiedenen "Gadgets" registrieren Sie VK im Namen eines Benutzers mit vollen Rechten.

Es ist auch nicht gut zu essen.

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

Ich biete meine Lösung für dieses Problem an. Meiner Meinung nach - schlicht und schön, bisher nicht beim Infostart angeboten.

Bei der Untersuchung dieses Problems fragte ich mich: Warum versucht 1C überhaupt, VK auf einem neuen Weg zu registrieren? Schließlich ist es bereits im System registriert.

Es stellte sich heraus, dass in typischen 1C-Konfigurationen (z. B. "Trade Management") die folgende Syntax der globalen Kontextmethode verwendet wird ConnectExternalComponent() :

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

Wie Sie sehen können, ist der VK-Treiber über das Layout „DriverATOLScannerBarcode“ 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 HKEY_CLASSES_ROOT-Registrierungszweig entlang dieses Pfads zu registrieren.

Auf dem Terminal haben normale Benutzer keine Rechte, diesen Registrierungszweig zu ändern, daher wird die Komponente für sie nicht verbunden.

Jetzt geht es darum, wie man aus dieser Situation herauskommt.

Globale Kontextmethode ConnectExternalComponent() hat mehrere Syntaxoptionen. Das werden wir verwenden.

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 64-Bit-Betriebssysteme.

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

Variante 1:

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

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

Option 2:

ProgID = "AddIn.Scanner45";

Externe Komponente verbinden (ProgID);

DriverObject = Neu (ProgID);

Meiner Meinung nach ist Option 2 vorzuziehen.

Gleichzeitig versucht 1C nicht, den VC entlang eines neuen Pfads in der Registrierung neu zu registrieren, und somit sind alle Probleme gelöst.

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

Beispielsweise ist es nicht möglich, eine Komponente neu zu schreiben, wenn Sie nicht ihr Autor sind und es einfach keine Quellcodes gibt. Oder wenn die einfachsten Typen, die von der nativen API-Technologie unterstützt werden (Zahl, Zeichenfolge, Boolean, Datum), für den Betrieb nicht ausreichen.

Bei der Arbeit mit der Dateibasis gibt es keine besonderen Probleme. Die geplante Aufgabe wird im Hintergrundprozess eines normalen Benutzers aufgerufen. Daher stehen ihm Client-Anrufe zur Verfügung. Es gibt keinen Client-Kontext in der Server-Datenbank, wenn eine geplante Aufgabe gestartet wird, also der Aufruf ConnectExternalComponent() Nicht verfügbar.

In diesem Fall können Sie die Komponente auf dem Client aufrufen. Dazu reicht es aus, eine weitere 1C-Sitzung über die geplante Aufgabe auf dem Server zu starten, in der die erforderlichen Aktionen auf dem Client ausgeführt werden. Vergessen Sie nicht, die Laufsitzung später zu beenden.

Nehmen wir an, dass wir in unserer geplanten Aufgabe einen Bericht generieren und speichern, der die externe COM-Komponente NameDeclension.dll verwendet, um den vollständigen Namen abzulehnen. Auf der Dateibasis funktioniert eine solche geplante Aufgabe korrekt, aber sie funktioniert nicht auf der Serverkomponente.

Um das Problem zu beheben, fügen wir dem Modul für geplante Aufgaben eine Prozedur hinzu, die eine weitere Sitzung im Servermodus startet und darin einen Aufruf zur Berichterstellung auf dem Client von der externen Verarbeitung ausführt.

#If Client Then Procedure ExecuteFormationAndSavingReport() Export If ConnectExternalComponent("CommonLayout.NAMEDECL","Cl",ExternalComponentType.COM) Then Component = New ("AddIn.Cl.NameDeclension"); //Hier ist der Code zum Generieren und Speichern des Berichts: ElseJoinLogRecord("RegTask", LogLogLevel.Error, "Failed to connect the external component on the client"); EndIf; Ende der Prozedur #Andernfalls Prozedur ExecuteFormationAndSavingReport() Export ExecuteOperationOnClient("RegularTasks.ExecuteFormationAndSavingReport()"); EndProcedure-Prozedur PerformOperationOnClient(ParameterToExecute) ExportUserName = ""; Benutzerpasswort = ""; PathToExternalProcessing = "c:/temp/Autostart.epf"; Zitat = """"; VerzeichnisBIN = VerzeichnisProgramm(); PathToConfiguration = InfoBase ConnectionString(); Konfigurationspfad = StrReplace (Konfigurationspfad, Zitat, Zitat + Zitat); StartString = Quote + Bin Directory + „1cv8.exe“ + Quote + „ENTERPRISE“ + „/IBConnectionString“ + Quote + ConfigurationPath + Quote + „/N“ + Quote + Benutzername + Quote + „/P“ + Quote + UserPassword + Zitat + " /Execute " + Zitat + PathToExternalProcessing + Zitat + " /C " + Zitat + ParameterToExecute + Zitat; StartApplication(StartString); EndProcedure #EndIf

Externer Verarbeitungscode, der einfach bewirkt, dass der Clientkontext den erforderlichen Bericht aus dem Modul für geplante Jobs druckt, und die Sitzung beendet, nachdem der Bericht generiert wurde.

Versuch auszuführen (StartupParameter); Ausnahme EndTry; ShutdownSystem (Falsch);

Der Komfort der Lösung besteht darin, dass es beim Einrichten geplanter Aufgaben keine Rolle spielt, in welchem ​​​​Modus die Aufgabe gestartet wird. Wenn es sich bei der Datenbank um eine Dateidatenbank handelt, wird die erforderliche Prozedur sofort gestartet. Wenn die Datenbank serverseitig ist und beim Start kein Clientkontext vorhanden ist, wird eine neue Sitzung initialisiert und die Prozedur funktioniert im Kontext des Clients ordnungsgemäß.

Code für eine typische Anwendung. Theoretisch wird es in einem gemanagten ganz ähnlich funktionieren.

p.s. Dieser Ansatz kann auch verwendet werden, um beliebige Client-Prozeduren in geplanten Jobs auszuführen.

DIE KLINGEL

Es gibt diejenigen, die diese Nachricht vor Ihnen gelesen haben.
Abonnieren Sie, um die neuesten Artikel zu erhalten.
Email
Name
Familien-oder Nachname
Wie möchten Sie The Bell lesen?
Kein Spam