Ensemble + .Net dll with MS Word

.NET, Ensemble

Hi,

We have created a dll with .Net that generates a MS Word document with a template. The .Net method works, we have tested it with Visual Studio and it generates the document.

But once we have created the dll and embebed it in Ensemble through the Wizard, when we try to execute the method that generates the document, it doesn't work. It doesn't throw us an error, it simply doesn't open the template.

We have seen that MS Word program is opened, but that's all.

We are using Microsoft.Office.Interop to generate the Word document. It must be Word 97 version document.

What are we missing? Are we doing something wrong?

Thanks

Answers

Laura

I have a dll that creates an Excel document

I would be delighted to help you debug your word dll.

I have been using activate for years. but when the 64 bit Cache was lauanced the 64 bit link did not work with the activate wizard. ( this is now fixed in the 2016.2 version)

So I was forced to created the .net dll

My original problem was that there were too  many parameters. so I added a top level dll to simplyfy the call

The Cache Studio allows you to chain these dll(s) go gether.

I also used the viual studio to create this module. and it is in constans use.

Since your version is not working yet may I offfer some advice for your consideration.

Embed all the commands with a single common library. in this way all your 'File Generation' code call will be a single source. in this way you will have only one place to expand or correct any problems.

All my reports are in excel spread sheets. Thus all these report generating routines build a common template

at the very end of the code each calls a common code with evokes all the file creation processes.

The younger developers know how to populate the template for with the reporting cache software, but they have no need of the knowledge on how to transfer this template into an actual file.  The system does this for them. Thus the maintenance of the library is entirely independent of all these reports. Thus if in the future Mircosoft or Intersystems change the rules there is only one place to go and fix the change

I have extended this further. When I call the template I first check the Cache version. if it is a 32 bit code I pass the template through the Activate channel for both Word and Excel. If I am running a 64 bit Cache version I pass the templaye to the Dll version.

If you think we have common email me

Laura, can you give some details about the versions you are using here?

Cache server version?  Bitness?

your DLL  - what .NET framework version?

The .NET gateway configuration has a few settings you can change before starting it, like 32 or 64 bit and the .NET framework version.  Can you screen cap the .NET gateway settings page from the portal?

One other question -  this DLL has some function that writes a file to disk.  The DLL is loaded by the DotNetGatewaySS.exe process (or 64 bit.exe version).  That executable was spawned off by Cache.exe and takes the same user name on windows.  What's the user listed in task manager?  Do they have write permissions in the folder you're trying to write to?

Comments

Can you share a bit more details, how you embedded it to Ensemble ?

Wizard - is it Studio wizard ?

And have you configured .Net gateway ? You should have it anyway, and you can configure log file, which may be contain some errors. 

Yes, we have a .Net Gateway configured, and we have imported the .Net dll through the Studio wizard.

We have activated gateway log, but it doesn't say anything.

From an Ensemble Bussiness Operation we call the .Net method. The code is this:

Class bo.GenerarWord Extends EnsLib.DotNetGateway.AbstractOperation
{

Parameter INVOCATION = "Queue";

Method generarDocumento(pRequest As msg.WordRequest, Output pResponse As msg.WordResponse) As %Status
{
        #dim sc as %status
        #dim gateway as %Net.Remote.Gateway
        
        set pResponse = ##class(msg.WordResponse).%New()
        
        set sc = ..GetConnection(.gateway)
        
        if $$$ISERR(sc){
            set pResponse.mensaje = "Error ("_sc_"):"_$System.Status.GetErrorText(sc)
            
        }else{
            #dim ce as cysnet.MiClase.entity.ControlError
            #dim we as cysnet.MiClase.entity.WordEntity
            #dim plantilla as %String
            #dim documento as %String
            
            set ce = ##class(cysnet.MiClase.entity.ControlError).%New(gateway)
            set we = ##class(cysnet.MiClase.entity.WordEntity).%New(gateway)
            
            set plantilla = "C:\InterSystems\Ensemble\mgr\DLLWORDENS2\dlls\PlantillaTuneada.doc"
            set documento = "C:\InterSystems\Ensemble\mgr\DLLWORDENS2\dlls\"
            
            //set we.setuTitulo = "TITULO_ENS"
            
            do dao.EscribirWord(ce,plantilla,documento,we,"PRUEBA_ENS")
            
            $$$LOGINFO(ce.getuDebbug())
        }
        
        set pResponse.mensaje = "OK"
        Quit $$$OK
}

XData MessageMap
{
<MapItems>
        <MapItem MessageType="msg.WordRequest"> 
            <Method>generarDocumento</Method>
        </MapItem>
</MapItems>
}

The .Net code is this:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using cysnet.MiClase.entity;
using System.IO;
using Microsoft.Office.Interop.Word;
 
namespace cysnet.MiClase
{
    public class MiClase
    {
        public String EscribirWord(ControlError ce, String fullPathPlantilla, String pathDocumento, WordEntity we, String numDocumento)
        {
 
            if (ce == null)
            {
                ce = new ControlError();
            }
            ce.Reset();
            ce.Debbug = fullPathPlantilla + " || " + pathDocumento + " || " + numDocumento + "  || ";
            ce.Debbug += " Iniciando método";
            String resultado = "";
            Application MSWord = new Application();
            Document documento;
 
            try
            {
                object oMissing = System.Reflection.Missing.Value;
                
                ce.Debbug += "RUTA DEL NUEVO DOCUMENTO:"+ pathDocumento + numDocumento +".docx";
 
                documento = MSWord.Documents.Add(ref oMissing, ref oMissing, ref oMissing, ref oMissing);
 
                ce.Debbug += " Abriendo plantilla Word";
                //Abrir Palntilla
 
                documento = MSWord.Documents.Open(fullPathPlantilla);
 
                ce.Debbug += " Escribiendo en marcadores";
                
                //Editar marcadores
                documento.Bookmarks["Titulo"].Range.Text = we.Titulo;
 
                ce.Debbug += " Guardando documento Word";
                //Guardar copia de la plantilla como documento
                documento.SaveAs(pathDocumento+numDocumento+".dot");
                
                ce.Debbug += " Cerrando documento Word";
                //Cerrar documento
                documento.Close();
                
                ce.Debbug += " Operación realizada con éxito";
            }
            catch (Exception e)
            {
                ce.MessageError = e.Message;
                ce.IsError = true;
            }
            finally
            {
                ce.Debbug += " Cerrando aplicación MsWord";
                //Cerrar la aplicación
                MSWord.Quit();
            }
 
            return resultado;
        }
    }
}

I have cleaned it a bit to be more legible. It has comments in spanish. I hope it doesn't matter.