Compile Tex inside Microsoft C#.net
Step 1: Create a batch file
To avoid recompiling the C# source code to be in sync with the (La)TeX compiler you want to use, it will be convenient to create a batch file. The batch file executes (La)TeX compiler behind the scene. Save the batch file anywhere and set the PATH system variable to the batch location.
The simplest batch may be as follows
rem %1 represents the file name with no extension.
pdflatex -shell-escape %1
Step 2: Create the C# code and compile
The simplest example is as follows:
using System.Diagnostics;
class MyApp
{
public static void Main(string[] args)
{
Process p1 = new Process();
p1.StartInfo.FileName = "batch.bat";
p1.StartInfo.Arguments = args[0];
p1.StartInfo.UseShellExecute = false;
p1.Start();
p1.WaitForExit();
}
}
Compile it with C# compiler to get MyApp.exe
for example.
Step 3: Finish, You are ready to make a try
MyApp.exe
needs a single argument which is the TeX input file name with no extension.
From command prompt, you execute MyApp.exe TeXInputFileNameWithNoExtension
.
So we meet again, C#. :)
It's not so easy for to provide an answer, but I'll try.
Most of the time, we end up with complex documents which might require several runs in order to reach a steady state. So, it's likely you'll need more than one run to get the correct output.
If you stick with the engines like pdflatex
, you'll probably need to ensure the miminal amount of calls to it and/or other helper programs (e.g, makeindex
). That might be a burden, specially when you don't know the steps in advance.
Tools like latexmk
and rubber
were created to ease the compilation process in the sense of trying to guess if your document needs another run, or calling other programs. They even give up on compilation if you have a document which will never reach a steady state. So, they might make your life easier. But of course we have the human factor. :)
Those tools might not work as expected (e.g, rubber
doesn't recognize biber
), so you might need to end up tuning those tools with configuration files or directives.
And now there's arara
, a humble project of mine (sorry for the shameless self-promotion). This tool is different from latexmk
and rubber
because, well, it will execute only what you tell it to. There's no guessing, no auxiliary file parsing or other cool stuff. By adding directives to the source code, (e.g, % arara: pdflatex: { shell: yes }
, arara
will expand those instructions based on well defined rules to commands and then execute them. It might be powerful if you really know what it's going on in the bowels of your engine, otherwise it might be difficult to digest the concept. The project is still in heavy development, thanks to the great contributions of Marco Daniel (project collaborator) and Joseph Wright.
Now, back to your question. :)
It would be great if you tell us about your C# application. Sometimes, based on your needs, a more reliable solution is available. For example, Forgiver's answer is an interesting way of calling pdflatex
. If you need a more generic configuration, you could use something among these lines:
using System;
using System.Xml;
using System.Diagnostics;
namespace MyProgram
{
class MyTeXWrapper
{
static void Main(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Sorry, I expect 2 arguments.");
System.Environment.Exit(-1);
}
string command = "";
string arguments = "";
try
{
XmlDocument document = new XmlDocument();
document.Load(args[1]);
XmlElement rootElement = document.DocumentElement;
XmlNodeList nodes = rootElement.ChildNodes;
foreach (XmlNode node in nodes)
{
if (node.Name.Equals("command"))
{
command = node.InnerText;
}
else
{
if (node.Name.Equals("arg"))
{
if (node.Attributes.Count == 1)
{
if (node.Attributes.Item(0).Name.Equals("value"))
{
arguments = arguments + node.Attributes.Item(0).Value + " ";
}
}
}
}
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
arguments = arguments + args[0];
Process process = new Process();
process.StartInfo.FileName = command;
process.StartInfo.Arguments = arguments;
process.StartInfo.UseShellExecute = false;
process.Start();
process.WaitForExit();
if (process.ExitCode == 0)
{
Console.WriteLine("Command was successfully executed.");
}
else
{
Console.WriteLine("An error occurred.");
}
}
}
}
The idea is to have a XML-based configuration file which will determine how the command should be invoked. A sample configuration file:
<configuration>
<command>pdflatex</command>
<arg value="--interaction=nonstopmode"/>
<arg value="--shell-escape"/>
</configuration>
Consider the following tex
file:
\documentclass{article}
\begin{document}
Hello world!
\end{document}
Now, I can run my code with MyProgram.exe hello config.xml
:
I use Mono. :)
Note that I used --interaction=nonstopmode
as an argument. Depending of how your application should behave, having interactive commands might be a problem. For example, if our tex
code above had a syntax typo, and without --interaction=nonstopmode
, pdflatex
would prompt you a message and wait for your input. For arara
I redirected the output streams (stdout
and stderr
) to separated threads, but I'm still struggling with the input stream (stdin
). As an example, TeXworks can prompt an input box if the program requires interaction:
Thankfully the TeX programs provide exit status, so you can check if the run was successful. If you have a very complex document, maybe it's wise to create a worker thread and let it handle the call, avoiding blocking your application (David mentioned in the chatroom that Frank's book took about 20 minutes to compile). :)
Now, which tool is the best? I have absolutely no idea. :)
My thoughts: if you want to have more control on your workflow, stick with the original command line programs. Now, flexibility and ease to use are keywords here, give latexmk
or rubber
a try. :)
I want to provide an answer which uses the tool arara
.
The tool arara
is well documented
- at the developer site: Arara -- The cool TeX automation tool
- at a printable documentation: arara -- pdf documentation
A small blog post by Joseph write is also available: arara: Making LaTeX files your way
Based on the given links you can compile your .tex
file with arara filename
. The compiling process can be specified by rules inside your .tex
. For example a simple |pdflatex| looks as follows:
% arara: pdflatex
arara
offers the possibility to set up options directly inside the |.tex| file.
Give arara
a try! ;-)