go to post Laura Blázquez ... · Feb 24, 2020 I have to convert the public key from pkcs#8 to pkcs#1. I have followed this article: https://community.intersystems.com/post/format-public-key-when-using-rsaencrypt-method-systemencryption-or-systemencryptionrsaencrypt Now I can encrypt the string, but the service returns that the api_key must be given in the request. I almost have it.
go to post Laura Blázquez ... · Feb 20, 2020 I have checked that question, but I don't understand what happens. Finally I have used this instruction "openssl rsautl -in fileIn.txt -out fileOut-enc.txt -pubin -inkey public.key -encrypt" using $ZF(-100) and having OpenSSL installed on the server and it works. I want to do it with Encryption methods, there must be a way to do this with COS and not using shell instructions, right?
go to post Laura Blázquez ... · Feb 19, 2020 Sorry, I got the error with RSAGetLastError(). Is this: error:0906D06C:PEM routines:PEM_read_bio:no start line;
go to post Laura Blázquez ... · Feb 19, 2020 Thank you very much for your answer. I don't know what algorithm uses openssl_public_encrypt. I've tried this: set json = "{""api_key"":""XXXXX"", ""id"":""1""}"set file = ##class(%FileCharacterStream).%New()set file.Filename = "public.key"set key = file.Read(file.Size) set jsonEncrypt = $System.Encryption.RSAEncrypt(json, key) But it doesn't work, it returns an empty string. I try to see the error using RSAGetLastError() and I don't get anything. The public.key has this format: -----BEGIN PUBLIC KEY-----........................-----END PUBLIC KEY----- The line breaks are LF and it is in UTF-8. What format should the public key be in order to work in Ensemble? I am doing something wrong?
go to post Laura Blázquez ... · Nov 12, 2019 Thank you very much, I was able to solve my problem with what I put in, and for now I have not needed more
go to post Laura Blázquez ... · Jul 23, 2018 Thank you very much! It works! I haven't seen that button :)
go to post Laura Blázquez ... · Jul 20, 2018 Hello.I'm having the same problem, when I try to open a BPL class with the Atelier BPL Editor I get this error:Bad editor input: org.eclipse.ui.part.FileEditorInput(/TEST/bp/Proceso.cls)And the option "Open diagram editor" is not available.I have this installed:Eclipse IDE for JavaScript and Web DevelopersVersion: Photon Release (4.8.0)Build id: 20180619-1200 And the last version of Atelier in the marketplace (1.2).What can I do? I have a macOS High Sierra v10.13.4, but it happens too on a Windows 10.Thank you in advance.
go to post Laura Blázquez ... · May 17, 2018 Thank you very much! I have tested this, and it's easier to create the full structure with this. This is very useful to us
go to post Laura Blázquez ... · May 16, 2018 Maybe is there something like ##class(Ens.Util.JSON).JSONStreamToObject(...)?
go to post Laura Blázquez ... · Apr 20, 2018 Thanks to all of you.I have extended the original class and tunned the method %ObjectToJSON like this:ClassMethod %ObjectToJSON(pObject As %RegisteredObject, ByRef pVisited, pLevel As %Integer = 0, pFormat As %String = "aceloqtw") As %Status{ Set tSC = $$$OK Try { If ((pObject="")||'$IsObject(pObject)||($D(pVisited(pObject)))) { // cycle Write:pFormat["a"||'pLevel "null" Quit } Set pVisited(pObject) = "" Set tClass = $classname(pObject) If (tClass = "%ZEN.proxyObject") { Set tSC = pObject.%ToJSON(pLevel,pFormat) Quit } Set tLF=$S(pFormat["w":$C(13,10), pFormat["n":$C(10), 1:"") If pFormat'=$TR(pFormat,"it123456789") { Set tN=+$ZStrip(pFormat,"<E'N"), $P(tTab,$S(pFormat["t":$C(9),1:" "),1+$S(tN:tN,pFormat["t":1,1:4))="" } Else { Set tTab="" } Set tIncludeWhitespace = (tLF_tTab'="") If (pObject.%Extends("%Collection.AbstractList")) { Set tList = pObject Set tCount = tList.Count() If (pFormat["l" || tCount) { Write "[" For n = 1:1:tCount { Set tValue = tList.GetAt(n) Write:n>1 "," If $IsObject(tValue) { If (tValue.%IsA("%ZEN.proxyObject")) { Set tSC = tValue.%ToJSON(pLevel+1,pFormat) Quit:$$$ISERR(tSC) } Else { Set tSC = ..%ObjectToJSON(tValue,.pVisited, pLevel+1, pFormat) Quit:$$$ISERR(tSC) } } Else { Write $$$ZENJSONVALUE(tValue,pFormat) } } Quit:$$$ISERR(tSC) If tIncludeWhitespace Set tIndent="", $P(tIndent,tTab,pLevel+1)="" Write tLF_tIndent Write "]" } Quit } ElseIf (pObject.%Extends("%Stream.Object")) { Write """" #; Initialize stream read length, if needed If '$data(tStreamMaxReadLen) Set tStreamMaxReadLen = ($$$MaxLocalLength\2) Do pObject.Rewind() While 'pObject.AtEnd { Write $$$ZENJSONESCAPE(pObject.Read(tStreamMaxReadLen),pFormat) } Write """" Quit } If pFormat["o" || 'pLevel { Set tPropCount = "" If (tIncludeWhitespace && pLevel) Set tIndent="", $P(tIndent,tTab,pLevel+1)="" Write $S(pFormat["b":tLF_tIndent,1:" ") Write "{" } Else { Set tPropCount = 0 } If pFormat["c" { // add class name to model Do nextProp Write $$$ZENJSONPAIR("_class",tClass,pFormat) // add id for persistent objects If (pObject.%IsA("%Library.Persistent")) { Do nextProp Set tID = pObject.%Id() Write $$$ZENJSONPAIR("_id",tID,pFormat) } } #; Special treatment for top-level array: output no matter what If pObject.%Extends("%Collection.AbstractArray") { #; write out (eligible) array elements/properties If pObject.%Extends("%Collection.AbstractArrayOfObj") { #; object elements Set tKey="" For { Set tValue = pObject.GetNext(.tKey) Quit:""=tKey If $IsObject(tValue) { If tValue.%Extends("%Stream.Object")||tValue.%Extends("%IO.I.Stream") { Do tValue.Rewind() If (pFormat["e" || tValue.Size()) { Do nextProp Write $$$ZENJSONPROP(tKey,pFormat)_":""" #; Initialize stream read length, if needed If '$data(tStreamMaxReadLen) Set tStreamMaxReadLen = ($$$MaxLocalLength\2) #; Rewind non-%IO streams if needed If tValue.AtEnd && tValue.%Extends("%Stream.Object") Do tValue.Rewind() While 'tValue.AtEnd { Write $$$ZENJSONESCAPE(tValue.Read(tStreamMaxReadLen),pFormat) } Write """" } } ElseIf pFormat["o" || ..hasObjContent(tValue,.pVisited,pFormat) { Do nextProp Write $$$ZENJSONPROP(tKey,pFormat)_":" Set tSC = ..%ObjectToJSON(tValue,.pVisited, pLevel+1,pFormat) Quit:$$$ISERR(tSC) } } ElseIf pFormat["a" { Do nextProp Write $$$ZENJSONPROP(tKey,pFormat)_":null" } } ; end tKey object array loop } Else { #; scalar array elements Set tKey="" For { Set tValue = pObject.GetNext(.tKey) Quit:""=tKey If (pFormat["e") || (tValue'="") { Do nextProp Write $$$ZENJSONPAIR(tKey,tValue,pFormat) } } ; end tKey scalar array loop } If tPropCount'=0 { #; either we wrote at least one property or we wrote an empty '{' due to "o" mode or level zero If tIncludeWhitespace Set tIndent="", $P(tIndent,tTab,pLevel+1)="" Write tLF_tIndent Write "}" } Quit } #; else: main object is not a collection #; loop over properties using class meta-data Do ..getOrderedProps(tClass,.tProps) Set tSeq="" For { Set tSeq=$O(tProps(tSeq),1,tPropName) Quit:""=tSeq Set tPrivate = +$$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPprivate) Continue:tPrivate||(tPropName["%") Set tType = $$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPtype) Set tClsType = $$$getClassType(tType) Set tClientType = $$$comClassKeyGet(tType,$$$cCLASSclientdatatype) Set tCollection = $$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPcollection) If (tClsType '= "datatype") { #; Check for the case where we have a property declared as a %ListOf** If ($classmethod(tType,"%IsA","%Collection.AbstractList")) { Set tCollection = "list" If ($classmethod(tType,"%IsA","%Collection.AbstractListOfDT")) { #; Reset object information for %ListOfDataTypes Set tClientType = "VARCHAR" Set tDataType = "" } } } Else { Set tDataType=$Case(tClientType, "BOOLEAN":"b", "INTEGER":"n","NUMERIC":"n","FLOAT":"n", "TIMESTAMP":"u", "DATE":"d", "TIME":"t", :"") } Set tMultiDim = 0 If (tCollection="array") { Set tCardinality = $$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPcardinality) Set tInverse = $$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPinverse) If ((tCardinality'="")&&(tInverse'="")) { // treat relationship as list Set tCollection = "list" } } ElseIf (tCollection = "") { Set tMultiDim = +$$$comMemberKeyGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPmultidimensional) } Continue:tMultiDim Set tValue = $property(pObject,tPropName) #; If the value is "" or $c(0) and we are NOT including empty properties, skip if we are not a collection, object or stream If (((tValue = "") || (tValue = $c(0))) && (pFormat'["e") && (tCollection = "") && $Case(tClientType, "HANDLE": 0, "CHARACTERSTREAM": 0, "BINARYSTREAM": 0, :1)) { Continue } // Write the property if not inhibited If (tCollection="list") { // list collection If '$IsObject(tValue) { Set tCount = 0 } Else { Set tList = tValue Set tCount = tList.Count() } If (pFormat["l" || tCount) { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":[" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":[" } For n = 1:1:tCount { Set tValue = tList.GetAt(n) Write:n>1 "," If (tClientType = "HANDLE") { #; object items If $IsObject(tValue) { Set tSC = ..%ObjectToJSON(tValue,.pVisited, pLevel+1, pFormat) Quit:$$$ISERR(tSC) } Else { Write "null" ; not conditional because it has to hold the place in the list } } Else { #; scalar list item ; converts $List to empty string! Write $S((tDataType="b")&&(pFormat["e"):$S(tValue=1:"true",tValue=0:"false",1:"null") , (tDataType="b"):$S(tValue:"true",1:"false") , ((tDataType="n")||(pFormat["q"))&&$$$ZENJSISNUM(tValue):$$$ZENJSNUM(tValue) , (tDataType="n")&&(tValue="")&&(pFormat["d"):"null" , ($C(0)=tValue)||$ListValid(tValue):"""""" , 1:$$$ZENJSONSTR(tValue,pFormat)) } } Write "]" } } ElseIf (tCollection="array") { // array collection (object on client) If '$IsObject(tValue) { Set tKey = "" } Else { Set tArray = tValue Set tKey = tArray.Next("") If pFormat'["o" && (""'=tKey) { #; look ahead to see if there is any content Set tHasArrayContent=0, k=tKey While (k '= "") { Set tValue = tArray.GetAt(k) If (tClientType = "HANDLE") { If $IsObject(tValue) { If ..hasObjContent(tValue,.pVisited,pFormat) Set tHasArrayContent=1 Quit } ElseIf (pFormat["a") { Set tHasArrayContent=1 Quit } } Else { If $S(tDataType="b":1 , $C(0)=tValue||$ListValid(tValue):pFormat["e" //, "dtu"[tDataType:$S(pFormat["u":$$$ZENJSUSTR(..formatDateTime(tValue,tType,tDataType,pFormat)), 1:$$$ZENJSSTR(..formatDateTime(tValue,tType,tDataType,pFormat))) , 1:""'=tValue||(pFormat["e")) { Set tHasArrayContent=1 Quit } } Set k = tArray.Next(k) } } } If (pFormat["o" || (""'=tKey && tHasArrayContent)) { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_": {" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_": {" } Set n = 0 While (tKey '= "") { Set tValue = tArray.GetAt(tKey) If (tClientType = "HANDLE") { #; object elements If $IsObject(tValue) { Set n = n+1 Write $S(n>1:",",1:"")_$$$ZENJSONPROP(tKey,pFormat)_":" Set tSC = ..%ObjectToJSON(tValue,.pVisited, pLevel+1, pFormat) Quit:$$$ISERR(tSC) } ElseIf (pFormat["a") { Set n = n+1 Write $S(n>1:",",1:"")_$$$ZENJSONPROP(tKey,pFormat)_":null" } } Else { #; scalar array item ; converts $List to empty string! Set tStr = $S((tDataType="b")&&(pFormat["e"):$S(tValue=1:"true",tValue=0:"false",1:"null") , (tDataType="b"):$S(tValue:"true",1:"false") , ((tDataType="n")||(pFormat["q"))&&$$$ZENJSISNUM(tValue):$$$ZENJSNUM(tValue) , (tDataType="n")&&(tValue="")&&(pFormat["d"):"null" , ($C(0)=tValue)||$ListValid(tValue):"""""" //, "dtu"[tDataType:$S(pFormat["u":$$$ZENJSUSTR(..formatDateTime(tValue,tType,tDataType,pFormat)), 1:$$$ZENJSSTR(..formatDateTime(tValue,tType,tDataType,pFormat))) , 1:$$$ZENJSONSTR(tValue,pFormat)) If (pFormat["e") || (tStr'="""""") { Set n = n+1 Write $S(n>1:",",1:"")_$$$ZENJSONPROP(tKey,pFormat)_":"_tStr } } Set tKey = tArray.Next(tKey) } Write "}" } } ElseIf (tClientType = "HANDLE") { // object If $IsObject(tValue) { If ..hasObjContent(tValue,.pVisited,pFormat) || (pFormat["o") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":" } Set tSC = ..%ObjectToJSON(tValue,.pVisited, pLevel+1, pFormat) Quit:$$$ISERR(tSC) } } ElseIf (pFormat["a") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":null" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":null" } } } ElseIf (tClientType = "CHARACTERSTREAM") { If $IsObject(tValue) { If tValue.Size || (pFormat["e") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":""" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":""" } If tValue.Size { #; Initialize stream read length, if needed If '$data(tStreamMaxReadLen) Set tStreamMaxReadLen = ($$$MaxLocalLength\2) Do tValue.Rewind() While 'tValue.AtEnd { Write $$$ZENJSONESCAPE(tValue.Read(tStreamMaxReadLen),pFormat) } } Write """" } } ElseIf (pFormat["a") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":null" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":null" } } } ElseIf (tClientType = "BINARYSTREAM") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":null" } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":null" } } Else { #; scalar item ; converts $List to empty string! Set tStr = $S((tDataType="b")&&(pFormat["e"):$S(tValue=1:"true",tValue=0:"false",1:"null") , (tDataType="b"):$S(tValue:"true",1:"false") , ((tDataType="n")||(pFormat["q"))&&$$$ZENJSISNUM(tValue):$$$ZENJSNUM(tValue) , (tDataType="n")&&(tValue="")&&(pFormat["d"):"null" , ($C(0)=tValue)||$ListValid(tValue):"""""" //, "dtu"[tDataType:$S(pFormat["u":$$$ZENJSUSTR(..formatDateTime(tValue,tType,tDataType,pFormat)), 1:$$$ZENJSSTR(..formatDateTime(tValue,tType,tDataType,pFormat))) , 1:$$$ZENJSONSTR(tValue,pFormat)) If (pFormat["e") || (tStr'="""""") { Do nextProp if ($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME") '= "") { Write $$$ZENJSONPROP($$$comMemberArrayGet(tClass,$$$cCLASSproperty,tPropName,$$$cPROPparameter,"XMLNAME"),pFormat)_":"_tStr } else { Write $$$ZENJSONPROP(tPropName,pFormat)_":"_tStr } } } } ; end properties loop Quit:$$$ISERR(tSC) If tPropCount'=0 { #; either we wrote at least one property or we wrote an empty '{' due to "o" mode or level zero If tIncludeWhitespace Set tIndent="", $P(tIndent,tTab,pLevel+1)="" Write tLF_tIndent Write "}" } } Catch ex { Set tSC = ex.AsStatus() } Quit tSCnextProp If tPropCount=0 { If (tIncludeWhitespace && pLevel) Set tIndent="", $P(tIndent,tTab,pLevel+1)="" Write $S(pFormat["b":tLF_tIndent,1:" ") Write "{" } ElseIf tPropCount { Write "," } ; else tPropCount="" means we already did the starting '{' due to "o" mode Set tPropCount = tPropCount + 1 If tIncludeWhitespace Set tIndent="", $P(tIndent,tTab,pLevel+2)="" Write tLF_tIndent Quit}And it works!TEST>set x = ##class(test.msg.struct.TestXML).%New()TEST>set x.statusId = "1111"TEST>set x.service = "222"TEST>do ##class(test.util.JsonProvider).%WriteJSONStreamFromObject(.obj1,.x,,,,"aelotuw")TEST>w obj1.Read(){ "status_id":"1111", "service":"222"}TEST>I didn't want to change system classes, so I thought to extend it and overrite what I need. For me is much clean this.
go to post Laura Blázquez ... · Apr 20, 2018 I had already thought about it, but we have a lot of properties with underscore, we would have to change everyone manually.We can do that, but I don't like it.Maybe changing something in the method ##class(%ZEN.Auxiliary.jsonProvider).%WriteJSONStreamFromObject() that if "XMLNAME" is defined, use that name instead property real name? But I don't know where to do that...
go to post Laura Blázquez ... · Apr 20, 2018 We are using 2016.2.1 (Build 803U).This is the way we generate JSON:TEST>set x = ##class(test.msg.struct.TestXML).%New() TEST>set x.statusId = "111" TEST>set x.service = "222" TEST>do ##class(Ens.Util.JSON).ObjectToJSONStream(x, .obj1, "aelotu") TEST>w obj1.Read(){ "statusId":"111", "service":"222"} And this is the definition of the object:Class test.msg.struct.TestXML Extends (%SerialObject,%XML.Adaptor){Property statusId As %String(MAXLEN = "", XMLNAME = "status_id");Property service As %String(MAXLEN = "");}
go to post Laura Blázquez ... · Feb 9, 2017 Thank you for the information. We know about Ensemble Alerts, and we use it to alert on error, but we did not know that we can set it to alert on other things. The course has been very useful too.
go to post Laura Blázquez ... · Oct 27, 2016 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.