Automate PDF exports

L

Lou Zher

I need to perform Form Services-based InfoPath forms to PDF conversions;
that is, convert user filled InfoPath .xml files hosted on SharePoint into
PDFs that I can push back into a SharePoint doclib. The InfoPath forms are
Administratively approved Form Services-based forms stored in
http://site/FormServerTemplates/mytemplate.xsn

I have explored several difference avenues, including various ones where I
first get HTML and then attempt to export that to PDF, but the bummer there
is that the HTML only renders correctly from IE and often only after scripts
are run. It is a big pain to automate IE to print using a print driver that
expects a file name to be typed in.

The option I'm currently trying involves using the InfoPath client via the
FormControl control, but I've been having some issues with this.

A security issue I'm having is getting it to fetch the templates to put in
the template cache. How can I control the credentials it uses to fetch the
template with? Can I prepop the template cache programmatically? Can I
reliably prevent the control from checking the target for updates? Can I
hook it to intercept these requests?

Another issue is that the export will occassionally fail with "InfoPath
cannot export the form. The parameter is incorrect." I saw the forum post
here
(http://www.developerfood.com/export...5c89-44a7-43a9-9e25-058cd570afd0/article.aspx)
that seems to describe my issue, but the response was not helpful. The best
part of this failure is that it seems to depend on the content of the xml.
In one case I got it to fail everytime I tried when the form had a richtext
field with a hyperlink in it (specifically
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx) but it would work
if I just added a bookmark to the hyperlink on the same document (like
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx#jour11masshost_topic1) I
don't see why that has anything to do with with anything, but it adding the
bookmark would make it work everytime, assuming of course I already had the
template in the local template cache. I tried adding slight delays here and
there to no avail.

Also, it would be preferable if I could use the FormControl without hosting
it in a Form. Is there any guidance on how to do this? I assume I should be
able to pump messages into it to get it to believe it is running in a Form.

Actually, it would be preferable if I could totally avoid using FormControl
entirely as it relies on InfoPath client being installed. There doesn't seem
to be any export capability in the Microsoft.Office.InfoPath.Server.dll.

Anyway, below is the FormControl code I'm using in these tests:

static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
FormControl fc = (FormControl)this.Controls[0];
fc.InternalStartup +=
new FormControl.EventHandler<EventArgs>(fc_InternalStartup);
// sometimes hangs here asking for credentials
// or just failing trying to get the template
fc.Open(@"c:\test.xml");
}

void fc_InternalStartup(object sender, EventArgs e)
{
// have to wait for the viewswitch to perform
// export or it will always fail
((FormControl)sender).EventManager.FormEvents.ViewSwitched +=
new ViewSwitchedEventHandler(FormEvents_ViewSwitched);
}

void FormEvents_ViewSwitched(object sender, ViewSwitchedEventArgs e)
{
// this sometimes fails
((XmlForm)sender).CurrentView.Export(@"c:\test.pdf",
ExportFormat.Pdf);
System.Windows.Forms.Application.ExitThread();
}
}

-LZ
 
L

Lou Zher

Ah ha! Important lesson: Use fully qualified filenames!

Exporting to \test.pdf would sometimes fail, but c:\test.pdf would not.

I think I can avoid the prompting if I run IE as the user account that I am
planning on running this application under and connect to the source of the
templates (that is, the SharePoint site) and save the credentials I use to
do that with.

-LZ


Lou Zher said:
I need to perform Form Services-based InfoPath forms to PDF conversions;
that is, convert user filled InfoPath .xml files hosted on SharePoint into
PDFs that I can push back into a SharePoint doclib. The InfoPath forms are
Administratively approved Form Services-based forms stored in
http://site/FormServerTemplates/mytemplate.xsn

I have explored several difference avenues, including various ones where I
first get HTML and then attempt to export that to PDF, but the bummer
there is that the HTML only renders correctly from IE and often only after
scripts are run. It is a big pain to automate IE to print using a print
driver that expects a file name to be typed in.

The option I'm currently trying involves using the InfoPath client via the
FormControl control, but I've been having some issues with this.

A security issue I'm having is getting it to fetch the templates to put in
the template cache. How can I control the credentials it uses to fetch the
template with? Can I prepop the template cache programmatically? Can I
reliably prevent the control from checking the target for updates? Can I
hook it to intercept these requests?

Another issue is that the export will occassionally fail with "InfoPath
cannot export the form. The parameter is incorrect." I saw the forum post
here
(http://www.developerfood.com/export...5c89-44a7-43a9-9e25-058cd570afd0/article.aspx)
that seems to describe my issue, but the response was not helpful. The
best part of this failure is that it seems to depend on the content of the
xml. In one case I got it to fail everytime I tried when the form had a
richtext field with a hyperlink in it (specifically
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx) but it would
work if I just added a bookmark to the hyperlink on the same document
(like
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx#jour11masshost_topic1) I
don't see why that has anything to do with with anything, but it adding
the bookmark would make it work everytime, assuming of course I already
had the template in the local template cache. I tried adding slight delays
here and there to no avail.

Also, it would be preferable if I could use the FormControl without
hosting it in a Form. Is there any guidance on how to do this? I assume I
should be able to pump messages into it to get it to believe it is running
in a Form.

Actually, it would be preferable if I could totally avoid using
FormControl entirely as it relies on InfoPath client being installed.
There doesn't seem to be any export capability in the
Microsoft.Office.InfoPath.Server.dll.

Anyway, below is the FormControl code I'm using in these tests:

static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
FormControl fc = (FormControl)this.Controls[0];
fc.InternalStartup +=
new FormControl.EventHandler<EventArgs>(fc_InternalStartup);
// sometimes hangs here asking for credentials
// or just failing trying to get the template
fc.Open(@"c:\test.xml");
}

void fc_InternalStartup(object sender, EventArgs e)
{
// have to wait for the viewswitch to perform
// export or it will always fail
((FormControl)sender).EventManager.FormEvents.ViewSwitched +=
new ViewSwitchedEventHandler(FormEvents_ViewSwitched);
}

void FormEvents_ViewSwitched(object sender, ViewSwitchedEventArgs
e)
{
// this sometimes fails
((XmlForm)sender).CurrentView.Export(@"c:\test.pdf",
ExportFormat.Pdf);
System.Windows.Forms.Application.ExitThread();
}
}

-LZ
 
L

Lou Zher

Ah ha! Important lesson #2: Give app pool identity good access to
C:\Documents and Settings\Default User\Local Settings\Application
Data\Microsoft\InfoPath so .Open() can write to the template cache there.
That is where FormControl writes to for all users if you do not load the
user profile, which you typically wouldn't if you wanted to automate
something like this.

I will try to come back and document the entire process here later.
-LZ

Lou Zher said:
Ah ha! Important lesson: Use fully qualified filenames!

Exporting to \test.pdf would sometimes fail, but c:\test.pdf would not.

I think I can avoid the prompting if I run IE as the user account that I
am planning on running this application under and connect to the source of
the templates (that is, the SharePoint site) and save the credentials I
use to do that with.

-LZ


Lou Zher said:
I need to perform Form Services-based InfoPath forms to PDF conversions;
that is, convert user filled InfoPath .xml files hosted on SharePoint into
PDFs that I can push back into a SharePoint doclib. The InfoPath forms are
Administratively approved Form Services-based forms stored in
http://site/FormServerTemplates/mytemplate.xsn

I have explored several difference avenues, including various ones where
I first get HTML and then attempt to export that to PDF, but the bummer
there is that the HTML only renders correctly from IE and often only
after scripts are run. It is a big pain to automate IE to print using a
print driver that expects a file name to be typed in.

The option I'm currently trying involves using the InfoPath client via
the FormControl control, but I've been having some issues with this.

A security issue I'm having is getting it to fetch the templates to put
in the template cache. How can I control the credentials it uses to fetch
the template with? Can I prepop the template cache programmatically? Can
I reliably prevent the control from checking the target for updates? Can
I hook it to intercept these requests?

Another issue is that the export will occassionally fail with "InfoPath
cannot export the form. The parameter is incorrect." I saw the forum post
here
(http://www.developerfood.com/export...5c89-44a7-43a9-9e25-058cd570afd0/article.aspx)
that seems to describe my issue, but the response was not helpful. The
best part of this failure is that it seems to depend on the content of
the xml. In one case I got it to fail everytime I tried when the form had
a richtext field with a hyperlink in it (specifically
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx) but it would
work if I just added a bookmark to the hyperlink on the same document
(like
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx#jour11masshost_topic1) I
don't see why that has anything to do with with anything, but it adding
the bookmark would make it work everytime, assuming of course I already
had the template in the local template cache. I tried adding slight
delays here and there to no avail.

Also, it would be preferable if I could use the FormControl without
hosting it in a Form. Is there any guidance on how to do this? I assume I
should be able to pump messages into it to get it to believe it is
running in a Form.

Actually, it would be preferable if I could totally avoid using
FormControl entirely as it relies on InfoPath client being installed.
There doesn't seem to be any export capability in the
Microsoft.Office.InfoPath.Server.dll.

Anyway, below is the FormControl code I'm using in these tests:

static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
FormControl fc = (FormControl)this.Controls[0];
fc.InternalStartup +=
new FormControl.EventHandler<EventArgs>(fc_InternalStartup);
// sometimes hangs here asking for credentials
// or just failing trying to get the template
fc.Open(@"c:\test.xml");
}

void fc_InternalStartup(object sender, EventArgs e)
{
// have to wait for the viewswitch to perform
// export or it will always fail
((FormControl)sender).EventManager.FormEvents.ViewSwitched +=
new ViewSwitchedEventHandler(FormEvents_ViewSwitched);
}

void FormEvents_ViewSwitched(object sender, ViewSwitchedEventArgs
e)
{
// this sometimes fails
((XmlForm)sender).CurrentView.Export(@"c:\test.pdf",
ExportFormat.Pdf);
System.Windows.Forms.Application.ExitThread();
}
}

-LZ
 
L

Lou Zher

Hmm.. It also appears that Export gets considerably less reliable if you
target anything in your user profile area; for example

C:\Documents and Settings\LouZher\Local Settings\Temp

but it works fine if I point it at

C:\WINDOWS\TEMP

it even worked at C:\Documents and Settings.
-LZ

Lou Zher said:
Ah ha! Important lesson #2: Give app pool identity good access to
C:\Documents and Settings\Default User\Local Settings\Application
Data\Microsoft\InfoPath so .Open() can write to the template cache there.
That is where FormControl writes to for all users if you do not load the
user profile, which you typically wouldn't if you wanted to automate
something like this.

I will try to come back and document the entire process here later.
-LZ

Lou Zher said:
Ah ha! Important lesson: Use fully qualified filenames!

Exporting to \test.pdf would sometimes fail, but c:\test.pdf would not.

I think I can avoid the prompting if I run IE as the user account that I
am planning on running this application under and connect to the source
of the templates (that is, the SharePoint site) and save the credentials
I use to do that with.

-LZ


Lou Zher said:
I need to perform Form Services-based InfoPath forms to PDF conversions;
that is, convert user filled InfoPath .xml files hosted on SharePoint
into PDFs that I can push back into a SharePoint doclib. The InfoPath
forms are Administratively approved Form Services-based forms stored in
http://site/FormServerTemplates/mytemplate.xsn

I have explored several difference avenues, including various ones where
I first get HTML and then attempt to export that to PDF, but the bummer
there is that the HTML only renders correctly from IE and often only
after scripts are run. It is a big pain to automate IE to print using a
print driver that expects a file name to be typed in.

The option I'm currently trying involves using the InfoPath client via
the FormControl control, but I've been having some issues with this.

A security issue I'm having is getting it to fetch the templates to put
in the template cache. How can I control the credentials it uses to
fetch the template with? Can I prepop the template cache
programmatically? Can I reliably prevent the control from checking the
target for updates? Can I hook it to intercept these requests?

Another issue is that the export will occassionally fail with "InfoPath
cannot export the form. The parameter is incorrect." I saw the forum
post here
(http://www.developerfood.com/export...5c89-44a7-43a9-9e25-058cd570afd0/article.aspx)
that seems to describe my issue, but the response was not helpful. The
best part of this failure is that it seems to depend on the content of
the xml. In one case I got it to fail everytime I tried when the form
had a richtext field with a hyperlink in it (specifically
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx) but it would
work if I just added a bookmark to the hyperlink on the same document
(like
http://msdn2.microsoft.com/en-us/arcjournal/bb491120.aspx#jour11masshost_topic1) I
don't see why that has anything to do with with anything, but it adding
the bookmark would make it work everytime, assuming of course I already
had the template in the local template cache. I tried adding slight
delays here and there to no avail.

Also, it would be preferable if I could use the FormControl without
hosting it in a Form. Is there any guidance on how to do this? I assume
I should be able to pump messages into it to get it to believe it is
running in a Form.

Actually, it would be preferable if I could totally avoid using
FormControl entirely as it relies on InfoPath client being installed.
There doesn't seem to be any export capability in the
Microsoft.Office.InfoPath.Server.dll.

Anyway, below is the FormControl code I'm using in these tests:

static class Program
{
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}

public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}

private void Form1_Load(object sender, EventArgs e)
{
FormControl fc = (FormControl)this.Controls[0];
fc.InternalStartup +=
new
FormControl.EventHandler<EventArgs>(fc_InternalStartup);
// sometimes hangs here asking for credentials
// or just failing trying to get the template
fc.Open(@"c:\test.xml");
}

void fc_InternalStartup(object sender, EventArgs e)
{
// have to wait for the viewswitch to perform
// export or it will always fail
((FormControl)sender).EventManager.FormEvents.ViewSwitched +=
new ViewSwitchedEventHandler(FormEvents_ViewSwitched);
}

void FormEvents_ViewSwitched(object sender, ViewSwitchedEventArgs
e)
{
// this sometimes fails
((XmlForm)sender).CurrentView.Export(@"c:\test.pdf",
ExportFormat.Pdf);
System.Windows.Forms.Application.ExitThread();
}
}

-LZ
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top