Hi All!
So you need to print some files from Dynamics AX? And it also has to work in batch?
Below are 2 methods that will help you do just that.
Printing text files using the copy method
This was the first method I used, and it works flawlessly when using text files, such as .txt or .csv files. It also works great on .prn files.
To print such a file, you can simple copy the file to the printer. See example code below.
static void KlFor_PrintUsingCopy(Args _args)
{
// use only for text files
#File
Set permissionSet;
System.Exception interopException;
FileName destinationFileName;
// parameters
Filename fileName = @"C:\text.txt";
PrinterName printername = @"\\PrintServer\YourPrinter";
;
try
{
// combine the destination path using the printer and the filename
new InteropPermission(InteropKind::ClrInterop).assert();
destinationFileName = System.IO.Path::Combine(printerName, System.IO.Path::GetFileName(fileName));
CodeAccessPermission::revertAssert();
// then copy the file
permissionSet = new Set(Types::Class);
permissionSet.add(new FileIOPermission(fileName,#io_write));
permissionSet.add(new FileIOPermission(destinationFileName,#io_write));
permissionSet.add(new InteropPermission(InteropKind::ClrInterop));
CodeAccessPermission::assertMultiple(permissionSet);
System.IO.File::Copy(fileName, destinationFileName);
CodeAccessPermission::revertAssert();
}
catch(Exception::CLRError)
{
// catch CLR errors and show inner exception
interopException = CLRInterop::getLastException();
while (!CLRInterop::isNull(interopException.get_InnerException()))
{
interopException = interopException.get_InnerException();
}
error(strFmt("%1", CLRInterop::getAnyTypeForObject(interopException.get_Message())));
}
}
An easy method, but do not use it on binary file types. Doing this would result in and endless stream of pages with unreadable characters on it. Yes… I’ve tried.
Print any file use System.Diagnostics.Process
A better way to print files is using the System.Diagnostics namespace. This example uses the “printto” verb to print the files to the server. This verb is visible in the context menu when you right click on a file, it will be listed as the option “Print”. Basically we are using Windows this functionality together with file extension associations to automatically print any file type.
A prerequisite is that an application is available that can open and print the files you want to print. If for example you want to print PDF files in batch using this method, you should install PDF reader software on the AOS server.
static void KlFor_PrintUsingSystemDiagnostics(Args _args)
{
#File
System.Diagnostics.ProcessStartInfo processInfo;
System.Diagnostics.Process process;
System.Exception interopException;
// Parameters
Filename fileName = @"C:\text.txt";
PrinterName printername = @"\\PrintServer\YourPrinter";
;
printerName = '"' + printerName + '"';
try
{
// assert permissions
new InteropPermission(InteropKind::ClrInterop).assert();
process = new System.Diagnostics.Process();
processInfo = process.get_StartInfo();
processInfo.set_UseShellExecute(true);
processInfo.set_CreateNoWindow(true);
processInfo.set_FileName(fileName);
// the argument is the printer name
processInfo.set_Arguments(printerName);
// set the verb to printto
processInfo.set_Verb('printto');
processInfo.set_WindowStyle(System.Diagnostics.ProcessWindowStyle::Hidden);
process.Start();
// revert asserted permissions
CodeAccessPermission::revertAssert();
}
catch(Exception::CLRError)
{
interopException = CLRInterop::getLastException();
while (!CLRInterop::isNull(interopException.get_InnerException()))
{
interopException = interopException.get_InnerException();
}
error(strFmt("@RDS10563", fileName, CLRInterop::getAnyTypeForObject(interopException.get_Message())));
}
}
You can use the code above to do many other things .The functionality is similar to shellexecute, only neater. If you are interested in modifying the code for other purposes using other verbs, you can figure out what verbs you can use using the job below. You will notice that the verbs that are available depend on the extension the file is using.
static void KlFor_GetAllVerbsForFile2(Args _args)
{
System.Diagnostics.ProcessStartInfo processInfo;
System.Array verbs;
int i;
List fileNames;
container verbsContainer;
ListEnumerator listEnumerator;
fileNames = new List(Types::String);
fileNames.addEnd(".xlsx");
fileNames.addEnd(".docx");
fileNames.addEnd(".png");
fileNames.addEnd(".txt");
fileNames.addEnd(".pdf");
listEnumerator = fileNames.getEnumerator();
new InteropPermission(InteropKind::ClrInterop).assert();
while(listEnumerator.moveNext())
{
processInfo = new System.Diagnostics.ProcessStartInfo(listEnumerator.current());
verbs = processInfo.get_Verbs();
verbsContainer = conNull();
for( i=0; i<ClrInterop::getAnyTypeForObject(verbs.get_Length()); i++ )
{
verbsContainer += ClrInterop::getAnyTypeForObject(verbs.GetValue(i));
}
info(strFmt("%1 has verbs: %2", listEnumerator.current(), con2Str(verbsContainer)));
}
CodeAccessPermission::revertAssert();
}
It takes a while to figure out how to do these things so hopefully this will save someone the trouble of going through that.
Related
Thomas Lorenzi
on September 25, 2014 at 18:44
Really nice post. Was exactly the one I was look for.
I have an issue when executing the code with System.Diagnostics.Process class on server side on AX2012 R2 CU7
when trying to print a PDF file using adobe acrobat reader. On client side it works like a charm.
The error I get is the following:
c:\test.pdf The specified executable is not a valid application for this OS platform.
Is this code limited to client processing only or should it work also on server/batch side? Maybe I’m missing something.
Any help would be great :-)
Klaas Deforche
on October 9, 2014 at 09:51
Hi Thomas,
It should work on server side. We use it on server (in batch) and it works fine.
However this means that you need software installed on the AOS that prints it, and the aos service account must have access to the file you are trying to print. C:\test.pdf should be on the C drive of the AOS server. In most cases there are more than one AOS so you can not use such paths. It is best practice always to use UNC paths (\\aserver\afolder\etc), especially for security reasons.
Hope this helps :).
Luis
on February 2, 2016 at 20:48
Great post! I’ve implemented it and it works great!
I’m getting a strange error when i send docx files to the default printer. Word raises printer exception, but the document prints great. Any idea? could it be a permissons problem?
Thanks in advance
Trackbacks
on March 19, 2024 at 06:37