Invoking SwiftView, SwiftConvert, or SwiftExtract from a Windows program
 

SwiftView Pro Viewer, SwiftConvert, and SwiftExtract are all licensing options for the "sview.exe" program.  All of them can be run in a batch, GUI-less mode with the -c command line option.  PCL analysis, conversion, and extraction operations can be entirely controlled using a single command line invocation. 

Here is sample code to invoke sview.exe from a Windows C, C++, C#/.NET, or Visual Basic application.  The sample C# code use the .NET CreateProcess wrapper object.  You will need to supply your own input and output filenames, and suitable error handling. 


Piped Input

SwiftView and SwiftConvert 8.3 or later support loading a PCL or HPGL document directly from a pipe on Windows or Unix. Because pipes on Windows are not accessed symmetrically with files, piped input is implemented as a distinct file access protocol, similar to http://.

A full description of pipe access is available from tech support, and will soon be added to the manual.  This sample C program shows how to use the feature; compiled versions for linux and Windows can be downloaded here.


Error Handling

SwiftView exit codes other than zero indicate some error.  This sample C/C++/C# code writes a "callback file" containing a log of sview.exe's actions, named by the "callback filename mycbfile" ICS command.  When your code detects an error return from sview.exe, you can easily display a suitable error message to the user by searching the callback file for a line beginning "SVC:ERROR: ". 

The sample VB code collects callbacks via a pipe from the program's stderr and captures any error messages; a similar approach can be used in C, C#, or C++. 

Or, you can map key SwiftView exit codes to your own error codes or messages, following these instructions.


C/C++ invocation

   char cmd[MAX_PATH+1];
   STARTUPINFO si;
   PROCESS_INFORMATION pi;
   memset(&si,0,sizeof(si));
   si.cb = sizeof(si);

   /* Build the desired command line, e.g.: */
   sprintf(cmd, "\"C:\\Program Files\\SwiftView\\sview.exe\" \
-c\"callback filename %s|ldoc %s|save PDF all %s onefile\"",
	   callbackfilename, inputfilename, outputfilename);

   int cpret = CreateProcess(NULL, cmd, NULL, NULL, FALSE,
                             // Suppress the DOS box.
                             CREATE_NO_WINDOW | NORMAL_PRIORITY_CLASS,
                             NULL, NULL, &si, &pi);
   if (!cpret)
   {
      ret = ERROR_FAILED_CREATE_PROCESS;
      goto ERRRET;
   }
   /* Wait for conversion to complete.  This could take a while on big PCL files,
      e.g. 1 million pages/300 pgs/second = 1 hour.  So usually a 20 minute wait will
      be more than enough except for really huge files. */
   if (WaitForSingleObject(pi.hProcess, 1200000) == WAIT_TIMEOUT)
   {
      ret = ERROR_TIMED_OUT;
      /* Note that this does not force a timed out sview to go away.*/
      goto ERRRET;
   }
   int ExitCode;
   /* dwExitCode argument should not be unsigned!  */
   if (!GetExitCodeProcess(pi.hProcess,(DWORD*)&ExitCode))
   {
      ret = ERROR_CHECKING_PROCESS;
      goto ERRRET;
   }
   /* Here are some basic error codes that SwiftView might return,
      mapped to values you will want to define.  See
      exit code list for more error codes. */
	    ret = (ExitCode  == 0) ?      ERROR_OK :
   ret = (ExitCode  == 0) ?      ERROR_OK :
	 (ExitCode  == -94) ?  ERROR_NO_FILE :
	 ((ExitCode == -114) ||
	  (ExitCode == -99)) ? ERROR_NO_MEM : ERROR_SVIEW;
 ERRRET:
   if (cpret)
   {
      DeleteFile(callbackfilename);
      CloseHandle(pi.hProcess);
      CloseHandle(pi.hThread);
   }
   return ret;

	

C#/.NET invocation

Note - this code is only a general example and has not been tested.  Contact us if you need additional assistance.

using System;
using System.Diagnostics;
using System.ComponentModel;

namespace MyProcessSample
{
    class MyProcess
    {
        int StartSview()
        {
	    int ret;
	    string args;
	    sprintf(args, "-c\"callback filename %s|ldoc %s|save PDF all %s onefile\"",
		   callbackfilename, inputfilename, outputfilename);
	    // XXX are quotes needed to handle spaces?
            ProcessStartInfo info = new ProcessStartInfo(
				"C:\\Program Files\\SwiftView\\sview.exe", args);
	    info.CreateNoWindow = true;
	    info.UseShellExecute = false;
	    /* This is useful if you start sview without a -c, but has no 
	       effect in this windowless example. */
            info.WindowStyle = ProcessWindowStyle.Minimized;

	    Process Sview = Process.Start(info);
	    if (!Sview)
	       return ERROR_FAILED_CREATE_PROCESS;

	    /* Wait for conversion to complete.  This could take a while on big PCL files,
               e.g. 1 million pages/300 pgs/second = 1 hour.  So usually a 20 minute wait will
               be more than enough except for really huge files. */
	    Sview.WaitForExit(1200000);
	    if (!Sview.HasExited)
	    {
               /* Note that this does not force a timed out sview to go
	          away; CloseMainWindow+Kill can be used, but be careful with
                  Kill! */
	       ret = ERROR_TIMED_OUT;
               goto ERRRET;
            }
	    int ExitCode = Sview.ExitCode;
	    /* Here are some basic error codes that SwiftView might return,
	       mapped to values you will want to define.  See
	       exit code list for more error codes. */
	    ret = (ExitCode  == 0) ?      ERROR_OK :
	          (ExitCode  == -94) ?  ERROR_NO_FILE :
	          ((ExitCode == -114) ||
	           (ExitCode == -99)) ? ERROR_NO_MEM : ERROR_SVIEW;

	 ERRRET:
	    if (Sview)
	       DeleteFile(callbackfilename);
	    return ret;
        }

        static void Main()
        {
	   /* Build the desired command line, e.g.: */
                
           MyProcess myProcess = new MyProcess();
           int errorcode = myProcess.StartSview(cmd);
           /* Handle error values here */
        }    
    }
}
	

Visual Basic invocation

VERSION 1.0 CLASS
BEGIN
  MultiUse = -1  'True
  Persistable = 0  'NotPersistable
  DataBindingBehavior = 0  'vbNone
  DataSourceBehavior  = 0  'vbNone
  MTSTransactionMode  = 0  'NotAnMTSObject
END
Attribute VB_Name = "DosShell"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Option Explicit

Private Declare Function CreatePipe Lib "kernel32" ( _
    phReadPipe As Long, _
    phWritePipe As Long, _
    lpPipeAttributes As Any, _
    ByVal nSize As Long) As Long

Private Declare Function ReadFileEx Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByVal lpBuffer As Any, _
    ByVal nNumberOfBytesToRead As Long, _
    ByVal lpOverlapped As Any, _
    ByVal lpCompletionRoutine As Long) As Long

Private Declare Function ReadFile Lib "kernel32" ( _
    ByVal hFile As Long, _
    ByVal lpBuffer As String, _
    ByVal nNumberOfBytesToRead As Long, _
    lpNumberOfBytesRead As Long, _
    ByVal lpOverlapped As Any) As Long

Private Declare Function WaitForSingleObject Lib "kernel32" _
    (ByVal hProcess As Long, _
    ByVal timeout As Long) As Long
    
Private Declare Function SleepEx Lib "kernel32" _
    (ByVal dwMilliseconds As Long, _
    ByVal bAlertable As Long) As Long

Private Declare Function Sleep Lib "kernel32" ( _
    ByVal timeout As Long) As Long

Private Declare Function GetExitCodeProcess Lib "kernel32" ( _
    ByVal hProcess As Long, _
    ByRef lpExitCode As Long) As Long

Private Type SECURITY_ATTRIBUTES
    nLength As Long
    lpSecurityDescriptor As Long
    bInheritHandle As Long
End Type

Private Type STARTUPINFO
    cb As Long
    lpReserved As Long
    lpDesktop As Long
    lpTitle As Long
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Private Declare Function CreateProcessA Lib "kernel32" ( _
    ByVal lpApplicationName As Long, _
    ByVal lpCommandLine As String, _
    lpProcessAttributes As SECURITY_ATTRIBUTES, _
    lpThreadAttributes As SECURITY_ATTRIBUTES, _
    ByVal bInheritHandles As Long, _
    ByVal dwCreationFlags As Long, _
    ByVal lpEnvironment As Long, _
    ByVal lpCurrentDirectory As Long, _
    lpStartupInfo As STARTUPINFO, _
    lpProcessInformation As PROCESS_INFORMATION) As Long

'Close opened handle
Private Declare Function CloseHandle Lib "kernel32" ( _
    ByVal hHandle As Long) As Long

'Consts for the above functions
Private Const NORMAL_PRIORITY_CLASS = &H20&
Private Const STARTF_USESTDHANDLES = &H100&
Private Const STARTF_USESHOWWINDOW = &H1
Private SCommand As String
Private SOutput As String
'Private Empties

'Event that notify the temporary buffer to the object
Public Event ReceiveOutputs(CommandOutputs As String)

' Invoke a program, collecting it's exit code to ExitCode, and 
' If the program doesn't start, ExitCode is set to -1.  
' 
Public Function ExecuteCommand(Optional SCommand As String, _
                               Optional ByRef ExitCode As Long) As String
    Dim APIReturn As Long
    Dim HReadPipe As Long
    Dim ProcInfo As PROCESS_INFORMATION
    Dim StartInfo As STARTUPINFO
    Dim SecurityAttrib As SECURITY_ATTRIBUTES
    Dim HWritePipe As Long
    Dim LngBytesRead As Long
    Dim StrBuff As String * 10000
    
    ExecuteCommand = "failed to execute command"
    
    'Create the Pipe
    SecurityAttrib.nLength = Len(SecurityAttrib)
    SecurityAttrib.bInheritHandle = 1&
    SecurityAttrib.lpSecurityDescriptor = 0&
    APIReturn = CreatePipe(HReadPipe, HWritePipe, SecurityAttrib, 0)
    If (APIReturn = 0) Then
       ExitCode = -1
       Exit Function
    End If
    
    'Launch the command line application
    StartInfo.cb = Len(StartInfo)
    StartInfo.dwFlags = STARTF_USESTDHANDLES Or STARTF_USESHOWWINDOW
    'Set the StdOutput and the StdError output to the SecurityAttrib Write Pipe handle
    StartInfo.hStdOutput = HWritePipe
    StartInfo.hStdError = HWritePipe
    'Execute the command
    APIReturn = CreateProcessA(0&, SCommand, SecurityAttrib, SecurityAttrib, 1&, _
        NORMAL_PRIORITY_CLASS, 0&, 0&, StartInfo, ProcInfo)
    Convertui.SwiftViewProcess = ProcInfo.hProcess
    Convertui.SwiftViewThread = ProcInfo.hThread
    Convertui.SwiftViewReadPipe = HReadPipe
    If (APIReturn = 0) Then
       ExitCode = -1
       Exit Function
    End If
        
   'Close the hWritePipe
    APIReturn = CloseHandle(HWritePipe)
    SOutput = ""
    
    'Read the ReadPipe handle
    'Empties = 5
    Do
        ' If it's a requirement to process UI events while in this
        ' function, e.g. while an sview error dialog is up, you would need
	' to replace this with ReadFileEx so you can call DoEvents.
        APIReturn = ReadFile(HReadPipe, StrBuff, 10000, LngBytesRead, 0&)
        SOutput = SOutput & Left(StrBuff, LngBytesRead)
        
        'APIReturn = ReadFileEx(HReadPipe, StrBuff, 10000, 0&, 0&)
        'SOutput = SOutput & "*******" & vbCrLf
        'Send data to the object via ReceiveOutputs event
        'If (APIReturn = 0 AND Empties) Then
        '    Empties = Empties - 1
        '    APIReturn = 1
        'End If
        RaiseEvent ReceiveOutputs(Left(StrBuff, LngBytesRead))
        DoEvents
        'MsgBox "got " & LngBytesRead
    Loop While APIReturn <> 0
 
    ' Wait for conversion to complete.  This could take a while on big PCL files,
    ' e.g. 1 million pages/300 pgs/second = 1 hour.  So usually a 20 minute wait will
    ' be more than enough except for really huge files.
    APIReturn = WaitForSingleObject(ProcInfo.hProcess, 1200000)
    If (APIReturn = -1) Then
       'WAIT_FAILED, I hope.
       ExitCode = -1
       ExecuteCommand = SOutput
       Exit Function
    End If

    ' Read anything left on the pipe.  Apparently, if the pipe is closed
    ' before we read again, data is lost, and this code can't collect it.
    Do
        APIReturn = ReadFile(HReadPipe, StrBuff, 10000, LngBytesRead, 0&)
        'APIReturn = ReadFileEx(HReadPipe, StrBuff, 10000, 0&, 0&)
        SOutput = SOutput & Left(StrBuff, LngBytesRead)
        'Send data to the object via ReceiveOutputs event
        RaiseEvent ReceiveOutputs(Left(StrBuff, LngBytesRead))
        DoEvents
        'MsgBox "after wait got " & LngBytesRead
    Loop While APIReturn <> 0

    APIReturn = GetExitCodeProcess(ProcInfo.hProcess, ExitCode)
    If (APIReturn = 0) Then
       ExitCode = -1
       ExecuteCommand = SOutput
       Exit Function
    End If
    'Close the opened handles
    APIReturn = CloseHandle(ProcInfo.hProcess)
    APIReturn = CloseHandle(ProcInfo.hThread)
    APIReturn = CloseHandle(HReadPipe)
    'Return the entire DOS output
    ExecuteCommand = SOutput
    Exit Function
End Function


''''
' Example invocation of SwiftConvert using the above function:
''''

Private Function u_getSviewDir() As String
    u_getSviewDir = GetString(HKEY_CURRENT_USER, _
		    "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\sview.exe", "Path")
    If (u_getSviewDir = "") Then
       u_getSviewDir = GetString(HKEY_CURRENT_USER, _
		    "SOFTWARE\Microsoft\Windows\CurrentVersion", "ProgramFilesDir")
       If (u_getSviewDir = "") Then
          Rem Desparate hardcoded default path  See include/ndgstdui.h
          u_getSviewDir = "C:\Program Files\SwiftView"
       Else
          u_getSviewDir = u_getSviewDir & "\SwiftView"
       End If
    End If
End Function
        
Dim ConvertProg As String
Dim Callbacks As String
Dim ConvertCmd As String
Dim ErrorMsg As String
Dim Msg As String
Dim EndErrorMsg As String

ConvertProg = u_getSviewDir() & "\sview.exe"
' -p sends callbacks to stderr, so we can collect them.
ConvertCmd = """" & ConvertProg & """ -v1 -p _
	 -c""ldoc """"" & FileName & """""|" & _
	    "save " & TypeName & " all """"" & OutFileName & """""" & " onefile" & """"
Callbacks = objdos.ExecuteCommand(ConvertCmd, ExitCode)

If (ExitCode <> 0) Then 
   Msg = "Conversion of " & FileName & " failed " & "(" & ExitCode & ")." & vbCrLf
   ErrorStart = InStr(Callbacks, "SVC:ERROR:") 
   If (ErrorStart = 0) Then
      ErrorMsg = Right(Callbacks, Len(Callbacks) - ErrorStart)
InStr(Callbacks, "SVC:ERROR:") <> 0) 
      ErrorEnd = InStr(ErrorMsg, "SVC:")
      If (ErrorEnd = 0) Then
          ErrorEnd = Len(ErrorMsg)
      End If
      ErrorMsg = Trim(Left(ErrorMsg, ErrorEnd))
      Msg = Msg & "SwiftConvert error message:" & ErrorMsg
   Else
      Msg = Msg & "SwiftConvert error message not available"
   End If
Else
   Msg = Conversion succeeded!"
End If
MsgBox(Msg)

	


SwiftView®, SwiftConvert, SwiftStamp, SwiftExtract, SwiftReprint, SwiftPublish, and LoanDocs®, are trademarks of eLynx
SwiftView, a division of Black Knight Financial Services, 9205 SW Gemini Drive Beaverton, OR 97008 USA
800.720.0196 or +1.971.223.2600
  ©2017 Black Knight Financial Services.