amagovpt / autenticacao.gov

Middleware Oficial de Identificação Eletrónica em Portugal - Cartão de Cidadão, da Chave Móvel Digital e Sistema de Certificação de atributos profissionais
https://www.autenticacao.gov.pt
European Union Public License 1.2
164 stars 33 forks source link

Incompatibilidade com Crystal Reports 13.0.3500 ou superior #81

Open renatoleitedacosta opened 3 years ago

renatoleitedacosta commented 3 years ago

Boa tarde,

Tenho um projeto c# v4.5 que esta a usar crystal reports 13.0.4000.0 e adicionei a dll pteidlib_dotnet, quando executo PTEID_ReaderSet.initSDK(); para depois proceder leitura do SNS. esta a devolver o erro:

O inicializador de tipo para 'pt.portugal.eid.pteidlib_dotNetPINVOKE' accionou uma excepção. em pt.portugal.eid.pteidlib_dotNetPINVOKE.PTEID_ReaderSet_initSDK__SWIG_1() em pt.portugal.eid.PTEID_ReaderSet.initSDK()

Isto só acontece quando utilizo primeiro o crystal. se executar primeiro o código da leitura do cartão depois dá erro na impressão pelo crystal.

Alguma sugestão/ajuda.

Obrigado

msdevpt commented 2 years ago

Também temos o mesmo problema reportado com as libs 13.0.3500 ou superior. Nas libs 13.0.2000 do Crystal Report Runtime 13.0.8 funciona corretamente mas claro gostaria-mos de puder usar versões mais recentes sem este problema.

Ficamos a aguardar o vosso feedback. Obrigado

ACamposPT commented 2 years ago

Olá boa tarde,

Não conhecemos a razão da incompatibilidade com as novas versões do Crystal Reports. Suspeitamos de algum problema relacionado com DLL's incompatíveis entre o Crystal Report e o autenticação.gov.

Na equipa não temos conhecimento sobre Crystal Reports e a sua utilização.

No sentido de tentar chegar ao problema e posteriormente encontrar uma solução, vocês conseguem partilhar um projecto Visual Studio, em que seja possível reproduzir o problema? O projecto deve ser o mais pequeno possível, com uma funcionalidade minima.

Para testar usaremos a versão do Crystal Reports disponível em:

https://www.crystalreports.com/download/

msdevpt commented 2 years ago

Boa tarde, segue em anexo projecto com exemplo se clicar em ler o cartão cidadão deverá ler sem problemas e depois clicar em imprimir deve dar erro. Se repetir mas em ordem inversa deve pedir para imprimir e depois deve dar erro a ler o cartão do cidadão.

Report de exemplo está incluido no ficheiro em anexo nas pastas Debug e Release.

Cartão do cidadão usei a versão 3.6.1

Crystal Reports 13.0.30 32bit https://origin.softwaredownloads.sap.com/public/file/0020000000195592021

Crystal Reports 13.0.30 64bit https://origin.softwaredownloads.sap.com/public/file/0020000000195602021

Atualizado hoje 16/09 removi ref. que não eram necessárias WindowsFormsDemo.zip

Obrigado

agrr commented 2 years ago

Boa tarde,

Desde já agradecemos ao @mskbpt, com esse projeto de exemplo é possível confirmar que a execução do código de leitura do CC causa um erro posterior no código de impressão do report usando o Crystal Reports.

Isto deve-se a uma DLL nativa que por coincidência é uma dependência tanto do Crystal Reports como da nossa lib pteidlib_dotnet: xerces-c_3_2.dll.

No caso do CR 13.0.30 (64-bit) esta DLL é instalada em: C:\Program Files (x86)\SAP BusinessObjects\Crystal Reports for .NET Framework 4.0\Common\SAP BusinessObjects Enterprise XI 4.0\win64_x64

Acontece que as versões desta DLL são incompatíveis e devido aos nomes serem exatamente iguais a aplicação não pode carregar ambas as versões em simultâneo.

A integração terá que ser feita com a atual versão do SDK autenticação.gov usando uma aplicação auxiliar para fazer a leitura do CC. Sugerimos um interface textual capturando o texto escrito no stdout desta aplicação.

O código de leitura do CC seria executado numa aplicação de consola a que chamamos CCReaderUtil Deste modo esta seria a nova versão da função ReadCard() do projeto WindowsFormsDemo partilhado pelo @mskbpt:

private bool ReadCard()
 {
            var processStartInfo = new ProcessStartInfo
            {
                FileName = @"CCReaderUtil.exe",
                RedirectStandardOutput = true,
                CreateNoWindow = true,
                UseShellExecute = false
            };
            var process = Process.Start(processStartInfo);
            var output = process.StandardOutput.ReadToEnd();
            process.WaitForExit();

            if (output.StartsWith("E"))
            {
                Console.WriteLine("CCReader returned error: " + output);
                return false;
            }
            else
            {
                Console.WriteLine("CCReader returned card data: " + output);
                return true;
            }
 }

Esta seria uma versão básica da aplicação auxiliar CCReaderUtil com a possibilidade de indicar erro de leitura através de um prefixo "E:" na string retornada. Para retornar uma estrutura de dados complexa seria uma boa ideia usar texto estruturado em formato JSON ou CSV por exemplo.

using System;
using pt.portugal.eid;

namespace CCReaderUtil
{
    class Program
    {
        static void Main(string[] args)
        {
            try
            {
                PTEID_ReaderContext context;
                PTEID_ReaderSet readerSet;
                readerSet = PTEID_ReaderSet.instance();
                if (readerSet.readerCount() == 0)
                {
                    Console.WriteLine("E: no card reader found!");
                }
                for (uint i = 0; i < readerSet.readerCount(); i++)
                {
                    context = readerSet.getReaderByNum(i);
                    if (context.isCardPresent())
                    {
                        PTEID_EIDCard card = context.getEIDCard();
                        PTEID_EId eid = card.getID();
                        Console.WriteLine("NIC: " + eid.getCivilianIdNumber());
                    }
                    else
                    {
                        Console.WriteLine("E: card not present in reader!");
                    }
                }
            }
            catch (PTEID_Exception ex)
            {
                Console.WriteLine("E: PTEID_Exception: " + ex.GetMessage());
            }
            PTEID_ReaderSet.releaseSDK();
        }
    }
}
msdevpt commented 2 years ago

Bom dia, desde já obrigado pela rápida resposta. Tem previsto alguma correção relativo a este problema numa futura versão?

Obrigado

agrr commented 2 years ago

Ainda não foi implementada nenhuma solução para este caso mas o que pretendemos é prevenir em geral a possibilidade de conflitos de DLLs com aplicações clientes do SDK. Existem 2 soluções possíveis que teremos de estudar e implementar: usar apenas "static libs" para as dependências do SDK ou renomear as respetivas DLLs.

Podemos prever que deverá ser corrigido depois da versão 3.7.0 que será lançada ainda este mês.

renatoleitedacosta commented 2 years ago

Bom dia, Pelo que tive a verificar a nova versão 3.7.0 ainda não corrige este problema que existe com o crystal. Alguma previsão para a resolução ?

Obrigado

valtersoares commented 1 year ago

Boa tarde. Temos a nova versão 3.8.0 com o Crystal Report 13.0.4000 e o problema subsiste. Quando instancio primeiro o CC (Dim ReaderSet as PTEID_ReaderSet = PTEID_ReaderSet.instance()) o CR dá o seguinte erro: "Falha ao obter class factory de COM do componente com CLSID {F734A321-8381-4FFD-A614-139E8906DC83} devido ao seguinte erro: 8007007f . Impossível localizar o procedimento especificado."

Quando instancio o CR primeiro ( Dim report As New reportDummy()) "_O inicializador de tipo para 'pt.portugal.eid.pteidlib_dotNetPINVOKE' accionou uma excepção. em pt.portugal.eid.pteidlib_dotNetPINVOKE.PTEID_ReaderSet_instance() em pt.portugal.eid.PTEIDReaderSet.instance"

agrr commented 1 year ago

Bom dia, Validem por favor a versão 3.9.0 do Autenticação.gov publicada ontem. Deverá resolver esta incompatibilidade com o Crystal Reports devido a conflito de DLLs.