在项目开发过程中,有时会需要用到调用第三方程序实现本系统的某一些功能,例如本文中需要使用到的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 == 0) 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); } }</div>
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, -1)) throw new Win32Exception(); } finally { ReleaseProcessHandle(handle); } }</div>
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(0); 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(0, 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, 0, false, NativeMethods.DUPLICATE_SAME_ACCESS | NativeMethods.DUPLICATE_CLOSE_SOURCE)) { throw new Win32Exception(); } #endif // !FEATURE_PAL if (throwIfExited && (access & NativeMethods.PROCESS_QUERY_INFORMATION) != 0) { if (NativeMethods.GetExitCodeProcess(handle, out exitCode) && exitCode != NativeMethods.STILL_ACTIVE) { throw new InvalidOperationException(SR.GetString(SR.ProcessHasExited, processId.ToString(CultureInfo.CurrentCulture))); } } return handle; } }</div>
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 == -1) { output.WaitUtilEOF(); } if( error != null && milliseconds == -1) { error.WaitUtilEOF(); } ReleaseProcessHandle(handle); } if (exited && watchForExit) { RaiseOnExited(); } return exited; }</div>
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, 0, false, NativeMethods.DUPLICATE_SAME_ACCESS); if (!succeeded) { Marshal.ThrowExceptionForHR(Marshal.GetHRForLastWin32Error()); }