C#的Process类调用第三方插件实现PDF文件转SWF文件
在项目开发过程中,有时会需要用到调用第三方程序实现本系统的某一些功能,例如本文中需要使用到的swftools插件,那么如何在程序中使用这个插件,并且该插件是如何将PDF文件转化为SWF文件的呢?接下来就会做一个简单的介绍。
在.NET平台中,对C#提供了一个操作对本地和远程的访问进程,使能够启动和停止系统进程。这个类就是System.Diagnostics.Process,我们首先来了解一下该类。
一.解析System.Diagnostics.Process类
在C#中使用Process类可以提供对本地和远程的访问进程,使能够启动和停止系统进程,并且该类可以对系统进程进行管理。该类中的一些常用方法:Start(),Kill(),WaitForExit()等方法;StartInfo,FileName,CreateNoWindow等属性。
1.Start()方法:启动(或重用)此Process组件的StartInfo属性指定的进程资源,并将其与该组件关联。如果启动了进程资源,则为true;如果没有启动新的进程资源(例如,如果重用了现有进程),则为false。
具体介绍一下该方法的实现代码:
///<devdoc>
///<para>
///<seecref='System.Diagnostics.Process'/>如果过程资源被重用而不是启动,重用的进程与此相关联<seecref='System.Diagnostics.Process'/>零件。
///</para>
///</devdoc>
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
publicboolStart(){
Close();
ProcessStartInfostartInfo=StartInfo;
if(startInfo.FileName.Length==0)
thrownewInvalidOperationException(SR.GetString(SR.FileNameMissing));
if(startInfo.UseShellExecute){
#if!FEATURE_PAL
returnStartWithShellExecuteEx(startInfo);
#else
thrownewInvalidOperationException(SR.GetString(SR.net_perm_invalid_val,"StartInfo.UseShellExecute",true));
#endif//!FEATURE_PAL
}else{
returnStartWithCreateProcess(startInfo);
}
}
2.Kill()方法:立即停止关联的进程。Kill强制终止进程,Kill方法将异步执行。在调用Kill方法后,请调用WaitForExit方法等待进程退出,或者检查HasExited属性以确定进程是否已经退出。
具体介绍一下该方法的实现代码:
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
publicvoidKill(){
SafeProcessHandlehandle=null;
try{
handle=GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
if(!NativeMethods.TerminateProcess(handle,-1))
thrownewWin32Exception();
}
finally{
ReleaseProcessHandle(handle);
}
}
SafeProcessHandleGetProcessHandle(intaccess){
returnGetProcessHandle(access,true);
}
///<devdoc>
///获取进程的短期句柄,具有给定的访问权限。
///如果句柄存储在当前进程对象中,则使用它。
///注意,我们存储在当前进程对象中的句柄将具有我们需要的所有访问权限。
///</devdoc>
///<internalonly/>
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine,ResourceScope.Machine)]
SafeProcessHandleGetProcessHandle(intaccess,boolthrowIfExited){
Debug.WriteLineIf(processTracing.TraceVerbose,"GetProcessHandle(access=0x"+access.ToString("X8",CultureInfo.InvariantCulture)+",throwIfExited="+throwIfExited+")");
#ifDEBUG
if(processTracing.TraceVerbose){
StackFramecalledFrom=newStackTrace(true).GetFrame(0);
Debug.WriteLine("calledfrom"+calledFrom.GetFileName()+",line"+calledFrom.GetFileLineNumber());
}
#endif
if(haveProcessHandle){
if(throwIfExited){
//因为hasProcessHandle是true,我们知道我们有进程句柄
//打开时至少要有SYNCHRONIZE访问,所以我们可以等待它
//zerotimeout以查看进程是否已退出。
ProcessWaitHandlewaitHandle=null;
try{
waitHandle=newProcessWaitHandle(m_processHandle);
if(waitHandle.WaitOne(0,false)){
if(haveProcessId)
thrownewInvalidOperationException(SR.GetString(SR.ProcessHasExited,processId.ToString(CultureInfo.CurrentCulture)));
else
thrownewInvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
}
}
finally{
if(waitHandle!=null){
waitHandle.Close();
}
}
}
returnm_processHandle;
}
else{
EnsureState(State.HaveId|State.IsLocal);
SafeProcessHandlehandle=SafeProcessHandle.InvalidHandle;
#if!FEATURE_PAL
handle=ProcessManager.OpenProcess(processId,access,throwIfExited);
#else
IntPtrpseudohandle=NativeMethods.GetCurrentProcess();
//Getarealhandle
if(!NativeMethods.DuplicateHandle(newHandleRef(this,pseudohandle),
newHandleRef(this,pseudohandle),
newHandleRef(this,pseudohandle),
outhandle,
0,
false,
NativeMethods.DUPLICATE_SAME_ACCESS|
NativeMethods.DUPLICATE_CLOSE_SOURCE)){
thrownewWin32Exception();
}
#endif//!FEATURE_PAL
if(throwIfExited&&(access&NativeMethods.PROCESS_QUERY_INFORMATION)!=0){
if(NativeMethods.GetExitCodeProcess(handle,outexitCode)&&exitCode!=NativeMethods.STILL_ACTIVE){
thrownewInvalidOperationException(SR.GetString(SR.ProcessHasExited,processId.ToString(CultureInfo.CurrentCulture)));
}
}
returnhandle;
}
}
3.WaitForExit()方法:指示<seecref='System.Diagnostics.Process'/>组件等待指定的毫秒数,以使相关联的进程退出。
具体介绍一下该方法的实现代码:
publicboolWaitForExit(intmilliseconds){
SafeProcessHandlehandle=null;
boolexited;
ProcessWaitHandleprocessWaitHandle=null;
try{
handle=GetProcessHandle(NativeMethods.SYNCHRONIZE,false);
if(handle.IsInvalid){
exited=true;
}
else{
processWaitHandle=newProcessWaitHandle(handle);
if(processWaitHandle.WaitOne(milliseconds,false)){
exited=true;
signaled=true;
}
else{
exited=false;
signaled=false;
}
}
}
finally{
if(processWaitHandle!=null){
processWaitHandle.Close();
}
//Ifwehaveahardtimeout,wecannotwaitforthestreams
if(output!=null&&milliseconds==-1){
output.WaitUtilEOF();
}
if(error!=null&&milliseconds==-1){
error.WaitUtilEOF();
}
ReleaseProcessHandle(handle);
}
if(exited&&watchForExit){
RaiseOnExited();
}
returnexited;
}
internalProcessWaitHandle(SafeProcessHandleprocessHandle):base(){
SafeWaitHandlewaitHandle=null;
boolsucceeded=NativeMethods.DuplicateHandle(
newHandleRef(this,NativeMethods.GetCurrentProcess()),
processHandle,
newHandleRef(this,NativeMethods.GetCurrentProcess()),
outwaitHandle,
0,
false,
NativeMethods.DUPLICATE_SAME_ACCESS);
if(!succeeded){
Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error());
}
this.SafeWaitHandle=waitHandle;
}
4.StartInfo属性:获取或设置要传递给Process的Start方法的属性。StartInfo表示用于启动进程的一组参数。调用Start时,StartInfo用于指定要启动的进程。唯一必须设置的StartInfo成员是FileName属性。
具体介绍一下该方法的实现代码:
[Browsable(false),DesignerSerializationVisibility(DesignerSerializationVisibility.Content),MonitoringDescription(SR.ProcessStartInfo)]
publicProcessStartInfoStartInfo{
get{
if(startInfo==null){
startInfo=newProcessStartInfo(this);
}
returnstartInfo;
}
[ResourceExposure(ResourceScope.Machine)]
set{
if(value==null){
thrownewArgumentNullException("value");
}
startInfo=value;
}
}
5.CreateNoWindow属性:获取或设置指示是否在新窗口中启动该进程的值。
具体介绍一下该方法的实现代码:
[
DefaultValue(false),
MonitoringDescription(SR.ProcessCreateNoWindow),
NotifyParentProperty(true)
]
publicboolCreateNoWindow{
get{returncreateNoWindow;}
set{createNoWindow=value;}
}
以上简单介绍了该类的三种常用方法和两种常用属性,在实际的开发项目中无须对每个属性方法和属性的底层实现做全面的了解,但建议在学习该类的时候,适当的了解一下某一些类的方法实现,有助于我们很好的掌握该类。
二.如何实现PDF文件转化为SWF文件
在项目如果需要将PDF文件转换为SWF文件,可以在项目中引入Swftools插件,该插件的主要功能:PDF到SWF转换器。每页生成一帧。使您能够在FlashMovie中拥有完全格式化的文本,包括表格,公式,图形等。它基于DerekB.Noonburg的xpdfPDF解析器。
简单介绍一下该插件的常用参数:
-h,–help Printshorthelpmessageandexit 打印帮助信息
-V,–version Printversioninfoandexit 打印版本号
-o,–outputfile.swf Directoutputtofile.swf.Iffile.swfcontains‘13568621′(file13568630.swf),theneachpage指定输出的swf文件名
-P,–passwordpassword Usepasswordfordecipheringthepdf.指定打开pdf的密码
-z,–zlib UseFlash6(MX)zlibcompression.使用Flash6的zlib压缩机制
-i,–ignore Allowspdf2swftochangethedraworderofthepdf.Thismaymakethegenerated允许程序修改pdf的绘制顺序,可能会导致结果与原来有差异
以上是几种常用的参数,具体擦参数列表详见:http://www.swftools.org/。
对实现本次操作的类和插件做了一个简单的介绍,接下来提供一个具体实现该功能的操作方法:
///<summary>
///PDF格式转为SWF
///</summary>
///<paramname="pdfPathParameter">原视频文件地址,如/a/b/c.pdf</param>
///<paramname="swfPathParameter">生成后的FLV文件地址,如/a/b/c.swf</param>
///<paramname="beginpage">转换开始页</param>
///<paramname="endpage">转换结束页</param>
///<paramname="photoQuality">照片质量</param>
///<returns></returns>
publicstaticboolPdfConversionSwf(stringpdfPathParameter,stringswfPathParameter,intbeginpage,intendpage,intphotoQuality)
{
if(string.IsNullOrEmpty(pdfPathParameter))
{
thrownewArgumentNullException(pdfPathParameter);
}
if(string.IsNullOrEmpty(swfPathParameter))
{
thrownewArgumentNullException(swfPathParameter);
}
if(endpage<beginpage)
{
thrownewArgumentException("起始页数大于结束页数");
}
if(photoQuality<=0)
{
thrownewArgumentException("照片质量错误");
}
varexe=HttpContext.Current.Server.MapPath("~/tools/swftools-2013-04-09-1007.exe");
varpdfPath=HttpContext.Current.Server.MapPath(pdfPathParameter);
varswfPath=HttpContext.Current.Server.MapPath(swfPathParameter);
Processp=null;
try
{
if(!File.Exists(exe)||!File.Exists(pdfPath))
{
returnfalse;
}
if(File.Exists(swfPath))
{
File.Delete(swfPath);
}
varsb=newStringBuilder();
sb.Append("\""+pdfPath+"\"");
sb.Append("-o\""+swfPath+"\"");
sb.Append("-sflashversion=9");
sb.Append("-sdisablelinks");
if(endpage>GetPageCount(pdfPath))
{
endpage=GetPageCount(pdfPath);
}
sb.Append("-p"+"\""+beginpage+""+"-"+endpage+"\"");
//SWF中的图片质量
sb.Append("-j"+photoQuality);
varcommand=sb.ToString();
//Process提供对本地和远程的访问进程,使能够启动和停止系统进程。
p=newProcess
{
StartInfo=
{
FileName=exe,
Arguments=command,
WorkingDirectory=HttpContext.Current.Server.MapPath("~/Bin/"),
UseShellExecute=false,
RedirectStandardError=true,
CreateNoWindow=false
}
};
//启动线程
p.Start();
//开始异步读取
p.BeginErrorReadLine();
//等待完成
p.WaitForExit();
//开始同步读取
//p.StandardError.ReadToEnd();
if(!File.Exists(swfPath))
returnfalse;
returntrue;
}
catch(IOExceptionioex)
{
thrownewIOException(ioex.Message);
}
catch(Exceptionex)
{
thrownewException(ex.Message);
}
finally
{
if(p!=null)
{
//关闭进程
p.Close();
//释放资源
p.Dispose();
}
}
}
三.小结
在本文中介绍了在C#中如何操作外部程序和线程的类System.Diagnostics.Process,并介绍了该类的一些常用方法的底层实现代码,如果需要对该类进行详细的了解,可以根据MSDN和.NET底层源码的相关注释和文章进行细致的学习。在介绍完实现操作的类的同时,也对Swftools插件做了一个说明,并列举了相关的参数,如果在项目中有较高的要求,可以根据官方提供的API文档进行重构。
在项目开发中,任何一个功能是无法做法完成所有的功能,在编码功能时,只能尽可能的考虑到方法的通用性,在理解了某一个类和某一个插件的基本原理和使用方法后,可以根据对应的API进行添加新功能。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持毛票票。