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>
/// <see cref='System.Diagnostics.Process'/>如果过程资源被重用而不是启动,重用的进程与此相关联<see cref ='System.Diagnostics.Process'/>零件。
/// </para>
/// </devdoc>
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
public bool Start() {
Close();
ProcessStartInfo startInfo = StartInfo;
if (startInfo.FileName.Length == )
throw new InvalidOperationException(SR.GetString(SR.FileNameMissing)); if (startInfo.UseShellExecute) {
#if !FEATURE_PAL
return StartWithShellExecuteEx(startInfo);
#else
throw new InvalidOperationException(SR.GetString(SR.net_perm_invalid_val, "StartInfo.UseShellExecute", true));
#endif // !FEATURE_PAL
} else {
return StartWithCreateProcess(startInfo);
}
}
2.Kill()方法:立即停止关联的进程。Kill 强制终止进程,Kill 方法将异步执行。 在调用 Kill 方法后,请调用 WaitForExit 方法等待进程退出,或者检查 HasExited 属性以确定进程是否已经退出。
具体介绍一下该方法的实现代码:
[ResourceExposure(ResourceScope.Machine)]
[ResourceConsumption(ResourceScope.Machine)]
public void Kill() {
SafeProcessHandle handle = null;
try {
handle = GetProcessHandle(NativeMethods.PROCESS_TERMINATE);
if (!NativeMethods.TerminateProcess(handle, -))
throw new Win32Exception();
}
finally {
ReleaseProcessHandle(handle);
}
}
SafeProcessHandle GetProcessHandle(int access) {
return GetProcessHandle(access, true);
}
/// <devdoc>
/// 获取进程的短期句柄,具有给定的访问权限。
///如果句柄存储在当前进程对象中,则使用它。
///注意,我们存储在当前进程对象中的句柄将具有我们需要的所有访问权限。
/// </devdoc>
/// <internalonly/>
[ResourceExposure(ResourceScope.None)]
[ResourceConsumption(ResourceScope.Machine, ResourceScope.Machine)]
SafeProcessHandle GetProcessHandle(int access, bool throwIfExited) {
Debug.WriteLineIf(processTracing.TraceVerbose, "GetProcessHandle(access = 0x" + access.ToString("X8", CultureInfo.InvariantCulture) + ", throwIfExited = " + throwIfExited + ")");
#if DEBUG
if (processTracing.TraceVerbose) {
StackFrame calledFrom = new StackTrace(true).GetFrame();
Debug.WriteLine(" called from " + calledFrom.GetFileName() + ", line " + calledFrom.GetFileLineNumber());
}
#endif
if (haveProcessHandle) {
if (throwIfExited) {
//因为hasProcessHandle是true,我们知道我们有进程句柄
//打开时至少要有SYNCHRONIZE访问,所以我们可以等待它
// zero timeout以查看进程是否已退出。
ProcessWaitHandle waitHandle = null;
try {
waitHandle = new ProcessWaitHandle(m_processHandle);
if (waitHandle.WaitOne(, false)) {
if (haveProcessId)
throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
else
throw new InvalidOperationException(SR.GetString(SR.ProcessHasExitedNoId));
}
}
finally {
if( waitHandle != null) {
waitHandle.Close();
}
}
}
return m_processHandle;
}
else {
EnsureState(State.HaveId | State.IsLocal);
SafeProcessHandle handle = SafeProcessHandle.InvalidHandle;
#if !FEATURE_PAL
handle = ProcessManager.OpenProcess(processId, access, throwIfExited);
#else
IntPtr pseudohandle = NativeMethods.GetCurrentProcess();
// Get a real handle
if (!NativeMethods.DuplicateHandle (new HandleRef(this, pseudohandle),
new HandleRef(this, pseudohandle),
new HandleRef(this, pseudohandle),
out handle,
,
false,
NativeMethods.DUPLICATE_SAME_ACCESS |
NativeMethods.DUPLICATE_CLOSE_SOURCE)) {
throw new Win32Exception();
}
#endif // !FEATURE_PAL
if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != ) {
if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) {
throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture)));
}
}
return handle;
} }
3.WaitForExit()方法:指示<see cref ='System.Diagnostics.Process'/>组件等待指定的毫秒数,以使相关联的进程退出。
具体介绍一下该方法的实现代码:
public bool WaitForExit(int milliseconds) {
SafeProcessHandle handle = null;
bool exited;
ProcessWaitHandle processWaitHandle = null;
try {
handle = GetProcessHandle(NativeMethods.SYNCHRONIZE, false);
if (handle.IsInvalid) {
exited = true;
}
else {
processWaitHandle = new ProcessWaitHandle(handle);
if( processWaitHandle.WaitOne(milliseconds, false)) {
exited = true;
signaled = true;
}
else {
exited = false;
signaled = false;
}
}
}
finally {
if( processWaitHandle != null) {
processWaitHandle.Close();
}
// If we have a hard timeout, we cannot wait for the streams
if( output != null && milliseconds == -) {
output.WaitUtilEOF();
}
if( error != null && milliseconds == -) {
error.WaitUtilEOF();
}
ReleaseProcessHandle(handle);
}
if (exited && watchForExit) {
RaiseOnExited();
}
return exited;
}
internal ProcessWaitHandle( SafeProcessHandle processHandle): base() {
SafeWaitHandle waitHandle = null;
bool succeeded = NativeMethods.DuplicateHandle(
new HandleRef(this, NativeMethods.GetCurrentProcess()),
processHandle,
new HandleRef(this, NativeMethods.GetCurrentProcess()),
out waitHandle,
,
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)]
public ProcessStartInfo StartInfo {
get {
if (startInfo == null) {
startInfo = new ProcessStartInfo(this);
}
return startInfo;
}
[ResourceExposure(ResourceScope.Machine)]
set {
if (value == null) {
throw new ArgumentNullException("value");
}
startInfo = value;
}
}
5.CreateNoWindow属性:获取或设置指示是否在新窗口中启动该进程的值。
具体介绍一下该方法的实现代码:
[
DefaultValue(false),
MonitoringDescription(SR.ProcessCreateNoWindow),
NotifyParentProperty(true)
]
public bool CreateNoWindow {
get { return createNoWindow; }
set { createNoWindow = value; }
}
以上简单介绍了该类的三种常用方法和两种常用属性,在实际的开发项目中无须对每个属性方法和属性的底层实现做全面的了解,但建议在学习该类的时候,适当的了解一下某一些类的方法实现,有助于我们很好的掌握该类。
二.如何实现PDF文件转化为SWF文件
在项目如果需要将PDF文件转换为SWF文件,可以在项目中引入Swftools插件,该插件的主要功能:PDF到SWF转换器。 每页生成一帧。 使您能够在Flash Movie中拥有完全格式化的文本,包括表格,公式,图形等。 它基于Derek B. Noonburg的xpdf PDF解析器。
简单介绍一下该插件的常用参数:
-h , –help Print short help message and exit 打印帮助信息
-V , –version Print version info and exit 打印版本号
-o , –output file.swf Direct output to file.swf. If file.swf contains ‘13568621′ (file13568630.swf), then each page指定输出的swf文件名
-P , –password password Use password for deciphering the pdf.指定打开pdf的密码
-z , –zlib Use Flash 6 (MX) zlib compression.使用Flash 6的zlib压缩机制
-i , –ignore Allows pdf2swf to change the draw order of the pdf. This may make the generated允许程序修改pdf的绘制顺序,可能会导致结果与原来有差异
以上是几种常用的参数,具体擦参数列表详见:http://www.swftools.org/。
对实现本次操作的类和插件做了一个简单的介绍,接下来提供一个具体实现该功能的操作方法:
/// <summary>
/// PDF格式转为SWF
/// </summary>
/// <param name="pdfPathParameter">原视频文件地址,如/a/b/c.pdf</param>
/// <param name="swfPathParameter">生成后的FLV文件地址,如/a/b/c.swf</param>
/// <param name="beginpage">转换开始页</param>
/// <param name="endpage">转换结束页</param>
/// <param name="photoQuality">照片质量</param>
/// <returns></returns>
public static bool PdfConversionSwf(string pdfPathParameter, string swfPathParameter, int beginpage, int endpage, int photoQuality)
{
if (string.IsNullOrEmpty(pdfPathParameter))
{
throw new ArgumentNullException(pdfPathParameter);
}
if (string.IsNullOrEmpty(swfPathParameter))
{
throw new ArgumentNullException(swfPathParameter);
}
if (endpage < beginpage)
{
throw new ArgumentException("起始页数大于结束页数");
}
if (photoQuality <= )
{
throw new ArgumentException("照片质量错误");
}
var exe = HttpContext.Current.Server.MapPath("~/tools/swftools-2013-04-09-1007.exe");
var pdfPath = HttpContext.Current.Server.MapPath(pdfPathParameter);
var swfPath = HttpContext.Current.Server.MapPath(swfPathParameter);
Process p = null;
try
{
if (!File.Exists(exe) || !File.Exists(pdfPath))
{
return false;
}
if (File.Exists(swfPath))
{
File.Delete(swfPath);
}
var sb = new StringBuilder();
sb.Append(" \"" + pdfPath + "\"");
sb.Append(" -o \"" + swfPath + "\"");
sb.Append(" -s flashversion=9");
sb.Append(" -s disablelinks");
if (endpage > GetPageCount(pdfPath))
{
endpage = GetPageCount(pdfPath);
}
sb.Append(" -p " + "\"" + beginpage + "" + "-" + endpage + "\"");
//SWF中的图片质量
sb.Append(" -j " + photoQuality);
var command = sb.ToString();
//Process提供对本地和远程的访问进程,使能够启动和停止系统进程。
p = new Process
{
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))
return false;
return true;
}
catch (IOException ioex)
{
throw new IOException(ioex.Message);
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
finally
{
if (p != null)
{
//关闭进程
p.Close();
//释放资源
p.Dispose();
}
} }
三.小结
在本文中介绍了在C#中如何操作外部程序和线程的类System.Diagnostics.Process,并介绍了该类的一些常用方法的底层实现代码,如果需要对该类进行详细的了解,可以根据MSDN和.NET底层源码的相关注释和文章进行细致的学习。在介绍完实现操作的类的同时,也对Swftools插件做了一个说明,并列举了相关的参数,如果在项目中有较高的要求,可以根据官方提供的API文档进行重构。
在项目开发中,任何一个功能是无法做法完成所有的功能,在编码功能时,只能尽可能的考虑到方法的通用性,在理解了某一个类和某一个插件的基本原理和使用方法后,可以根据对应的API进行添加新功能。
C#的Process类调用第三方插件实现PDF文件转SWF文件的更多相关文章
- C#代码使用Process类调用SWFTools工具
一.Process类调用SWFTools工具将PDF文档转为swf文档 1 string cmdStr = "D:\\SWFTools\\pdf2swf.exe"; string ...
- ThinkPHP自动获取关键词(调用第三方插件)
ThinkPHP自动获取关键词调用在线discuz词库 先按照下图路径放好插件 方法如下 /** * 自动获取关键词(调用第三方插件) * @return [type] [description] * ...
- 利用.Net中Process类调用netstat命令来判断计算端口的使用情况
利用.Net中Process类调用netstat命令来判断计算端口的使用情况: Process p = new Process();p.StartInfo = new ProcessStartInfo ...
- C#使用Process类调用外部程序(转)
在程序开发中,一个程序经常需要去调用其他的程序,C#中Process类正好提供了这样的功能.它提供对本地和远程进程的访问并使您能够启动和停止本地系统进程.一.启动进程实例 Process myProc ...
- Process类调用exe,返回值以及参数空格问题
(方法一)返回值为int fileName为调用的exe路径,入口参数为para,其中多个参数用空格分开,当D:/DD.exe返回值为int类型时. Process p = new Process() ...
- C#的Process类的一些用法
c#之process类相关整理 一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 using System.Diagnostics; using Sys ...
- c#之process类相关整理
一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 using System.Diagnostics; using System.Manageme ...
- 转:Process类的使用
转载自:http://www.oschina.net/code/snippet_119226_6188 一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 ...
- C#使用Process类杀死进程,执行命令等
c#之process类相关整理 一.根据进程名获取进程的用户名? 需要添加对 System.Management.dll 的引用 using System.Diagnostics; using Sys ...
随机推荐
- 读书笔记:JavaScript DOM 编程艺术(第二版)
读完还是能学到很多的基础知识,这里记录下,方便回顾与及时查阅. 内容也有自己的一些补充. JavaScript DOM 编程艺术(第二版) 1.JavaScript简史 JavaScript由Nets ...
- .Net中的AOP系列之构建一个汽车租赁应用
返回<.Net中的AOP>系列学习总目录 本篇目录 开始一个新项目 没有AOP的生活 变更的代价 使用AOP重构 本系列的源码本人已托管于Coding上:点击查看. 本系列的实验环境:VS ...
- C语言 · 矩阵乘法 · 算法训练
问题描述 输入两个矩阵,分别是m*s,s*n大小.输出两个矩阵相乘的结果. 输入格式 第一行,空格隔开的三个正整数m,s,n(均不超过200). 接下来m行,每行s个空格隔开的整数,表示矩阵A(i,j ...
- C# 利用性能计数器监控网络状态
本例是利用C#中的性能计数器(PerformanceCounter)监控网络的状态.并能够直观的展现出来 涉及到的知识点: PerformanceCounter,表示 Windows NT 性能计数器 ...
- 【声明】前方不设坑位,不收费!~ 我为NET狂官方学习计划
发个通知,过段时间学习计划相关的东西就出来了,上次写了篇指引文章后有些好奇心颇重的人跟我说:“发现最近群知识库和技能库更新的频率有点大,这是要放大招的节奏啊!” 很多想学习却不知道如何规划的人想要一个 ...
- HTML5 sessionStorage会话存储
sessionStorage 是HTML5新增的一个会话存储对象,用于临时保存同一窗口(或标签页)的数据,在关闭窗口或标签页之后将会删除这些数据.本篇主要介绍 sessionStorage(会话存储) ...
- [APUE]系统数据文件与信息
一.口令文件 UNIX口令文件包含下表中的各个字段,这些字段包含在 由于历史原因,口令文件是/bin/passwd,而且是一个文本文件,每一行都包括了上表中的七个字段,字段之间用":&quo ...
- 深入理解CSS中的margin负值
前面的话 margin属性在实际中非常常用,也是平时踩坑较多的地方.margin折叠部分相信不少人都因为这样那样的原因中过招.margin负值也是很常用的功能,很多特殊的布局方法都依赖于它.它看似简单 ...
- Linux常用指令指南,终端装逼利器
最近搞了台Macbook Pro,就学习了一下Linux命令,在网上查了些资料,看了本书叫<快乐的 Linux 命令行>,里面涉及到了各个方面的命令. 在此将常用的整理出来,以备将来使用. ...
- React Native环境配置之Windows版本搭建
接近年底了,回想这一年都做了啥,学习了啥,然后突然发现,这一年买了不少书,看是看了,就没有完整看完的.悲催. 然后,最近项目也不是很紧了,所以抽空学习了H5.自学啃书还是很无趣的,虽然Head Fir ...