이 소식을 먼저 읽은 사람들이 있습니다.
최신 기사를 받으려면 구독하십시오.
이메일
이름
당신은 벨을 어떻게 읽고 싶습니까?
스팸 없음

질문: 1С 8.3에서 Linux(Ubuntu x64)용 C++의 외부 네이티브 API 구성 요소


나는 VK를 쓰고 있는데 우분투에서 1에 연결할 수 없습니다. 1의 예도 연결되지 않습니다. 그래서 그것에 대한 질문:

1) 기사에 제공된 VNCOMPS 예제에서 VK를 연결하려고 합니다.

(링크는 맨 끝에서 찾을 수 있습니다: "복사").
내부적으로 NativeApi 프로젝트에는 makefile이 있습니다. 그것으로 나는 Ununtu에 .so 라이브러리를 구축합니다.
그러나 "외부 구성 요소 연결"에서 1이 시작됩니다.
마찬가지로, "build.sh"(프로젝트 루트에서)를 사용하여 빌드하는 경우.

makefile 자체에서 플래그를 m32에서 m64로 변경합니다. 1c 및 x64 시스템 자체. (m32 매개 변수를 사용하면 어쨌든 선택하지 않습니다)
다음은 1C 8.3에서 VK를 호출하는 예입니다.
연결 완료 = 외부 구성 요소 연결("/home/alexeyubuntux64-20gb/Documents/VNCOMP83/example/NativeAPI/AddInNative.so", "AddInNative", ExternalComponentType.Native); 이 주제에 대한 기사가 있습니다.
그러나 내가 볼 수 있는 한 이러한 모든 사항은 VNCOMPS 예제에서 이미 고려되고 수정되었습니다.

그러나 사실 컴파일 매개변수의 비즈니스입니다. MB 32비트 외부 구성 요소는 일반적으로 32비트 1c에 연결되지만 Ubuntu x64 1c enterprise83 8.3.5-1486 amd64에 배포했습니다. 그리고 나는 그녀에게 VK를 데리러 가고 싶다.

누구든지이 문제를 해결하는 방법을 알고 있습니까?
VNCOMPS 예제가 작동해야 하지만 빌드 매개변수를 수정해야 하거나 테스트 중인 플랫폼 자체가 올바르지 않습니다.

대답:흥미롭게도 Java로 외부 구성 요소를 작성할 수 있습니까?

질문: 외부 구성 요소(네이티브)가 연결되지 않았습니다.


64비트 및 32비트 시스템에 대해 ITS를 사용하여 예제를 컴파일했습니다.

나는 다음과 같이 연결합니다.
ConnectionResult = ConnectExternalComponent(CDLLPath, "Comp", ExternalComponentType.Native); 한 PC는 연결되고 다른 PC는 연결되지 않습니다. OS의 차이가 있습니다. 연결이 가는 곳에 Win7이 있고 Win10이 없습니다. 동시에 표준 구성 요소는 내 구성 요소가 작동하지 않는 PC에서 작동합니다.

다른 플랫폼에서 테스트되었습니다(8.3.4.482, 8.3.6.2100, 8.3.11.2700, 8.3.12.1412).

연결되지 않는 이유를 이해하는 방법은 무엇입니까?

대답: vc_redist가 잊지 않았습니까?

질문: 1C8 및 기본 유형의 외부 구성 요소


안녕하세요.
BP 3.0.50.12의 구성과 UniServerAuto를 사용하여 Scales-Soft에서 계량을 구현하려는 바람이 있습니다.
개발자는 Windows 32 및 64용 Native 구성 요소를 컴파일하여 maifest 파일과 함께 아카이브에 넣었습니다. 1C에 대한 예도 있습니다. 무게를 계산하는 방법입니다. 그 안에 바이너리 데이터가 있는 레이아웃의 도움으로 이 아카이브가 내가 이해한 대로 표시됩니다. 예제에서는 모든 것이 정상입니다. 구성 요소가 설치되고 연결된 다음 연결이 설정되고 무게가 읽힙니다.
그러나 자신을 1C로 옮기기 시작하자마자 무게가 읽히지 않습니다. 모든 것이 간단하게 쓰여진 것 같지만 갈퀴가 어디에 있는지 이해하지 못합니다.
누가 약간의 시간을 가질 것인가 - 도와주세요. 한 눈으로 살펴보십시오. 아마도 해결책이 표면에 있지만 잘못된 곳에서 어딘가를 걷고 있고 잘못된 일을하고 있습니다. 저는 네이티브 기술로 작업한 적이 없습니다...

그리고 첨부 파일에 내 처리 텍스트가 있습니다

대답:

글쎄, 나는 몇 가지 소식이 있습니다 ...
어느 지점에서 실패하기 시작하는지 단계별로 살펴보기 시작했습니다. 이를 위해 빈 데이터베이스를 만들고 명령으로 처리했습니다. 공급자의 예와 유추하여 레이아웃을 새 conf로 옮겼습니다. 두 번째로 작동합니다. 저것들. 처음에는 아니요, 두 번째는 그렇습니다. 이것은 다른 절차에 따라 구성 요소와 개체의 연결을 분리하는 처리 과정에서 여전히 필요하다는 아이디어를 촉발했습니다.
그런 다음 레이아웃 연결을 사용하여 데이터베이스로 전송했습니다. 작동합니다. 헐 벌써 좋다.... 하지만 구성을 바꾸지 않고 했으면 좋겠으니 넘어가자

처리에 레이아웃을 추가하려고 합니다. 크기가 10kb에서 3mb로 즉시 증가하고 상당한 속도 저하가 나타납니다. 적합하지 않습니다. dll을 통해 구성 요소를 연결하는 방향으로 파고들기 시작합니다. 저것들. 기본적으로 시작한 곳과 동일합니다. 그러나 하나의 "BUT"이 있습니다. 사용자 폴더에서 dll 이름으로 검색하여 이 dll이 1C에 등록된 dll이 추가된 위치에 있다는 것을 알았습니다.
C:\Users\USER\AppData\Roaming\1C\1cv8\ExtCompT
따라서 dll의 전체 경로를 사용할 필요가 없습니다. 간단히 이름을 쓰면 됩니다.
ConnectExternalComponent("Add1CUniServerAuto32.dll", "UniServerAuto", ExternalComponentType.Native);

나는 시도 ... 등록시 맹세하지만 칭량 결과를 반환합니다. dll이 이미 등록되어 있는 것으로 나타났습니다. 즉, 연결하기만 하면 됩니다. 나는 그것을 제거하고 모든 것이 작동합니다.
나는 요약한다:
1. When Opening 절차에서 계량 처리에서 외부 부품의 연결과 물체에 대한 연결을 추가했습니다.
2. 내가 작성하지 않은 dll의 경로, 이름만 표시했습니다.

이제 앉아서 생각합니다. dll이 1C에 언제 설치되었습니까? 소프트웨어 설치 시? 거의... 이 dll의 개발자 설정을 실행할 때 폼을 열었을 때 어디에 설정되어 있나요? 잘은 모르겠지만 저랑 가까운 것 같군요... 어떻게 생각하세요?
둘째, 새로운 장소에서 동일한 터미널을 설치해야 하는 경우 모든 것이 작동하려면 어떻게 해야 할까요? 소프트웨어를 완전히 설치하고 공급업체의 구성을 실행하여 작업을 확인한 다음 (이론적으로) 내 처리가 작동해야 합니까? 뭔가 좀 복잡한데... 아니면 내 처리에 소프트웨어를 설치한 후 InstallExternalComponent를 한 번 하시겠습니까?

이에 대한 귀하의 생각을 듣고 싶습니다...

질문: 외부 component.dll


좋은 하루 되세요.
질문입니다.
1C 7.7에서 잘 작동하는 dll 구성 요소
1s 8.1에서 전혀 부팅하고 싶지 않습니다 ...
C:\Program Files\1cv81\bin\cache1c.dll에 붙여넣었습니다.
regsvr32 "C:\Program Files\1cv81\bin\cache1c.dll"을 사용하여 등록을 시도했습니다.
문제없이 등록되었습니다.
액세스하려고 하면 다음과 같은 오류 메시지가 나타납니다.

외부 구성 요소를 로드하는 동안 오류가 발생했습니다! 캐시1c.dll
절차 ButtonClick(Button) 실행 외부 구성 요소 로드 시도( "C:\Program Files\1cv81\bin\cache1c.dll"); 예외 보고서( "외부 구성 요소를 로드하는 동안 오류가 발생했습니다!"+ "cache1c.dll"); 시도 종료; 시도 // 구성 요소 개체를 가져옵니다. // m = 신규("cache1c.GTMcmd" ); m = 새로운 COMObject("cache1c.GTMcmd" ); 예외 보고서(); 시도 종료; 종료 절차

대답:불가능할 정도로 평범한...
호출 사이에 일시 중지(밀리초)를 유지해야 합니다...
프로시저 ButtonExecuteClick(Button) Attempt // 구성 요소 개체를 가져옵니다. m = 새로운 COMObject("cache1c.GTMcmd" ); 예외 보고서( "외부 구성 요소 개체를 만들 수 없습니다"); 시도 종료; m.RemoteHost = "192.168.1.101" ; m. 원격 포트 = 6330; m.연결(); m.pause(100); ...... 등
1s 7.7의 경우 - 이것은 필요하지 않으며 순환이 더 빠른 것으로 나타났습니다.

질문: 1C 서버가 있는 외부 구성 요소의 작업 ...


안녕하세요,

C ++로 작성된 외부 구성 요소가 있으며, 그 작업은 외부 데이터베이스에서 정보를 수신하고 쿼리 결과를 1C의 값 테이블 형식으로 반환하는 것입니다.
현재 시점에서 값의 테이블을 형성하기 위해 IDispatch* pBackConnection 인터페이스가 사용되며, 이는 Init() 함수에서 매개변수로 수신됩니다. 또한 1C 함수를 사용하여 값 테이블을 만들고 채우고 CallAsFunc(...)의 두 번째 매개 변수로 반환합니다.
문제는 1C 씬 클라이언트로의 전환과 함께 시작되었습니다. 서버 측에서 외부 구성 요소는 실제로 시작되지 않습니다. 클라이언트 측에서 실행할 수 있지만 모두 목발처럼 보이고 1C의 일반적인 "클라이언트-서버" 논리에서 벗어납니다. 예를 들어 클라이언트는 값 테이블이 무엇인지, "전역"변수 문제, 세션 등을 이해하지 못합니다.
NativeAPI는 이와 관련하여 훨씬 더 잘립니다.
탬버린으로 춤을 추면 1C 서버에서 외부 구성 요소를 시작할 수 있었지만 pBackConnection에서 Invoke를 호출하려고 할 때까지 작업이 발생합니다. 64비트 버전의 서버 8.2는 시간 초과 시 중단될 때까지 무언가를 시도하고, 32비트 버전(VK도 당연히 32비트임)은 즉시 중단됩니다.
1C 서버는 이 작동 모드를 제공하지 않는다고 가정합니다.
따라서 질문이 발생합니다. 일시적입니까 아니면 1C의 논리가이 작업 계획의 폐지로 축소됩니까? 이런 식으로 1C(가치표)의 내부 구조를 만드는 것이 불가능하다면, 원칙적으로 C로 만들려고 시도하기 위해 시스템 수준에서 값의 표가 무엇인지에 대한 설명이 있습니까? +, 채우고 반환 매개 변수로 1C를 입력하시겠습니까? 적어도 파헤쳐야 할 방향은 알고 싶습니다.

고맙습니다.

대답:

당신은 한 가지를 쓰고 다른 것을 의미합니다.
1C 환경에서 다른 세션에서 볼 수 있는 변수를 선언하는 것이 지금은 불가능하지 않으며 이전에도 불가능했습니다. 다른 세션은 물리적으로 다른 프로세스입니다.
세션은 데이터베이스 연결 세션입니다. 사용자 세션. 아니면 당신 자신의 무언가와 이 개념을 넣습니까?

하나의 세션 내에서 세션 모듈에서 변수를 선언하는 것이 가능했고 이제는 가능합니다. 이 변수는 세션 내에서 다른 위치에서 살고 볼 수 있습니다. 실제로는 4개가 있습니다.
- 세션 모듈;
- 일반 애플리케이션 모듈;
- 관리되는 애플리케이션 모듈;
- 외부 연결 모듈.

물론 컨텍스트에 대해 기억해야 합니다. 서버 컨텍스트는 클라이언트 측에서 직접 액세스할 수 없으며 그 반대의 경우도 마찬가지입니다.

일반적으로 1C 아키텍처는 데이터 교환이 계속되도록 제공합니다.
- 매개변수/프로시저/기능 반환을 통해
- 소위 세션 매개변수를 사용하여(객체가 될 수 없으며 실제로 팔레트에서 볼 수 있음).

폼의 테이블은 ... 개체 테이블과 연결되어 있습니까(예: 처리)? 아니면. 그렇다면 서버(&AtServer)에서도 사용할 수 있고 편집할 수 있습니다....

그리고 예, ValueTable은 클라이언트 측의 UV에서 사용할 수 없습니다. 음, 1C는 그렇게 결정했습니다.

어서 해봐요! 여기서는 Excel과 함께 작동하고 FSO 및 기타 모든 것과 함께 작동하지만 여기서는 작동하지 않습니다. 오류를 잡아서 분석하세요....

시도
...
당신의 행동
...
예외
str = 설명오류();
시도 종료;

최신 하드웨어 기능을 사용하면 이것은 논쟁의 여지가 전혀 없습니다.

순전히 당신의 개인적인 의견입니다. 현실과 관련이 없습니다. 어떤 식 으로든 아닙니다. 다시 한 번 반복하지만 1C는 COM과 잘 작동합니다. in-proc 및 out-proc 모두.

업로드하고 VK에 적용하는 코드를 제공하십시오.

그건 그렇고, VK ... 귀하의 경우 COM 또는 기본 API입니까?
COM인 경우 regsvr32를 통해 등록합니다. 그러면 비트 심도 문제를 어떻게 "해결"합니까?

질문: 외부 구성 요소 설치


외부 구성 요소를 설치하는 방법을 알려주세요. 다음 코드를 실행하면 오류가 발생합니다. 레이아웃에서 NameDecl.dll 찾기

SetExternalComponent("GeneralLayout.Layout") 시도; 예외 EndTry ;
오류: 플러그인 설치에 실패했습니다!

대답: ()
ConnectExternalComponent("GeneralLayout.Layout", "NameDecl", ExternalComponentType.Native)는 FALSE를 반환합니다.
New("AddIn.NameDecl.CNameDecl", Undefined) = (()): 유형이 정의되지 않음(AddIn.NameDecl.NameDecl)

질문: 기본 dll이 1s 8.1에 연결되어 있지 않습니다(fptrwin32_fz54_9_11_0_5549.dll).


여보세요.
1C는 fdd 1.05용 온라인 금전 등록기 atol용 dll을 업데이트했습니다(fptrwin32_fz54_9_11_0_5549.dll 유지 관리 처리에 포함됨).
나는 오래된 1C 8.1을 가지고 있습니다. 8.2와 달리 8.2와 같은 방식으로 외부기기와의 작업을 지원하지 않기 때문에 먼저 윈도우에서 dll을 등록한 후 1C에만 연결하면 되는건가요?

ProgID = "AddIn.IntegrationComponent.ATOL_KKT_1C83_V9"; LoadExternalComponent("C:\fptrwin32_fz54_9_11_0_5549.dll"); ConnectExternalComponent(ProgID); 드라이버 = 신규(ProgID);

그러나 이전 처리는 "technology"com에 작성되었으며 새로운 네이티브입니다. 따라서 등록할 때 regsvr32에서 오류가 발생합니다.
모듈이 로드되었지만 DllRegisterServer 진입점을 찾을 수 없습니다. 그리고 이 파일이 올바른 dll 또는 OCX 파일인지 확인하는 것이 좋습니다.
비슷한 상황에 처한 사람, 어떻게 빠져나왔나요? 비슷한 문제가 7.7에 있을 것임을 이해합니다.
코드 8.2:

레이아웃 = GetLayout("통합 구성 요소"); 주소 = PlaceInTempStorage(레이아웃); ConnectExternalComponent(주소, "통합 구성 요소", ExternalComponentType.Native); 드라이버 = New("AddIn.IntegrationComponent.ATOL_KKT_1C83_V9");

1C 8.2:
외부 구성 요소 연결(<Местоположение>, <Имя>, <Тип>)
1C 8.1:
외부 구성 요소 연결(<Идентификатор объекта>)
옵션:
<Идентификатор объекта>(필수의)
유형: 문자열. 외부 구성 요소 개체의 ProgID(프로그래매틱 식별자)입니다. 시스템 등록 데이터베이스(레지스트리)의 정보와 일치해야 합니다.
설명:
외부 구성 요소 개체를 1C:Enterprise에 연결합니다.
1C:Enterprise 서버에서는 사용할 수 없습니다. 외부 접속 모듈에서는 사용하지 않습니다.
메모:
외부 구성 요소는 1C:Enterprise 7.7 구성 요소와 호환됩니다.
예시:
시도
ConnectExternalComponent("AddinObject.Scanner");
alert("바코드 스캐너 구성 요소가 로드되었습니다.");
예외
alert("바코드 스캐너 구성 요소가 로드되지 않았습니다.");
시도 종료

이 dll을 8.1에 연결할 수 있는 방법이 있습니까?

고맙습니다!

대답:

나는 또한 최근에이 문제가 발생했습니다. 1s의 이후 버전으로 변환할 수 없습니다. 이 구성이 작동하는 dll이 작동을 멈추고 1c가 오류와 함께 떨어졌습니다.
문제는 다음과 같은 방법으로 해결되었습니다.
구성 요소 초기화를 처리하는 빈 데이터베이스 8.3을 만든 다음 COM 연결을 통해 8.1에서 이전에 만든 데이터베이스에 액세스하고 구성 요소를 초기화했습니다. 그런 다음 이미 8.1에서 이 구성 요소의 메서드를 호출했습니다.
물론 이것은 목발이지만 아직 다른 탈출구를 찾지 못했습니다(

코드 예 8.3:
렘 드라이버 내보내기;
함수 ConnectionComponentsCCP() 내보내기
시도

레이아웃 = GetLayout("통합 구성 요소");
주소 = PlaceInTempStorage(레이아웃);
ConnectExternalComponent(주소, "통합 구성 요소", ExternalComponentType.Native);
드라이버 = New("AddIn.IntegrationComponent.SMDrvFR1C20");
결과 = 참;​

예외

결과 = 거짓;​

시도 종료;
반환 결과
EndFunctions

코드 예제 8.1

함수 CreateDriverObject(드라이버) 내보내기

결과 = 참;

시도

ConnectionString="파일="""데이터베이스 경로""";
ComObject= 새 COMObject("V83.ComConnector");
연결 = ComObject.Connect(ConnectionString);

처리 = Connect.Processing.ConnectingExternalComponent.Create();
ConnectionResult = Processing.ConnectingKKT Components();
결과가 연결되면
드라이버 = 처리.드라이버;
EndIf;​

예외
해보시거나 비슷한 문제 경험하신 분 설명 부탁드립니다. 간단한 예원칙 그 자체. 외부 구성 요소의 연결로 모든 것이 명확한 것 같습니다.

// 값 테이블을 채우는 예 TK.Clear(); 요청 = 새 요청; Query.Text = "선택 | 명명법 링크 방법 명명법 | FROM | Directory.Nomenclature AS 명명법", QueryResult = Query.Execute(), Sampling = QueryResult.Select(), While Sampling.Next() 루프 Str = TK.Add(), FillPropertyValues(Pr, Sampling), EndCycle,
이 예제를 통해 일반적으로 코드의 어떤 부분이 제거되는지 설명해 주시겠습니까? 요청이 있는 부분을 제거하는 것이 논리적이지만 플랫폼을 우회하여 외부 구성 요소에서 외부 구성 요소의 데이터베이스에 어떻게 액세스할 수 있습니까? 텍스트는 무의미합니다. 또는 표 부분의 형성 자체를 제거하십시오. 이에 대한 경험을 공유해 주십시오.

대답:그리고 "비호환성"이라는 단어는 항상 "나쁜"이라는 단어를 의미합니까? 네, 제 스타일을 "1C: 자연에 존재하는 이 스크립팅 엔진의 최악의 프로그래밍(문학 언어로 번역됨)"이라고 하면 제 스타일인 것 같습니다. 그러면 분명히 이 짐승을 확인하려는 사람들이 있을 것입니다. 그리고 그것은 고전처럼 보입니다. "나는 Pasternak을 읽지 않았지만 그와 완전히 동의하지 않습니다!" :)

질문: 1s 8.3.6 및 Win8에서 외부 구성 요소 연결


자체 작성 구성에 vk_rs232.dll ExternalComponent를 연결해야 합니다. regsvr32.exe를 통해 등록된 것과 같습니다. "구성 요소가 등록되었지만 방화벽에 문제가 있습니다."라는 메시지를 받았기 때문에 "그런 것 같습니다." 메시지의 전반부에 의지하여 1초 안에 코드를 작성합니다
AfterConnection = New NotificationDescription("AfterConnectionVK",ThisForm); StartExternalComponentInstallation(,"C:\Controller\vk_rs232.dll"); StartConnectingExternalComponent(AfterConnecting,"C:\Controller\vk_rs232.dll","DLL_Scales");
그리고 나는 오류를 얻는다.
"외부 구성 요소 설치에 실패했습니다! 사용 중인 클라이언트 응용 프로그램의 구성 요소가 누락되었을 수 있습니다!".

그리고 지금 나는 이해하지 못한다.
1. 구성 요소가 레지스트리에 등록되지 않았을 수 있습니다. 어떻게 확인할 수 있습니까?
2. Win8에서는 32비트가 있지만 "버전"이 작동하지 않을 수 있습니다.
3. 어쩌면 1 자체가 너무 새롭다. 따라서이 dll을 사용할 수 없습니까?
4. 글쎄, 그것은 진부하다 - 내가 뭔가를 잘못 쓰고 있습니다.

대답:그리고 이 모든 것이 나를 다음 문제로 이끌었습니다. VneshComp가 설치되었습니다. 이제 연결해야 합니다. 그리고 여기에 두 가지 옵션이 있습니다.
ConnectExternalComponent("C:\Controller\vk_rs232.dll","스케일")
ConnectExternalComponent("GeneralLayout.Layout","Scales")

구문 옵션: 이름 및 위치별

통사론:

외부 구성 요소 연결(<Местоположение>, <Имя>, <Тип>)
옵션:

<Местоположение>(필수의)

유형: 문자열.
외부 구성 요소의 위치입니다.
위치를 사용할 수 있습니다.
ZIP 아카이브가 아닌 파일 시스템의 외부 구성 요소 파일에 대한 경로(웹 클라이언트에서는 사용할 수 없음).
성명바이너리 데이터 또는 ZIP 아카이브를 저장하는 레이아웃;
GetNaviLink와 유사한 이진 데이터 또는 ZIP 아카이브 형식의 외부 구성 요소에 대한 URL입니다.
<Имя>(필수의)

유형: 문자열.
플러그형 외부 구성 요소의 기호 이름입니다.
이름은 기본 제공 언어의 명명 규칙을 따라야 합니다.
<Тип>(선택 과목)

유형: ExternalComponent 유형.
연결할 외부 구성 요소의 유형입니다.
구성 요소가 ZIP 아카이브에 패키지된 경우에는 사용되지 않습니다.
방법 변형에 대한 설명:

Native 및 COM 기술을 사용하여 만든 구성 요소를 연결합니다.
구성 요소는 정보 베이스 또는 구성 레이아웃에 바이너리 데이터 또는 ZIP 아카이브로 저장할 수 있습니다.
"씬 클라이언트" 및 "웹 클라이언트" 실행 모드의 경우 외부 구성 요소 설치 방법을 사용하여 구성 요소를 미리 설치해야 합니다.
구문 옵션: ID별

통사론:

외부 구성 요소 연결(<ИдентификаторОбъекта>)
옵션:

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

유형: 문자열.
MS Windows 레지스트리의 ProgID(Programmatic Identifier) ​​형식의 외부 구성 요소 개체 식별자(예: "AddIn.Scanner").
시스템 등록 데이터베이스(레지스트리)의 정보와 일치해야 합니다.
방법 변형에 대한 설명:

구성 요소는 COM 기술을 사용하여 구현하고 MS Windows 레지스트리에 등록해야 합니다.
이러한 구성 요소는 1C:Enterprise 7.7 구성 요소와 호환됩니다.
주목! 이 방법의 변형은 서버와 외부 연결에서 작동하지 않습니다.
반환 값:

유형: 부울.
True - 연결에 성공했습니다.
설명:

외부 구성 요소를 1C:Enterprise에 연결합니다.
외부 구성 요소는 정보 베이스 또는 구성 레이아웃에 ZIP 아카이브, 바이너리 데이터 또는 파일 시스템 파일로 저장할 수 있습니다.
씬 클라이언트 및 웹 클라이언트에서 작업할 때 구성 요소가 사전 설치되어 있어야 합니다.

유효성:

씬 클라이언트, 웹 클라이언트, 서버, 외부 연결.
메모:

외부 구성 요소는 기본 API 또는 COM 기술을 사용하여 구현할 수 있습니다. COM 기술을 사용하여 만든 구성 요소는 1C:Enterprise 7.7 구성 요소와 호환됩니다.
웹 클라이언트는 아카이브에 압축된 정보 베이스의 구성 요소에서만 작동할 수 있습니다.
씬 클라이언트는 아카이브에 포함된 정보 베이스의 구성 요소 및 파일 시스템에 있는 구성 요소와 함께 작동할 수 있습니다.
씩 클라이언트는 구성 요소에 대한 모든 스토리지 옵션과 함께 작동할 수 있습니다. 이 경우 InstallExternalComponent 방식으로 Component를 설치하면 설치된 Component를 그대로 사용하고, 설치되어 있지 않으면 연결 시 해당 Component를 수신하게 됩니다.
서버는 모든 구성 요소와 함께 작동할 수 있습니다. 구성 요소는 서버 세션에 대해 캐시됩니다.
예시:

If ConnectExternalComponent("AddinObject.Scanner") 다음
alert("바코드 스캐너 구성 요소가 로드되었습니다.");
그렇지 않으면
alert("바코드 스캐너 구성 요소가 로드되지 않았습니다.");
EndIf;

  • 지도 시간

소개

이 기사에서는 1C:Enterprise 시스템에서 외부 구성 요소가 작동하는 방식에 대한 아이디어를 제공합니다.
파일 버전의 작업으로 Windows 운영 체제에서 실행되는 1C:Enterprise 버전 8.2 시스템의 외부 구성 요소를 개발하는 프로세스가 표시됩니다. 이 옵션은 중소기업용으로 설계된 대부분의 솔루션에 사용됩니다. VC는 C++ 프로그래밍 언어로 구현됩니다.

외부 구성 요소 "1C: Enterprise"

"1C: Enterprise"는 확장 가능한 시스템입니다. 확장용 기능시스템은 외부 구성 요소(VC)를 사용합니다. 개발자의 관점에서 VC는 속성과 메서드가 있는 외부 개체이며 1C:Enterprise 시스템에서 처리할 이벤트를 생성할 수도 있습니다.
외부 구성 요소는 1C: Enterprise에 내장된 프로그래밍 언어를 사용하여 구현하기 어렵거나 심지어 불가능한 작업 클래스를 해결하는 데 사용할 수 있습니다. 특히 이 클래스에는 예를 들어 특정 하드웨어와 함께 작동하기 위해 운영 체제와의 낮은 수준의 상호 작용이 필요한 작업이 포함됩니다.
1C:Enterprise 시스템은 외부 구성 요소를 생성하기 위해 두 가지 기술을 사용합니다.
  • 네이티브 API 사용
  • COM 기술을 사용하여
위의 두 기술 간의 제한 사항을 감안할 때 그 차이는 미미하므로 Native API를 사용한 VK 개발을 고려해 보겠습니다. 필요한 경우 구현된 개발을 COM 기술을 사용하는 VC 개발에 적용할 수 있으며 약간의 수정을 가하여 파일 작동 모드 이외의 다른 작동 옵션이 ​​있는 1C: Enterprise 시스템에서 사용하도록 적용할 수 있습니다.
VK 구조
1C:Enterprise 시스템의 외부 구성 요소는 DLL 라이브러리로 제공됩니다. 라이브러리 코드는 IComponentBase 파생 클래스를 설명합니다. 생성되는 클래스에서 외부 컴포넌트의 기능을 구현하는 메소드를 정의해야 합니다. 재정의된 메서드는 나중에 자료를 제시하는 과정에서 더 자세히 설명합니다.

데모 VK 시작

작업:
  1. ITS 구독과 함께 제공되고 1C에서 외부 구성 요소 메커니즘의 주요 기능을 시연하도록 설계된 외부 구성 요소를 조립합니다.
  2. 데모 구성 요소를 1C 구성에 연결
  3. 선언된 함수가 올바르게 작동하는지 확인
편집
데모 VC는 "/VNCOMP82/example/NativeAPI" 디렉토리의 ITS 구독 디스크에 있습니다.
Microsoft Visual Studio 2008을 사용하여 데모 VK를 어셈블합니다. 이 제품의 다른 버전은 사용된 Visual Studio 프로젝트 형식을 지원하지 않습니다.


AddInNative 프로젝트를 엽니다. 프로젝트 설정에서 프로젝트를 빌드하는 데 필요한 헤더 파일과 디렉터리를 연결합니다. 기본적으로 디렉토리의 ITS 디스크에 있습니다. /VNCOMP82/포함.
빌드 결과는 파일입니다. /bind/AddInNative.dll. 이것은 1C 구성에 연결하기 위한 컴파일된 라이브러리입니다.
VK를 1C 구성에 연결
빈 구성 1C를 만들어 보겠습니다.
다음은 관리되는 애플리케이션 모듈에 대한 코드입니다.
var 데모컴프; SystemStartup Procedure() ConnectExternalComponent("...\bind\AddInNative.dll", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); 종료 절차
1C 구성을 시작할 때 오류가 보고되지 않으면 VK가 성공적으로 연결된 것입니다.
위의 코드를 실행한 결과, 구성의 전역 가시성에 개체가 나타납니다. 데모컴프외부 Bean 코드에 정의된 속성 및 메서드가 있는 입니다.
임베디드 기능 시연
데모 VK의 성능을 확인해보자. 이를 위해 일부 속성을 설정 및 읽고, 일부 VK 메서드를 호출하고, VK 메시지도 수신 및 처리해 보겠습니다.
ITS 디스크에 제공된 설명서에는 데모 VC의 다음 기능이 나와 있습니다.
  1. 구성 요소 개체 상태 관리
    행동 양식: 켜다, 끄다
    속성: 포함
  2. 타이머 제어
    1초마다 구성 요소는 매개 변수가 있는 1C: Enterprise 시스템에 메시지를 보냅니다. 요소, 시간제 노동자및 시스템 클록 카운터 스트링.
    행동 양식: 시작 타이머, 정지 타이머
    속성: 타이머가 있다
  3. 방법 ShowInStatusLine, 매개변수로 메소드에 전달된 텍스트를 상태 표시줄에 표시합니다.
  4. 방법 이미지 업로드. 지정된 파일에서 이미지를 로드하고 이진 데이터로 1C:Enterprise 시스템에 전송합니다.
이러한 기능이 작동하는지 확인합시다. 이를 위해 다음 코드를 실행합니다.
var 데모컴프; SystemStart() 프로시저 ConnectExternalComponent(...); DemoComp = New("AddIn.DemoVK.AddInNativeExtension"); DemoComp.Disable(); 알림(DemoComp. 활성화됨); DemoComp.Enable(); 알림(DemoComp. 활성화됨); DemoComp.StartTimer(); EndProcedure ProcedureExternalEventHandler(소스, 이벤트, 데이터) 보고서(소스 + " " + 이벤트 + " " + 데이터); 종료 절차
구성을 실행한 결과가 이미지에 표시됩니다.


메소드 호출 결과는 "메시지" 패널에 표시됩니다. DemoComp.Disable()그리고 Demo.Comp.Enable(). 같은 패널의 다음 줄에는 VK에서 받은 메시지 처리 결과가 포함되어 있습니다. 원천, 이벤트그리고 데이터각기.

임의의 외부 구성 요소 이름

작업: 외부 구성 요소의 이름을 임의의 이름으로 변경합니다.
이전 섹션에서는 식별자를 사용했습니다. 네이티브 확장 추가, 그 의미는 설명되지 않았습니다. 이 경우 네이티브 확장 추가확장자의 이름입니다.
VC 코드는 메소드를 정의합니다. RegisterExtensionAs, 1C: Enterprise 시스템에 이름을 반환합니다. 이는 시스템에 VC를 후속 등록하는 데 필요합니다. 외부 구성 요소의 본질을 어느 정도 드러내는 식별자를 지정하는 것이 좋습니다.
다음은 메서드의 전체 코드입니다. RegisterExtensionAs확장 이름이 변경된 경우:
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); return true; ) return false; )
위의 예에서 VK 이름은 일부 이름. 그런 다음 VK를 연결할 때 새 이름을 지정해야 합니다.
DemoComp = New("AddIn.DemoVK.SomeName");

VK 속성 목록 확장

작업:
  1. VC 속성 구현 연구
  2. 문자열 유형의 읽기-쓰기 속성 추가
  3. 속성 마지막 집합의 데이터 유형을 저장하는 읽기/쓰기 문자열 유형 속성을 추가합니다. 속성 값을 설정할 때 아무 작업도 수행되지 않습니다.

생성되는 구성 요소의 속성을 정의하려면 개발자가 AddInNative.cpp 라이브러리의 코드에서 다음 메서드를 구현해야 합니다.
GetNProps
이 확장의 속성 수를 반환하고 속성이 없으면 0을 반환합니다.
FindProp
매개변수에 이름이 전달된 속성의 서수를 반환합니다.
GetPropName
서수와 전달된 언어 ID로 속성 이름을 반환합니다.
GetPropVal
지정된 서수가 있는 속성 값을 반환합니다.
SetPropVal
지정된 서수로 속성 값을 설정합니다.
IsPropReadable
지정된 서수가 있는 속성의 가독성 플래그를 반환합니다.
IsPropWritable
지정된 시퀀스 번호가 있는 속성 쓰기 가능성 플래그를 반환합니다.


위의 클래스 메소드의 구현을 고려하십시오. CAddIn네이티브.
데모 VC는 2가지 속성을 정의합니다. 포함그리고 타이머가 있다 (사용 가능그리고 IsTimerPresent).
라이브러리 코드의 전역 범위에는 두 개의 배열이 정의되어 있습니다.
정적 wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent"); static wchar_t *g_PropNamesRu = (L"활성화됨", L"타이머가 있습니다");
속성의 러시아어 및 영어 이름을 저장합니다. 헤더 파일에서 AddInNative.h열거형은 다음과 같이 정의됩니다.
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropLast // 항상 마지막 );
ePropIsEnabled그리고 ePropIsTimerPresent, 각각 값이 0과 1인 속성의 서수를 의미 있는 식별자로 바꾸는 데 사용됩니다. 값이 2인 ePropLast는 속성 수를 가져오는 데 사용됩니다(GetNProps 메서드 사용). 이러한 이름은 구성 요소의 코드 내에서만 사용되며 외부에서 액세스할 수 없습니다.
FindProp 및 GetPropName 메서드는 배열을 검색합니다. g_PropNames그리고 g_PropNames.
라이브러리 모듈의 필드 값을 저장하기 위해 CAddInNative 클래스에는 구성 요소의 속성 값을 저장하는 속성이 있습니다. 행동 양식 GetPropVal그리고 SetPropVal각각 이러한 속성의 값을 반환하고 설정합니다.
행동 양식 IsPropReadable그리고 IsPropWritable그리고 돌아오다 진실또는 거짓, 응용 프로그램 논리에 따라 속성의 전달된 서수에 따라 달라집니다.
사용자 정의 속성을 추가하려면:

  1. 배열에 추가할 속성 이름 추가 g_PropNames그리고 g_PropNames(파일 AddInNative.cpp)
  2. 열거에 소품(파일 AddInNative.h) 전에 ePropLast추가할 속성을 고유하게 식별하는 이름 추가
  3. 속성값을 저장하기 위한 메모리 정리(해당 값을 저장하는 컴포넌트 모듈 필드 생성)
  4. 방법 변경 GetPropVal그리고 SetPropVal이전 단계에서 할당된 메모리와 상호 작용하기 위해
  5. 애플리케이션 로직에 따라 메소드 변경 IsPropReadable그리고 IsPropWritable
1, 2, 5번 항목은 설명이 필요 없습니다. 이러한 단계의 구현에 대한 자세한 내용은 기사의 부록에서 찾을 수 있습니다.
테스트 속성의 이름을 지정해 보겠습니다. 테스트그리고 유형 확인각기. 그런 다음 단락 1의 결과로 다음을 얻습니다.
정적 wchar_t *g_PropNames = (L"IsEnabled", L"IsTimerPresent", L"Test", L"TestType"); 정적 wchar_t *g_PropNamesRu = (L"활성화됨", L"HasTimer", L"테스트", L"체크 유형");
열거 소품다음과 같이 보일 것입니다:
enum Props ( ePropIsEnabled = 0, ePropIsTimerPresent, ePropTest1, ePropTest2, ePropLast // 항상 마지막 );
코드를 크게 단순화하기 위해 STL C++를 사용합니다. 특히 문자열 작업의 경우 WCHAR, 라이브러리 연결 wstring.
메소드의 값을 저장하려면 테스트, 클래스에서 정의 CAddIn네이티브범위 개인 필드:
문자열 테스트1;
1C:Enterprise와 외부 구성 요소 간에 문자열 매개변수를 전송하기 위해 1C:Enterprise 메모리 관리자가 사용됩니다. 그의 작품을 자세히 살펴보자. 각각 메모리를 할당하고 해제하려면 다음 함수를 사용하십시오. 할당 메모리그리고 프리메모리, 파일에 정의 메모리매니저.h. 1C: Enterprise 시스템에 문자열 매개변수를 전달해야 하는 경우 외부 구성요소는 함수를 호출하여 이에 대한 메모리를 할당해야 합니다. 할당 메모리. 프로토타입은 다음과 같습니다.
virtual bool ADDIN_API AllocMemory (void** pMemory, unsigned long ulCountByte) = 0;
어디 피메모리- 할당된 메모리의 주소가 위치할 포인터의 주소,
ulCountByte- 할당된 메모리 영역의 크기.
문자열에 대한 메모리 할당의 예:
WCHAR_T *t1 = NULL, *테스트 = L"TEST_STRING"; int iActualSize = wcslen(test1)+1; m_iMemory->AllocMemory((void**)&t1, iActualSize * sizeof(WCHAR_T)); ::convToShortWchar(&t1, test1, iActualSize);
문자열 데이터 유형 작업의 편의를 위해 함수를 설명합니다. wstring_to_p. 매개변수로 wstring 문자열을 사용합니다. 함수의 결과는 채워진 구조입니다. t변형. 기능 코드:
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(), 참을 반환; )
그런 다음 메서드의 switch 문의 해당 사례 섹션 GetPropVal다음과 같은 형식을 취합니다.
케이스 ePropTest1: wstring_to_p(test1, pvarPropVal); 부서지다;
방법 SetPropVal:
case ePropTest1: if (TV_VT(varPropVal) != VTYPE_PWSTR)은 false를 반환합니다. test1 = std::wstring((wchar_t*)(varPropVal -> pstrVal)); 부서지다;
두 번째 속성을 구현하기 위해 클래스 필드를 정의합니다. 캐드인네이티브
uint8_t last_type;
마지막으로 전달된 값의 유형을 저장할 것입니다. 이렇게 하려면 CaddInNative::SetPropVal 메서드에 다음 명령을 추가합니다.
last_type = TV_VT(varPropVal);
이제 두 번째 속성의 값 읽기를 요청할 때 값을 반환합니다. last_type, 지정된 작업에 필요한 것입니다.
변경 사항의 성능을 확인해 보겠습니다.
이를 위해 우리는 모습보기에 구성 1C:
var 데모컴프; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.CheckType = 1; 보고서(문자열(DemoComp.TypeCheck)); DemoComp.Test = "바샤"; 보고서(문자열(DemoComp.Test)); DemoComp.Test = "페티야"; 보고서(문자열(DemoComp.Test)); 보고서(문자열(DemoComp.TypeCheck)); 종료 절차
출시 결과 다음과 같은 일련의 메시지가 표시됩니다.
3
바샤
페트야
22

두 번째 및 세 번째 메시지는 이전 단계에서 설정한 속성을 읽은 결과입니다. 첫 번째 및 두 번째 메시지에는 마지막 속성 집합의 유형 코드가 포함됩니다. 3은 정수 값에 해당하고 22는 문자열 값에 해당합니다. 유형 및 해당 코드의 대응은 파일에 설정됩니다. 유형.h, ITS 디스크에 있습니다.

메소드 목록 확장

작업:
  1. 다음 기능을 사용하여 외부 구성 요소의 기능을 확장합니다.
  2. 외부 구성 요소 메서드를 구현하는 방법 알아보기
  3. 메소드 기능 추가 기능1, 두 개의 문자열("Parameter1" 및 "Parameter2")을 매개변수로 사용합니다. 결과적으로 다음과 같은 형식의 문자열이 반환됩니다. “Check. 매개변수1, 매개변수2"
  4. 변경 사항이 작동하는지 확인합니다.

생성되는 구성 요소의 메서드를 정의하려면 개발자가 AddInNative 라이브러리의 코드에서 다음 메서드를 구현해야 합니다.
GetNMethods, FindMethod, GetMethodName
방법의 수를 각각 구하고, 방법의 번호와 이름을 검색하도록 설계되었습니다. 속성에 대한 해당 메서드와 유사
GetNParams
지정된 시퀀스 번호가 있는 메서드 매개변수의 수를 반환합니다. 이 번호를 가진 메서드가 없거나 매개변수가 없으면 0을 반환합니다.
GetParamDef값
지정된 메소드의 지정된 매개변수의 기본값을 리턴합니다.
HasRetVal
지정된 반환 값 서수가 있는 메서드가 갖는 플래그를 반환합니다. 반환 값이 있는 메서드의 경우 true 및 거짓그렇지 않으면
CallAsProc
거짓, 런타임 오류가 발생하고 1C: Enterprise 모듈의 실행이 중지됩니다. 매개변수 배열을 위한 메모리는 1C: Enterprise에 의해 할당 및 해제됩니다.
CallAsFunc
지정된 서수로 메서드를 실행합니다. 메서드가 반환되는 경우 거짓, 런타임 오류가 발생하고 1C: Enterprise 모듈의 실행이 중지됩니다. 매개변수 배열의 메모리는 1C: Enterprise에서 할당합니다. 반환 값이 문자열 또는 이진 데이터 유형이면 구성 요소는 함수를 사용하여 메모리를 할당합니다. 할당 메모리메모리 관리자는 거기에 데이터를 쓰고 이 주소를 구조의 해당 필드에 저장합니다. 1С: 기업은 다음을 호출하여 이 메모리를 해제합니다. 프리메모리.
매개변수 목록을 포함한 방법에 대한 전체 설명은 ITS 디스크에 제공된 설명서에 자세히 설명되어 있습니다.
위에서 설명한 방법의 구현을 고려하십시오.
구성 요소 코드에서 두 개의 배열이 정의됩니다.
정적 wchar_t *g_MethodNames = (L"활성화", L"비활성화", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture"); 정적 wchar_t *g_MethodNamesRu = (L"활성화", L"비활성화", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage");
그리고 열거형:
enum 메소드 ( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethLast // 항상 마지막);
그들은 기능에서 사용됩니다 GetNMethods, FindMethod그리고 GetMethodName, 속성 설명과 유사합니다.
행동 양식 GetNParams, GetParamDef값, HasRetVal전달된 매개변수 및 응용 프로그램 논리에 따라 스위치를 구현하고 필요한 값을 반환합니다. 방법 HasRetVal코드에는 결과를 반환할 수 있는 유일한 메서드 목록이 있습니다. 그들을 위해 그것은 반환 진실. 모든 철강 방법 반환 거짓.
행동 양식 CallAsProc그리고 CallAsFunc직접 실행 가능한 메소드 코드를 포함합니다.
함수로만 호출할 수 있는 메서드를 추가하려면 외부 컴포넌트의 소스 코드에서 다음과 같이 변경해야 합니다.
  1. 배열에 메소드 이름 추가 g_MethodNames그리고 g_MethodNames(파일 AddInNative.cpp)
  2. 의미 있는 메서드 식별자를 메서드 열거형(파일 AddInNative.h)
  3. 기능 코드 변경 GetNParams프로그램 논리에 따라
  4. 필요한 경우 메서드 코드를 변경합니다. GetParamDef값메소드 매개변수의 기본값을 사용하려는 경우.
  5. 함수 변경 HasRetVal
  6. 함수의 논리를 변경합니다. CallAsProc또는 CallAsFunc, 메소드의 직접 실행 가능한 코드를 거기에 배치함으로써
배열을 가져오자 g_MethodNames그리고 g_MethodNames, 뿐만 아니라 열거 행동 양식보기에:
static wchar_t *g_MethodNames = (L"활성화", L"비활성화", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadPicture", L"Test"); 정적 wchar_t *g_MethodNamesRu = (L"활성화", L"비활성화", L"ShowInStatusLine", L"StartTimer", L"StopTimer", L"LoadImage", L"테스트");

열거 메서드( eMethEnable = 0, eMethDisable, eMethShowInStatusLine, eMethStartTimer, eMethStopTimer, eMethLoadPicture, eMethTest, eMethLast // 항상 마지막);
함수를 수정하자 GetNProps"Test" 메서드의 매개변수 수를 반환합니다.
long CAddInNative::GetNParams(const long lMethodNum) ( switch(lMethodNum) ( 케이스 eMethShowInStatusLine: return 1; 케이스 eMethLoadPicture: return 1; 케이스 eMethTest: return 2; 기본값: return 0; ) return 0; )
함수를 변경해 보겠습니다.
bool CAddInNative::GetParamDefValue(const long lMethodNum, const long lParamNum, tVariant *pvarParamDefValue) ( ​​​TV_VT(pvarParamDefValue)= VTYPE_EMPTY; switch(lMethodNum): ethMethStart 케이스 eMethEnable: 케이스 eMethLine 케이스 eMethEnable 케이스 : case/기본적으로 매개변수 값이 없습니다. break; default: return false; ) return false; )
추가된 라인 덕분에
케이스 eMethTest:
하나 이상의 인수가 없으면 해당 매개변수는 빈 값( VTYPE_EMPTY). 매개변수의 기본값이 필요한 경우 섹션에서 지정해야 합니다. eMethTest기능 스위치 문 CAddInNative::GetParamDefValue.
"Test" 메서드는 값을 반환할 수 있으므로 함수 코드를 변경해야 합니다. HasRetVal:
bool CAddInNative::HasRetVal(const long lMethodNum) ( switch(lMethodNum) ( 케이스 eMethLoadPicture: 케이스 eMethTest: return true; 기본값: return false; ) return false; )
그리고 메서드의 실행 코드를 함수에 추가합니다. CallAsFunc:
bool CAddInNative::CallAsFunc(const long lMethodNum, tVariant* pvarRetValue, tVariant* paParams, const long lSizeArray) ( ... std::wstring s1, s2; switch(lMethodNum) ( 케이스 eMethLoad ... breakPicture: if (!lSizeArray || !paParams) false 반환, s1 = (paParams) -> pwstrVal, s2 = (paParams+1) -> pwstrVal, wstring_to_p(std::wstring(s1+s2), pvarRetValue), ret = true ; 중단; ) ret 반환; )
구성 요소를 컴파일하고 구성 코드를 다음 형식으로 가져옵니다.
var 데모컴프; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); 레인 = DemoComp.Test("안녕하세요, ", "세계!"); 통지(당); 종료 절차
구성을 시작한 후 "Hello, World!"라는 메시지가 표시되며 이는 메서드가 성공적으로 작동했음을 나타냅니다.

시간제 노동자

작업:
  1. 데모 VK에서 타이머 구현 연구
  2. 매개변수에 타이머 간격(밀리초)을 전달하는 기능을 추가하여 "StartTimer" 메서드를 수정합니다.
  3. 변경 사항이 작동하는지 확인합니다.

WinAPI에서 시간과 함께 작업하려면 메시지를 사용할 수 있습니다. WM_TIMER. 이 메시지는 타이머를 생성할 때 지정한 시간 간격으로 프로그램에 전송됩니다.
타이머를 만들려면 다음 기능을 사용하십시오. 타이머 설정:
UINT SetTimer(HWND hWnd, // 창 핸들 UINT nIDevent, // 타이머 ID(숫자) UINT nElapse, // 지연 TIMERPROC lpTimerFunc); // 함수 포인터
운영 체제에서 메시지를 보냅니다. WM_TIMER인수에 지정된 간격으로 프로그램에 n경과(밀리초 단위). 마지막 매개변수에서 타이머가 실행될 때마다 실행될 함수를 지정할 수 있습니다. 이 함수의 헤더는 다음과 같아야 합니다(이름은 무엇이든 가능).
무효 __stdcall TimerProc(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
데모 VK에서 타이머 구현을 고려하십시오.
우리는 Windows OS 제품군을 위한 외부 구성 요소를 개발하는 과정을 고려하고 있기 때문에 다른 시스템에서 타이머 구현을 고려하지 않습니다. 운영체제. 특히 GNU/Linux OS의 경우 구현은 함수의 구문이 다릅니다. 타이머 설정그리고 TimerProc.
메서드는 실행 코드에서 호출됩니다. 타이머 설정, 함수가 전달되는 대상 MyTimerProc:
m_uiTimer = ::SetTimer(NULL,0,100,(TIMERPROC)MyTimerProc);
생성된 타이머의 ID는 변수에 배치됩니다. m_ui타이머나중에 끌 수 있도록.
기능 MyTimerProc다음과 같이:
VOID CALLBACK MyTimerProc(HWND hwnd, // 타이머 메시지에 대한 창 핸들 UINT uMsg, // WM_TIMER 메시지 UINT idEvent, // 타이머 식별자 DWORD dwTime // 현재 시스템 시간) ( 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 , 무엇, wstime); wstime 삭제; ) )
함수의 본질은 메서드가 호출된다는 것입니다. 외부 이벤트, 1C: Enterprise 시스템에 메시지를 보냅니다.
메서드의 기능을 확장하려면 시작 타이머다음을 수행해 보겠습니다.
메소드 코드 수정 GetNParams방법을 위한 것이므로 eMethStartTimer반환된 값 1:
eMethStartTimer의 경우: 1을 반환합니다.
다음은 메소드 코드입니다. CallAsProc보기에:
케이스 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;
이제 기능을 확인해보자. 이를 위해 구성의 관리되는 애플리케이션 모듈에서 코드를 작성합니다.
var 데모컴프; SystemStartup Procedure() ConnectExternalComponent("...", "DemoVK", ExternalComponentType.Native); DemoComp = New("AddIn.DemoVK.SomeName"); DemoComp.StartTimer(2000); 종료 절차
구성을 시작한 후 프로그램은 타이머의 올바른 작동을 나타내는 2초 간격으로 메시지를 수신합니다.

1C: 엔터프라이즈 시스템과의 상호 작용

외부 구성 요소와 1C:Enterprise 시스템 간의 상호 작용을 위해 파일에 설명된 IAddInDefBase 클래스의 메서드 AddInDefBase.h. 가장 일반적으로 사용되는 목록은 다음과 같습니다.
오류 메시지 생성
virtual bool ADDIN_API AddError(부호 없는 짧은 wcode, const WCHAR_T* 소스, const WCHAR_T* 설명, 긴 코드)
wcode, 암호- 오류 코드(설명이 있는 오류 코드 목록은 ITS 디스크에서 찾을 수 있음)
원천- 오류 소스
설명- 오류 설명
1C: Enterprise 시스템에 메시지 보내기
가상 부울 ADDIN_API ExternalEvent(WCHAR_T* wszSource, WCHAR_T* wszMessage, WCHAR_T* wszData) = 0;
wsz소스- 메시지 소스
wsz메시지- 메시지 텍스트
wsz데이터- 전송된 데이터
메시지 가로채기는 HandlingExternalEvent 프로시저에 의해 수행됩니다.
1C:Enterprise 시스템에 외부 부품 등록
가상 부울 ADDIN_API RegisterProfileAs(WCHAR_T* wszProfileName)
wsz프로필 이름- 구성 요소 이름.
이러한 방법은 VK와 1C의 완전한 상호 작용에 충분합니다. 1C:Enterprise 시스템에서 외부 구성 요소의 데이터를 수신하거나 그 반대의 경우도 마찬가지입니다. 외부 구성 요소는 특수 메시지를 보내고 차례로 1C 시스템에 의해 가로채어 필요한 경우 외부 구성 요소의 메서드를 호출하여 보낼 수 있습니다. 백 데이터.

tVariant 데이터 유형

외부 구성 요소와 1C:Enterprise 시스템 간에 데이터를 교환할 때 tVariant 데이터 유형이 사용됩니다. ITS 디스크에서 찾을 수 있는 types.h 파일에 설명되어 있습니다.
struct _tvariant (_anonymous_union Union (int8_t i8val; int16_t shortval; int32_t lval; int intval; unsigned uintval; int64_t llval; uint8_t ui8val; uint16_t d (pVal; char chVal; wchar_t wchVal; DATE 날짜; IID IDVal; struct _tVariant *pvarVal; struct tm tmVal; _ANONYMOUS_STRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NY_2;USASTRUCT struct ( void* pInterfaceVal; IID InterfaceID; ) __VARIANT_NY_2;__i /바이트 배열 ) __VARIANT_NAME_3/*str*/; _ANONYMOUS_STRUCT struct ( WCHAR_T* pwstrVal; uint32_t wstrLen; //기호 카운트 ) __VARIANT_NAME_4/*wstr*/; ) __VARIANT_NAME_1; _VARIANT_NAME_1; uint32의 경우 pvarVal에서 TYPEVAR vt; );
유형 t변형는 다음을 포함하는 구조입니다.
  • 데이터 저장을 위해 직접 의도된 혼합(결합)
  • 데이터 유형 식별자
일반적으로 유형의 변수로 작업 t변형다음 알고리즘에 따라 발생합니다.
  1. 현재 변수에 저장된 데이터 유형 확인
  2. 데이터에 직접 액세스하기 위해 혼합물의 해당 필드에 액세스
유형 사용법 t변형 1C: Enterprise 시스템과 외부 구성 요소의 상호 작용을 크게 단순화합니다.

신청

"examples" 디렉토리에는 기사에 대한 예제가 포함되어 있습니다.
examples/1 - 데모 구성 요소 실행
examples/2 - 속성 목록 확장 데모
examples/3 - 메소드 목록 확장 데모
각 디렉토리에는 VS 2008 프로젝트와 미리 빌드된 1C 구성이 포함되어 있습니다.

종종 프로그래머는 사용자가 터미널을 통해 서버에 연결하여 1C로 작업할 때 외부 구성 요소(예: 상용 장비 드라이버)를 연결하는 데 문제가 있습니다.

동시에 사용자는 예를 들어 기사 발표에 제시된 그림을 봅니다.

로컬 컴퓨터에서 작업하는 동안 외부 구성 요소를 연결하는 데 문제가 없습니다.

그것은 무엇과 연결되어 있습니까? 이는 사용자가 터미널 서버를 통해 작업할 때 로컬 컴퓨터에서 작업할 때보다 권한이 적기 때문입니다.

관리 권한이 있는 계정으로 터미널 서버에 로그인하면 쉽게 확인할 수 있습니다.

이러한 차이가 나는 이유는 사용자가 정상적인 권한으로 터미널에서 작업할 때 1C가 레지스트리에 외부 구성 요소를 등록할 수 없기 때문입니다. 일반 사용자는 시스템 레지스트리 분기에 대한 쓰기 권한이 없습니다. HKEY_CLASSES_ROOT.

터미널에서 외부 구성 요소를 연결하는 주제에 대한 출판물에서 이 문제를 해결하기 위한 다양한 방법이 제공됩니다.

예를 들면 다음과 같습니다.

1. 1C를 ​​관리자 권한으로 처음 실행합니다.

이 옵션이 항상 작동하는 것은 아닙니다. 이유는 아래에서 설명하겠습니다.

2. 터미널의 일반 사용자에게 시스템 레지스트리 분기에 쓸 수 있는 권한 부여 HKEY_CLASSES_ROOT.

불충분하게 "고급" 사용자는 이 작업을 수행하지 않아야 합니다. 그렇지 않으면 문제가 발생할 수 있습니다.

3. 다양한 "가제트"를 사용하여 모든 권한을 가진 사용자를 대신하여 VK를 등록합니다.

먹는 것도 좋지 않습니다.

그렇다면 이 상황에서 벗어날 수 있는 가장 좋은 방법은 무엇일까요?

나는 이 문제에 대한 나의 해결책을 제시한다. 제 생각에는 간단하고 아름답습니다. 이전에는 infostart에서 제공되지 않았습니다.

이 문제를 조사하면서 1C가 새로운 경로를 따라 VK를 등록하려고 시도하는 이유가 무엇인지 궁금했습니다. 결국, 그것은 이미 시스템에 등록되어 있습니다.

일반적인 1C 구성(예: "Trade Management")에서는 다음과 같은 글로벌 컨텍스트 메서드 구문이 사용되는 것으로 나타났습니다. ConnectExternalComponent() :

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

보시다시피 VK 드라이버는 "Connected Equipment" 디렉토리의 "DriverATOLScannerBarcode" 레이아웃에서 연결됩니다.

그러면 어떻게 됩니까?

1C는 구성 요소를 사용자의 임시 폴더에 저장합니다(예: "C:\Documents and Settings\User\Local Settings\Temp\1032\v8_4_12.tmp").

이 경로를 따라 HKEY_CLASSES_ROOT 레지스트리 분기에 등록하려고 합니다.

터미널에서 일반 사용자는 이 레지스트리 분기를 변경할 수 있는 권한이 없으므로 구성 요소가 연결되지 않습니다.

이제이 상황에서 벗어나는 방법에 대해.

전역 컨텍스트 메서드 ConnectExternalComponent()에는 여러 구문 옵션이 있습니다. 이것이 우리가 사용할 것입니다.

따라서 단계별로:

1. 터미널 서버의 regsvr32.exe 유틸리티를 사용하여 외부 구성 요소를 32비트 OS의 경우 C:\WINDOWS\SYSTEM32 폴더 또는 해당 폴더에 등록합니다. 64비트 OS의 경우 C:\WINDOWS\SYSWOW64.

2. ConnectExternalComponent() 메서드에 대해 두 가지 추가 구문 옵션 중 하나를 사용합니다.

옵션 1:

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

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

옵션 2:

ProgID = "AddIn.Scanner45";

외부 구성 요소 연결(ProgID);

DriverObject = 새로 만들기(ProgID);

제 생각에는 옵션 #2가 더 좋습니다.

동시에 1C는 레지스트리의 새 경로를 따라 VC를 재등록하지 않으므로 모든 문제가 해결됩니다.

그게 다야. 직장에서 행운을 빕니다!

예를 들어, 작성자가 아니고 단순히 소스 코드가 없는 경우 구성 요소를 다시 작성할 수 없습니다. 또는 Native API 기술에서 지원하는 가장 단순한 유형(숫자, 문자열, 부울, 날짜)이 작동에 충분하지 않은 경우.

파일 기반으로 작업할 때 특별한 문제는 없습니다. 예약된 작업은 일반 사용자의 백그라운드 프로세스에서 호출됩니다. 따라서 클라이언트 호출을 사용할 수 있습니다. 예약된 작업이 시작될 때 서버 데이터베이스에 클라이언트 컨텍스트가 없으므로 호출 ConnectExternalComponent()사용할 수 없습니다.

이 경우 클라이언트에서 구성 요소를 호출할 수 있습니다. 이렇게하려면 클라이언트에서 필요한 작업을 수행하기 위해 서버의 예약 된 작업에서 다른 1C 세션을 시작하는 것으로 충분합니다. 나중에 실행 중인 세션을 종료하는 것을 잊지 마십시오.

예약된 작업에서 외부 COM 구성 요소 NameDeclension.dll을 사용하여 전체 이름을 거부하는 보고서를 생성하고 저장한다고 가정해 보겠습니다. 파일 기반에서 이러한 예약된 작업은 올바르게 작동하지만 서버 구성 요소에서는 작동하지 않습니다.

이 문제를 해결하기 위해 서버 모드에서 다른 세션을 시작하고 외부 처리에서 클라이언트에 대한 보고서 생성 호출을 실행하는 프로시저를 예약된 작업 모듈에 추가해 보겠습니다.

#If 클라이언트 then 프로시저 ExecuteFormationAndSavingReport() Export If ConnectExternalComponent("CommonLayout.NAMEDECL","Cl",ExternalComponentType.COM) Then Component = New("AddIn.Cl.NameDeclension"); //보고서 생성 및 저장을 위한 코드 ElseJoinLogRecord("RegTask", LogLogLevel.Error, "Failed to connect the external component on the client"); EndIf; 절차 끝 #Otherwise 절차 ExecuteFormationAndSavingReport() 내보내기 ExecuteOperationOnClient("RegularTasks.ExecuteFormationAndSavingReport()"); EndProcedure 프로시저 PerformOperationOnClient(ParameterToExecute) ExportUserName = ""; 사용자 비밀번호 = ""; PathToExternalProcessing = "c:/temp/Autostart.epf"; 인용 = """"; 디렉토리BIN = 디렉토리프로그램(); PathToConfiguration = InfoBase 연결 문자열(); ConfigurationPath = StrReplace(구성 경로, 견적, 견적 + 견적); StartString = Quote + Bin Directory + "1cv8.exe" + Quote + " ENTERPRISE" + " /IBConnectionString " + Quote + ConfigurationPath + Quote + " /N " + Quote + 사용자 이름 + Quote + " /P " + Quote + UserPassword + Quote + " /Execute " + Quote + PathToExternalProcessing + Quote + " /C " + Quote + ParameterToExecute + Quote; 응용 프로그램 시작(시작 문자열); EndProcedure #EndIf

클라이언트 컨텍스트가 예약된 작업 모듈에서 필요한 보고서를 인쇄하도록 하고 보고서가 생성된 후 세션을 종료하는 외부 처리 코드입니다.

실행 시도(StartupParameter); 예외 EndTry; 시스템 종료(거짓);

솔루션의 편리함은 예약된 작업을 설정할 때 작업이 시작되는 모드가 중요하지 않다는 것입니다. 데이터베이스가 파일인 경우 필요한 절차가 즉시 시작됩니다. 데이터베이스가 서버 측이고 시작 시 클라이언트 컨텍스트가 없는 경우 새 세션이 초기화되고 프로시저는 클라이언트 컨텍스트에서 올바르게 작동합니다.

일반적인 응용 프로그램에 대한 코드입니다. 이론적으로 관리되는 것과 완전히 유사한 방식으로 작동합니다.

추신.또한 이 접근 방식은 예약된 작업에서 모든 클라이언트 프로시저를 실행하는 데 사용할 수 있습니다.

이 소식을 먼저 읽은 사람들이 있습니다.
최신 기사를 받으려면 구독하십시오.
이메일
이름
당신은 벨을 어떻게 읽고 싶습니까?
스팸 없음