Page 1 of 1

CURL

Posted: Mon Mar 25, 2019 2:25 pm
by Verhoven
Cuando ejecuto el siguiente código no hace nada ni WINEXEC, ni MsgRun ni WaitRun.
Pero si lo aplico al NOTEPAD.EXE si funciona.
No lo entiendo

Code: Select all

function curl_enviaFichero(cCertificado,cCertificadoKey,cFicheroAenviar,cFichRespAeat,cHttpAeat)
  local cText4Curl:='curl.exe --connect-timeout 60 -m 60 -S -L --cert ' + cCertificado + ' --key ' + cCertificadoKey +;
                    ' -d @' + cFicheroAenviar + ' -o "' + cFichRespAeat +'" ' +;
                    cHttpAeat
  
  //msginfo(cText4Curl)
  
   // NINGUNO DE LOS SIGUIENTES TRES COMANDOS FUNCIONA.
   WINEXEC(cText4Curl)
   MsgRun( 'Espere...',, { || WINEXEC(cText4Curl)} )
   WaitRun("C:\CLIWIN\AEAT\PruebaALB.BAT",.F.)

   // SIN EMBARGO. NOTEPAD SI LO ARRANCA BIEN Y MUESTRA EL FICHERO
   WaitRun("NOTEPAD.EXE "+cFicheroAenviar)
return
 
Por otro lado, cuando trato de usar las librería de CURL me encuentro con que compila bien enlazando las libcur.lib de FW y la hbcurl.lib de harbour, además de colocar el #include "C:\hb32\contrib\hbcurl\hbcurl.ch" al principio del prg, pero al arrancar el exe generado me da aviso de error de sistema: La ejecución no puede continuar porque no se encontró LIBCURL.DLL.
Y se sale del programa.
Estoy corriendo todo en Windows 10.

Re: CURL

Posted: Mon Mar 25, 2019 3:17 pm
by hmpaquito
Ponle el path a CUrl.Exe.
También "recoge" la salida e inspeccionala.
Algo asi:

Code: Select all

#Define PATH_CURL         AQUI_PONER_EL_PATH_DE_CURL
#Define FILE_CURL_SALIDA  "SalidaCurl.Txt"
 local cText4Curl:=PATH_CURL+ '\'+ 'curl.exe --connect-timeout 60 -m 60 -S -L --cert ' + cCertificado + ' --key ' + cCertificadoKey +;
                    ' -d @' + cFicheroAenviar + ' -o "' + cFichRespAeat +'" ' +;
                    cHttpAeat+ " > "+ FILE_CURL_SALIDA

Re: CURL

Posted: Mon Mar 25, 2019 3:36 pm
by Verhoven
Con el código que sigue genera el archivo salida.txt peero está vacío:

Code: Select all

function CURL_enviaFichero(cCertificado,cCertificadoKey,cFicheroAenviar,cFichRespAeat,cHttpAeat)
 local cText4Curl:='C:\Windows\System32\curl.exe --connect-timeout 60 -m 60 -S -L --cert ' + cCertificado + ' --key ' + cCertificadoKey +;
                    ' -d @' + cFicheroAenviar + ' -o "' + cFichRespAeat +'" ' +;
                    cHttpAeat+ " > "+ "Salida.Txt"
  ShellExecute( 0, 'OPEN', "cmd" ,"/c "+cText4Curl, , 1 )
return
Con los comandos winxec, waitrun y msgrun no hace nada.

He comprobado si era un problema del firewall pero mi aplicación está en la lista de excepciones.
Si esa instrucción que trato de ejecutar desde dentro del prg la grabo en un .bat y la ejecuto desde fuera del programa entonces si la procesa.

Re: CURL

Posted: Mon Mar 25, 2019 5:22 pm
by hmpaquito
Esto está funcionando en producción. Cambia tu segundo 60 por 300 y a más a más, adapta tus variables a este comando, a ver qué tal.

Code: Select all

cCommand:= "\Contabilidad\Sii\Curl.Exe -k --connect-timeout 60 -m 300 -s -S -L --header "Content-Type: text/xml;charset=UT8" --cert "\Contabilidad\Sii\Certificados\Certificado.Pem" --key "\Contabilidad\SiiCertificados\Certificado_key.Pem" --data @\Contabilidad\Error\Nif_Envio_4109979.xml https://www1.agenciatributaria.gob.es/wlpl/BURT-JDIT/ws/VNifV2SOAP --output \Contabilidad\Error\Nif_Respuesta_4109979.xml -v"

WaitRun(cCommand, 0)

Re: CURL

Posted: Mon Mar 25, 2019 9:58 pm
by Verhoven
Debe de ser una de esas sorpresas que el flamante Windows 10 tiene escondidas en lo más intrincado de su naturaleza.

Resulta que si invocamos al curl.exe que trae el propio S.O. en la carpeta C:\Windows\system32, no lo encuentra cuando utilizamos los comandos mencionados en los post anteriores. Pero es más, resulta que, aún estando allí, no lo encuentra siquiera la instrucción file("C:\Windows\System32\curl.exe").
Y si vas a verificar su existencia con el explorardor de windows, como digo, sin embargo allí está.

Para resolver el problema ha bastado con utilizar un curl otro cualquiera de los varios que aparecen instalados en el sistema, como el que viene con XAMPP (si lo teneis instalado) o el propio de harbour ubicado en: C:\hb32\comp\mingw\bin\curl.exe

Pero a quién se le va a ocurrir que pasen estas cosas con windows, que no encuentre un archivo que si está.

Les dejo el código por si a alguien le puede ser de utilidad:

Code: Select all

function CURL_enviaFichero(cCertificado,cCertificadoKey,cFicheroAenviar,cFichRespAeat,cHttpAeat)
 local cCurl    :="C:\hb32\comp\mingw\bin\curl.exe"
 local cOpciones:='--connect-timeout 60 -m 60 -S -L --cert ' + cCertificado + ' --key ' + cCertificadoKey +;
                    ' -d @' + cFicheroAenviar + ' -o "' + cFichRespAeat +'" ' +cHttpAeat+ " > "+ "Salida.Txt"
 
 local nErrorShellExecute:=32  // A partir del valor 32 inclusive es correcto y es el handler asignado al ejecutable
 
 if FILE(cCurl)
     nError = ShellExecute(oWnd,"Open",cCurl,cOpciones,,3)
     if nError < 32  //error
         msgstop(erroresShellExecute(nError),"ERROR AL EJECUTAR COMANDO DEL S.O.")
        else
         msginfo("COMANDO PROCESADO","INFORMACION")
     endif
    else
     msgstop("NO EXISTE EL PROGRAMA: "+cCurl,"ERROR DEL SISTEMA")
  endif

/*  Windows 10 NO lo encuentra a pesar de estar allí instalado. 25/03/2019.
  De modo que el siguiente código siempre devuelve el error nº 2 de ShellExecute
  if FILE("C:\Windows\System32\curl.exe")
     nError = ShellExecute(oWnd,"Open","C:\Windows\System32\curl.exe",cOpciones,,3)
     if nError < 32  //error
         msgstop(erroresShellExecute(nError),"ERROR AL EJECUTAR COMANDO DEL S.O.")
        else
         msginfo("COMANDO PROCESADO","INFORMACION")
     endif
    else
     msgstop("NO EXISTE EL PROGRAMA: "+"C:\Windows\System32\curl.exe","ERROR DEL SISTEMA")
  endif
*/
return


/* Instrucciones de ShellExecute: 
   https://docs.microsoft.com/en-us/windows/desktop/api/shellapi/nf-shellapi-shellexecutea#return-value
Devuelve:
El valor devuelto es el identificador de instancia de la aplicación que se abrió o se imprime, si la función se realiza correctamente. 
(Este controlador también podría ser el identificador de una aplicación de servidor DDE.) 
Una devolución de valor menor o igual a 32 especifica un error.

Errores:
La función ShellExecute() devuelve el valor 31 Si no hay ninguna asociación para el tipo de archivo especificado, 
o si no hay ninguna asociación para la acción especificada en el tipo de archivo. 
Los demás valores de error posibles son:*/                                     
function erroresShellExecute(nError)
 local nPos:=0
 local aErrores:={ {0, "System was out of memory, executable file was corrupt, or relocations were invalid."},;
                   {2, "File was not found."},;
                   {3, "Path was not found."},;
           {5, "Attempt was made to dynamically link to a task, or there was a sharing or network-protection error."},;
                   {6, "Library required separate data segments for each task."},;
                   {8, "There was insufficient memory to start the application."},;
                   {10,"Windows version was incorrect."},;
                   {11,"Executable file was invalid. Either it was not a Windows application, or there was an error in the .exe image."},;
                   {12,"Application was designed for a different operating system."},;
                   {13,"Application was designed for MS-DOS 4.0."},;
                   {14,"Type of executable file was unknown."},;
                   {15,"Attempt was made to load a real-mode application (developed for an earlier version of Windows)."},;
                   {16,"Attempt was made to load a second instance of an executable file containing multiple data segments that were not marked read-only."},;
                   {19,"Attempt was made to load a compressed executable file. The file must be decompressed before it can be loaded."},;
                   {20,"Dynamic-link library (DLL) file was invalid. One of the DLLs required to run this application was corrupt."},;
                   {21,"Application requires Microsoft Windows 32-bit extensions."},;
                   {31,"La extensión del archivo no tiene asociación"} }
  nPos=ascan(aErrores,{|aVal| aVal[1]==nError})
return iif(nPos<>0,str(nError,3)+" - "+aErrores[nPos,2],"SIN ERRORES")
 

Re: CURL

Posted: Tue Mar 26, 2019 7:35 am
by darioflores
Por si quieres una alternativa a curl:

Code: Select all

oWS := CreateObject("MSXML2.ServerXMLHTTP.6.0")
   if ValType(oWS)<>"O"
      MsgInfo("No tenemos el objeto...")
      return nil
   endif

   // Certificado que vamos a usar desde el almacén de certificados de Windows.
   oWS:SetOption(3, "Nombre del certificado")

   oWS :Open("POST", "https://www7.aeat.es/wlpl/SSII-FACT/ws/fe/SiiFactFEV1SOAP", .f.)

   // Establecer el timeout de la operación:
   // resolveTimeout, connectTimeout, sendTimeout, receiveTimeout
   // Los valores son en milisegundos:
   oWS :setTimeouts(15000,15000, 600000, 600000)

   // El método al que vamos a llamar.
   oWS:SetRequestHeader("SOAPAction", "SuministroLRFacturasEmitidas")

   cXML := MemoRead(archivoxml)

   // Enviamos la información del XML.
   oWS:send(cXML)

   MsgInfo("Respuesta: "+oWS:responsexml:xml)
   // Analizar la respuesta...
 
Un saludo.