Programmatically Convert PDF to XPS Document Using MXDW - CodeProject

:

Introduction

This is a hack to programmatically convert PDF documents to XPS documents using Microsoft XPS Document Writer (MXDW).

Using the Code

This approach can be used to convert almost any document to XPS document, provided the 'ProcessStartInfo::Verbs' property of the file supports 'print' or 'printto'. The trick here is to perform UI automation, that's it.

ProcessStartInfo^ info = gcnew ProcessStartInfo( gcnew String(sourcefile));
info->Arguments = "Microsoft XPS Document Writer";
info->UseShellExecute = true;
info->WindowStyle = ProcessWindowStyle::Hidden;
info->CreateNoWindow = false;

for( int i = 0; i < info->Verbs->Length ; i++)
{
    if(info->Verbs[i]->ToString()->Equals("print",StringComparison::OrdinalIgnoreCase))
    {
        info->Verb="print";
        IsPrintable =true;
        break;
    }
}

/* --- Set MXDW as default printer --- */

Process ^ process =  gcnew Process();
process->Start(info);
Edit(targetfile);

/* --- Reset to the original default printer --- */

Some PDF apps exit after issuing print job, few don't. The following must be considered for such a scenario.

/*  wait for 20 sec */
    process->WaitForExit(20000);

/*  commented 'wait for infinite time'.
    since some application don't exit,
    even after they are done.
*/

//  process->WaitForExit();

This is where the UI automation is done. Editing the Text box and mimicking the save button key press.

//edits the filename in text box automatically
void Edit(char * pFileName)
{
    HWND hWnd =0;
    try
    {
        // Find Save File Dialog Box
        do{

            Sleep(1000);
            hWnd = FindWindow(DialogClass, "Save the file as");

        }while(!hWnd);

        GetWnd(hWnd,"Edit","");

    }catch(HWND hChild)
    {
        // Enter file name and mimic key press:
        if(SendMessage(hChild, WM_SETTEXT,NULL, (LPARAM) pFileName) !=0)
        {
            hChild = FindWindowEx(hWnd, NULL, NULL, "&Save");
            SendMessage (hChild, WM_IME_KEYDOWN, 'S', NULL);
        }
    }
    return;
}

Given the parent window handle, GetWnd function traverses through all of its child windows until it finds the one which matches classname and caption provided.

//throws an exception if match is found
void GetWnd( HWND hWnd,char * classname,char * caption)
{
    if( hWnd ==0 || classname[0] == '\0' || caption == '\0')
        return;

    GetWnd ( GetWindow(hWnd,GW_CHILD),classname,caption );
    char Class[50],Text[50];
    GetClassName(hWnd,Class,50);
    GetWindowText(hWnd,Text,50);
    /* throw exception to come out of recursion */
    if ( !strcmp(Class,classname) && !strcmp(Text,caption) )
        throw hWnd;
    GetWnd ( GetWindow(hWnd,GW_HWNDNEXT),classname,caption);
    return;
}

Fixes

Few PDF applications don't close even after issuing print job, causing pdftoxps to wait for infinite time, this was the main intent in commenting 'process.WaitForExit()' earlier. The source code has been modified a bit to address this issue.

Reference