I am working on converting word docs and excel to pdf and automate the whole process. We have a server application that prints all the .doc and .xls files using COM interop and we want to have those files converted to PDF instead of printing them. I referred to How do I convert Word files to PDF programmatically? and also http://www.microsoft.com/en-us/download/details.aspx?id=7 to convert the documents to PDF and i was able to convert them. When i was doing some more research on the topic i found that it is not advisable to call Office Interop from Server Side application (Office documents to PDF), so i thought of using something like a PDF printer driver using which i can configure to bypass the Save As dialog. The i downloaded PDF995 and used the following code to test the output
string printerName = "PDF995";
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = (#"C:\...\test.XLS");
startInfo.Arguments = "\"" + printerName + "\"";
startInfo.CreateNoWindow = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
//startInfo.UseShellExecute = true;
startInfo.Verb = "printto";
using (Process process = new Process())
{
process.StartInfo = startInfo;
process.Start();
if (!process.HasExited)
{
process.WaitForExit();
}
}
It works in my box and i need to test it in the server. I just realized while testing it, i am getting exception "No Process associated with this object" at the line (!process.hasexited) only for .xls files but not for .doc and .ppt files. I am wondering why, i tried to look at the Process Monitor (https://technet.microsoft.com/en-us/sysinternals/bb896645.aspx) but could not find it. But it does work for .doc files without throwing the exception. Any idea why?
I would also like to know if there is a better way to go about it? I did take a look at the libraries like Aspose to convert word to pdf but the problem was we may have to purchase separate modules for word and another one for excel and one for slides which would be expensive. So we thought of using a printer driver which would be ideal to handle different types of documents.
Related
I am trying to open the file in Adobe Reader through "process" because Adobe reader can repair the corrupt file itself, but I need to “SaveAs” the file also from there at code level without manually saving it, is it possible in .net?
Code I am using :
Process p = new Process();
p.StartInfo.FileName = file;
p.Start();
//Code to Save As this file
p.Close();
corrupt = true;
inputDocument = PdfReader.Open(file, PdfDocumentOpenMode.Import);
You could do it by poking the application with the AutomationAPI that is built into Windows.
TestStacks.White is an automation wrapper I've used in the past for automated UI testing, but it could also do what you require: https://teststackwhite.readthedocs.io/en/latest/
I have an application that executes an SSRS report to create a file, which is saved locally in PDF. I would like to print the file, but we have been experiencing problems with the Acrobat Reader security settings, which are stopping the print from happening - our security guys and app support have said that Acrobat is not an option and I need to find another way to print the report.
All of the computers that will be used to run the app have Google Chrome installed, so it seems sensible to me to use this to open and print the PDF. We can set chrome as the default application for opening PDF files, and with this done, I had the following code snippet running (after some research online):
Process process = new Process();
PrintDialog printDialog = new PrintDialog();
numberOfCopies = printDialog.PrinterSettings.Copies;
ProcessStartInfo starter = new ProcessStartInfo();
starter.FileName = "\"" + printFileName + "\"";
starter.Arguments = "\"" + printDialog.PrinterSettings.PrinterName + "\"";
//starter.Verb = "printto";
for (short s = 1; s <= numberOfCopies; s++)
{
starter.CreateNoWindow = true;
starter.WindowStyle = ProcessWindowStyle.Hidden;
starter.UseShellExecute = true;
process.StartInfo = starter;
process.Start();
//... more code
With the line starter.Verb = "printto"; commented, chrome opens the PDF, but adding the verb causes an error to be returned saying there is no default app for that file type. I have been doing some research and it seems maybe I should be using headless mode, but all I have found there is command line stuff and ASP.NET.
I believe that a previous developer had problems with MS Word as well, so would prefer to avoid that route if possible - I think there was something to do with Citrix, but not sure.
Does Chrome support the use of the print command like this, or am I on a hiding to nothing? If it does support, what am I doing wrong / how could I do it better (e.g. headless mode?)? If it does not support, is there some other way that I can use to print a PDF without using acrobat?
Google chrome has no command line switch for "printto". Hence when you use the verb "printto" there is an error. Below are the list of command line switches supported by Chrome.
https://peter.sh/experiments/chromium-command-line-switches/
There is a switch "--print" in chrome. But that doesn't print pdf file.
If you are able to print pages using Acrobat reader then it should work. It would be easier for me to help if you can give more details on the security settings issue that you were facing. Having said that, I have been using Acrobat reader to initiate PDF printing in my Windows forms application for a fair amount of time . They have the "print" and "printto" verbs implemented. And it works well in all of production deployment.
System.Diagonstics.Process class does what "Start-Process" does on Powershell. We can test printing using "Start-Process" without having to run the C# code. Set the default application for opening pdf as Acrobat reader. Run the below sample code by changing pdf location.
Start-Process "C:\DevOps-with-ASP.NET-Core-and-Azure.pdf" -Verb printto "OneNote"
By this we can identify the security issue and do necessary changes to allow printing through Acrobat Reader.
Printing pdf through a browser using Process class is not feasible as of now. Even the Microsoft's own edge browser doesn't support printing through Process. Below is the error we get when we try to do same in powershell
PS C:\Users\darsh> Start-Process "C:\DevOps-with-ASP.NET-Core-and-Azure.pdf" -Verb printto "OneNote"
Start-Process : This command cannot be run due to the error: No application is associated with the specified file for
this operation.
At line:1 char:1
+ Start-Process "C:\DevOps-with-ASP.NET-Core-and-Azure.pdf" -Verb print ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [Start-Process], InvalidOperationException
+ FullyQualifiedErrorId : InvalidOperationException,Microsoft.PowerShell.Commands.StartProcessCommand
I am trying to run a 'EXE' using c# code to convert .xls to .xlsx. It is running successfully and working as expected if I run using a console application or cmd.
But when I am running it in server side (code hosted in IIS i.e code running using w3wp.exe worker process) it unable to convert files to .xlsx
First, I used Excelcnv.exe to convert
if (System.IO.File.Exists(pstrIPDTemplatePath))
{
string pstrOpenXMLIPDTemplatePath = pstrIPDTemplatePath.Replace(".xls", ".xlsx");
string processArguments = "-oice \"" + pstrIPDTemplatePath + "\" \"" + pstrOpenXMLIPDTemplatePath + "\"";
ProcessStartInfo Excelcnv = new ProcessStartInfo();
Excelcnv.FileName = mstrExcelCnvExePath;
Excelcnv.Arguments = processArguments;
Process.Start(Excelcnv);
}
It converted few files successfully but for few files it is creating excelcnv.exe*32 process in task manager, but it is not converting excel file. I even used event handlers for output, but the result is null. Process is going to indefinite state.
But if I am Running it through console application it converted the file successfully it also popped up a dialog after running it to convert multiple files that Excel did not launch correctly and asking whether to start in Safe Mode.
To avoid this safe mode issue, I tried to use ofc.exe
So, I used ofc.exe to convert as below:
Process prc = new Process();
prc.StartInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
prc.StartInfo.FileName = #"OFC.exe";
prc.StartInfo.Arguments = #"ofc.ini";
prc.StartInfo.UseShellExecute = false;
prc.StartInfo.RedirectStandardOutput = true;
prc.Start();
Same case with this code. It is working successfully and converting as expected when running via console application.
It is unable to convert to .xlsx but creating the process in task manager and log file is empty when running using w3wp process hosted in IIS.
Even after giving IIS_IUSRS permission to 'EXE' location, it is not working but its working in console application.
Any ideas why this is happening, and how to get around it?
Try to add your w3wp running user to 'Administrator' group. It will work.
Otherwise use this which is mentioned here
Solidworks generate "EDRWX" files. Usually, those are opened with Microsoft XPS viewer.
Issue :
An application use .net XPSDocument to open them and do some manipulation with them before printing. The faulting method is "GetFixedDocumentSequence". It returns null with files generate from a specific computer. It does so even when the application is running on the specific computer. But it is working fine with file generated by other computer.
When trying to open the file with XPS document viewer, it's fail to open saying it can't be opened. However, it does open on the specific computer that created it. If this computer print a normal XPS file from microsoft word, others computer are able to open it normally with XPS document viewer. Also, "EDRWX" file generated by others computers are easily opened with XPS document viewer on every computer including the specific one.
More specification :
The specific computer run under windows 8.1.
Others computers run under windows 7.
The application run with .net Framework 4.0.
Here is a "EDRWX" dummy file generated by the specific computer.
Here is a "EDRWX" dummy file generated by one of the others computers.
What is the cause of the issue and how can it be fixed?
Sidenote : I have been investigating for almost 3 days....So I'm getting angry at the problem. May be your eyes can see what I don't anymore for being sucked into it this much.
In my digging, I found this difference between the two files.
The failing EDRWX files are not XPS files, they are Open XPS files. The two formats are very similar, however as you have discovered, XPSDocument doesn't support OpenXPS. I am not aware of any .net API that directly supports Open XPS, however microsoft did release standalone converter tools that you may be able to leverage.
Another alternative, which may or may not work, is to try to force SolidWorks to generate xps instead of oxps on the failing machine. It is possible that solidworks is using the xps document writer to generate these files, in which case changing the output format as described here may resolve the issue.
Like Jon pointed out, the issue is that starting with windows8, solidworks use OXPS format no matter what. Changing default format in Group Policy worked for others applications but Solidworks didn't care. So I ended up using the only tool provided by Microsoft thus far to handle the situation. Which is the converter application that come with a windows update package. Once installed, the converting application can be found here :
C:\Program Files (x86)\Windows Kits\8.0\bin
There is a x86 version and a x64 one.
Here is an usage example in the console.
So added the converter appplication next to my application and in my application I silently launch the converter. Here is a method that show how I did it. The method convert the given file to XPS format if necessary. But the resulted conversion must be another file, because the tool can't overwrite the file it is converting.
private string EnsureFileIsUnderXPSFormat(string fileName)
{
string retValue = fileName;
string convertedFileName = System.IO.Path.GetDirectoryName(fileName).TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar + System.IO.Path.GetFileNameWithoutExtension(fileName) + "_converted" + System.IO.Path.GetExtension(fileName);
Version win8version = new Version(6, 2, 9200, 0);
if (Environment.OSVersion.Platform == PlatformID.Win32NT && Environment.OSVersion.Version >= win8version || true)
{
System.Diagnostics.ProcessStartInfo startInfo = new System.Diagnostics.ProcessStartInfo();
startInfo.Arguments = "/XPS /InputFile=" + fileName + " /OutputFile=" + convertedFileName;
string applicationFolderPath = AppDomain.CurrentDomain.BaseDirectory.TrimEnd(System.IO.Path.DirectorySeparatorChar) + System.IO.Path.DirectorySeparatorChar;
startInfo.FileName = applicationFolderPath + "xpsconverter.exe";
//if (Environment.Is64BitOperatingSystem)
// startInfo.FileName = #"C:\Users\maxiveil\Desktop\testConversion\xpsconverter.exe";
//else
// startInfo.FileName = #"C:\Users\maxiveil\Desktop\testConversion\xpsconverter.exe";
startInfo.WindowStyle = System.Diagnostics.ProcessWindowStyle.Hidden;
startInfo.CreateNoWindow = true;
using (System.Diagnostics.Process processus = System.Diagnostics.Process.Start(startInfo))
{
processus.WaitForExit();
if (processus.ExitCode != 0)
{
throw new Exception("Failed to convert OXPS file(" + fileName + ") to XPS format. Error code : " + processus.ExitCode.ToString());
}
}
retValue = convertedFileName;
}
return retValue;
}
N.B : The converter application doesn't care if you try to convert a XPS format file to XPS format file. So the "windows8 if" is optional.
If I have a path of any kind of file (.doc , .pdf , .png ...etc) and I would like to open that file as it is opened via double click (no need to determine the host program). An example of what I mean is: .doc file needs to be opened via MS Word or whatever word processor exists in the machine and it is set as defualt word processor.
http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.useshellexecute.aspx
Process proc = new Process();
proc.StartInfo.FileName = "file.doc";
proc.StartInfo.UseShellExecute = true;
proc.Start();
Use Process.Start and pass the file name as an argument. This requires that the file extension be associated with the correct program.