|
|
|
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)
|
|
|
|
|