Trying to run a C# .exe program on the SBM server from an SBM URL on a client browser to create a "Batch of PDFs" Problem
We have a C# program that was written to extend SBM's ability to fill in a PDF template from SBM data, and this C# program can currently create hundreds of PDFs at one time, from data records in an SBM Primary table (whereas the SBM PDF Widget can only create a PDF "one at a time"). This C# program uses a call to iTextSharpe to create the PDFs, and the C# .exe is currently being installed on every User's Client Desktop (that needs this "batch" PDF creating ability), and when executed, the C# program first pops up a login box that will accept the User's SBM Login name and Password, and then the C# program uses the sbmappservices72 web service to authenticate the User, and then a second box pops up asking the User for some data parameters.
At this point the User enters a Fiscal Year and an Organization Name, and then the C# program reads all of the records in an SBM Primary table for that Fiscal Year and Organization, and it takes the data from these records and creates one PDF per SBM Primary record read, and then the C# program creates a single .zip file containing these "hundreds of PDFs", and then the C# program asks the User where they would like the zip file to be stored.
Again, the C# .exe program is currently installed on each User's Client desktop, and we would like to put this .exe onto the SBM server, and then find a way to call the .exe from an SBM Transition or from a custom Button on an SBM form (that would maybe open a URL that invokes the C# .exe that's stored on the server), so that we don't have to install the C# .exe on every User's Client Desktop.
I tried putting the .exe in the AE/bin/images directory on the SBM server, and then I tried to hit this URL from my client desktop "http://servername:8088/tmtrack/images//CSHARPE_PDF_CREATOR.exe" but this didn't cause the .exe to run on my Client desktop (and probably for good reason :-) So, can the SBM guru gods possibly suggest some way to make this C# .exe able to be stored on the SBM server AND executed from the SBM User's client browser?
Also, as a bonus extra credit, I'm thinking about doing away with the C# program altogether and looking for another way to create these "batches of PDFs" from a single click on an SBM screen, and with this new age thought in mind, I'm considering writing an AppScript that will accept the Fiscal Year and Organization Name, and then it will create a delimited .txt (or .csv) data file with 1 row per record that's in the Primary table, and then find a way to feed this delimited .txt file to a tool that will take the delimited records, and the "PDF fillable template", as inputs, and then return me back the set of PDFs with the data filled in, 1 row per PDF generated.
It was suggested to me that Adobe Acrobat "may" be able to do this, but we would have to buy multiple copies of Adobe Acrobat (not good), unless we could buy just one copy of Adobe Acrobat to store it on the SBM server, and then have SBM somehow execute Acrobat, produce the multiple PDFs, and then put the PDFs somewhere that the User can retrieve the PDFs from.
In my research I haven't seen that Adobe Acrobat can take a delimited file with multiple rows, and create multiple PDFs "in one swoop", and basically my management would like a "free" solution to replace the current C# code anyway, so if there's anyone who can help guide me out of the abyss, I would be deeply indebted to you for your kindness.
And if you've read down to this point, and have not passed out from boredom or an extreme brain-f&rt, then thanks for making it this far, and I look forward to any and all comments, questions, or statements of disbelief.
Accepted AnswerModeratorDavid GoodaleOffline0Hi Tony,
You want to call your C# program from an AppScript using Ext.CmdLineWait, Ext.NewTask or ExtNewTaskWait. The AppScript should call a batch file that calls your C# program and whatever other commands you need to complete the process.
The batch file / C# program would do the following. Place the output into a specific directory under your IIS website. I would suggest naming the file something unique like user_timestamp.pdf.
Consider the functionality you want. You can use the C# program to attach the PDF to the item via web services; this way you track the history of PDFs generated and make it easier and safer to get PDF to the user. Or you can attach a note to the item via web services with the link. Alternatively, you can send out an email with the link. I would probably go with note or attachment.
Finally, if you do not use the attachment method then you will need to decide how you will clean up all of these temporary PDFs. Perhaps, have the batch file delete anything older than one week.
As for replacing your C# program, I would keep it because you control it. A free solution will likely get out of date fast. You are probably best to stay with the C# program or convert VB if you want an language that is known by more people.
Thanks Dave, and by the way, does it matter which directory I put the C# .exe in, such as a directory under the Application Engine root, or does it not matter where I put the C# exe?
David Goodalemore than a month agoIIS just needs to have permissions to the C# .exe / bat file directory (the app pool user). It best to put the exe and bat file in a directory that is not shared by IIS. You do not want hackers getting access to your exe or bat file.
Accepted AnswerPaul ThompsonOffline0@TonyC:
Did you ever get the server-resident version of the PDF batch creator working? We have a requirement for this. Anything you can share would be helpful. Thanks in advance!
Hi Paul, yes I have it working (thank the powers that be), with the help of a C# programmer. Basically I start with an SBM Primary Table (Workflow) record from which the User creates a new record (or modifies an existing record), and then they press the Transition button to create the .Zip file full of PDFs, and they supply a parameter to the Transition screen (that is used to guide the extraction of the data from another Primary Table), and then a Post Transition script runs to create a .Txt file with a header row and 1 or more data rows (comma separated), and my script then writes this .Txt file to a directory on the web server.
Next, the script creates a .bat file containing a call to the C# program inside the .bat file, along with some other parameters in the .bat file for input to the C# program (including the name of the .Txt file and a PDF Template file name, etc..). And then the script executes the .bat file (using the Ext.CmdLineWait function).
This C# program runs and takes the name of the .Txt file, and takes the name of the PDF template, and takes the desired name of the output .Zip file (which the script creates using the Date/Time stamp in order to keep the .Zip file name unique), and then the C# program merges the .Txt data onto the PDF template (using a freeware program for merging Text to a PDF Template), and the C# program creates 1 PDF per data row that is in the .Txt file, and then the C# program combines the PDF files into a .Zip file, and places the .Zip file into the SBM Attachments directory on the web server.
Next, the script creates an entry in the TS_ATTACHMENTS Table for that .Zip file, referencing the Workflow record that started the whole she-bang, and when all is said and done (and the Transition completes), the .Zip file appears (to the User) as an attachment on the given Workflow record, and then the User can download the .Zip file to their desired location. Simple as that ;-)
What makes this whole thing work (outside of the usual SBM available tools) is that you must first give the IIS AppPool User permissions to the directory holding the C# program, and permissions to the SBM Attachments Directory, and the C# programmer used some freeware tool that I'll have to locate, that merges data onto a PDF Template, and then .Zips up the PDFs.
I hope this helps, and I can demo the process to you when you have time. And you can email me also, at Tony (at) AJCUnited.Com.
I believe the C# programmer used something called iTextSharpe or iTextPDF, and he no longer works for the client that I built this process for, but that's the only PDF library that I kind of remember.
Accepted AnswerNeil GillOffline1Hi Tony,
Just seen this post, glad you got it resolved. We have a few apps now where we need to create PDFs and attach to items. We use similar processes to those described above calling c# apps via Ext.cmdLineWait. The difference in our approach is we parse the sbm data into xml files which we pass along with a template PDF file to an Adobe Lifecycle server. This merges the xml into the template and returns a pdf. The real advantage of doing this is you can create automatically expanding tables in the form to handle different lengths of data, we use it for Actions, so one pdf may only have one action, another may have 10's of actions.
Shame we dont get to meet at the Exchange sessions anymore, but happy to chat via email if you need anymore details.
All the best
I've been doing a little research and discovered the same option. We can have an AppScript or ModScript create an FDF or XFDF then call a command line on the server that will merge that with the PDF template and spit out a completed PDF. Or at least that's me dream of how it would work.
Next step is figuring out how to do the FDF/XFDF + PDF --> PDF merging part.
Accepted AnswerPaul ThompsonOffline0I think I found an "easy" (well, relatively) way to do this. Still need to work out a few details, but the idea is this:
Download the PDFtk toolkit from "https://www.pdflabs.com/tools/pdftk-the-pdf-toolkit/" and install it on the AE (IIS) server. If you're a good sport, use the commercial "server" PDFtk and pay them the $79 for support.
In the server, open a command line window and run the PDFtk command line command to read the PDF template file and create an FDF:
pdftk Name-of-PDF-template generate_fdf output Name-of-FDF verbose
Run "pdftk --help" to get usage.
The generated FDF will become the "model" for a file that needs to be created by an AppScript or ModScript.
The FDF file basically lists all the fields in the PDF on lines that look more-or-less like this:
<< /T (Name-of-PDF-field) /V (value-from-SBM-to-be-put-into-PDF) >>
Note that the file output by PDFtk does this but spreads them across multiple lines and may change the order of the /T and /V. There's also lines for the page organization plus header and trailer stuff. The syntax of the FDF file seems to ignore white space. It also uses the BACKSLASH as a line-continuation character where needed.
Write an App or Mod script that reads the fields from SBM and outputs a bunch of lines that more-or-less duplicate the FDF that came from the PDFtk command line. These lines need to be written into a uniquely named FDF on the server using Ext.AppendTextFile. Once the file is generated, the script needs to launch a command on the server using Ext.NewTask or Ext.NewTaskWait that runs the PDFtk command line tool again. The PDFtk command reads the PDF template on the server, the uniquely named FDF file just created by the script and outputs a uniquely named PDF. The output PDF is the original PDF template plus all the SBM data from the FDF file:
pdftk Name-of-PDF-template fill_form Name-of-FDF-generated-by-script output unique-PDF-name verbose
Optionally, the script could update a status field in the item with the names of the PDF file output by PDFtk. I'm thinking it might be a good idea to single-thread the section of script code that runs the PDFtk command to prevent the server from being overloaded. The Ext.AcquireLock and Ext.ReleaseLock calls do this. The downside is that each item will queue up on the lock section. Some items could take a very long time to be completed.
In the Workflow, create a special "QUICK" transition that will run the script that creates the FDF. For our application, we need to restrict who can do this so we'll create a Role (no extra privileges needed) like "Can Generate PDF bundle" and assign that Role to a user or group.
Create a report that allows selecting multiple items. The user does this and does a mass-transition on those items. Each item runs the script which creates it's own FDF and runs the PDFtk command the server.
One thing I still need to figure out is how to bundle all my generated PDFs into a zip and make that available to the requestor. It would be nice if all the items selected for a mass transition could somehow decide on a single "leader" item that would be the first or last item transitioned. That one item would execute script code to do the ZIP and any other one-time-only stuff.