如何使用Process对象获取实例

我想要做的是写一个方法来循环所有打开的Excel实例,并找出是否已经打开特定的Excel文件。 如果是这样,那么用打开的文件传出excel实例以作进一步的工作。

我的斗争是如何将一个过程对象转换为一个Excel.Application,以便我可以遍历实例中的工作簿。

我已经通过在类似的post中的答案阅读如何使用进程ID获取Excel实例或Excel实例CLSID? 。 但是,由Mike在他的回答中提到的Andrew Whitechapel 的“Shimmed Automation Add-in”中的“ 获取应用程序对象”一文不能访问。

示例代码:

using System; using System.Diagnostics; using Excel = Microsoft.Office.Interop.Excel; namespace test { public class try { private bool IsExcelOpened(string wbookname, out Excel.Application exApp) { bool isOpened = false; Excel.Application exl=new Excel.Application(); Process[] allopenexcel = Process.GetProcessesByName("EXCEL"); foreach (Process excl in allopenexcel) { exl=MagicConversionFromProcessToExcel(excl) // struggle here, how to do this foreach (Excel.Workbook wb in exl.Workbooks) { if (wb.Name == wbookname) { isOpened = true; break; } } if (isOpened) break; } exApp = exl; return isOpened; } } } 

我创build了一个类,可以遍历所有当前正在运行的Excel实例,还可以通过ProcessID,Hwnd或Process对象查找Application对象。 下面的代码,但检查链接进一步的描述。

http://www.codeproject.com/Tips/1080611/Get-a-Collection-of-All-Running-Excel-Instances

这尚未在所有版本的Excel或Windows上进行testing。


码:

 using System; using System.Collections; using System.Collections.Generic; using System.Diagnostics; using System.Linq; using System.Runtime.InteropServices; //Don't add the entire interop namespace, it will introduce some naming conflicts. using xlApp = Microsoft.Office.Interop.Excel.Application; using xlWin = Microsoft.Office.Interop.Excel.Window; namespace ExcelExtensions { /// <summary> /// Collection of currently running Excel instances. /// </summary> public class ExcelAppCollection : IEnumerable<xlApp> { #region Constructors /// <summary>Initializes a new instance of the /// <see cref="ExcelAppCollection"/> class.</summary> /// <param name="sessionID">Windows sessionID to filter instances by. /// If not assigned, uses current session.</param> public ExcelAppCollection (Int32? sessionID = null) { if (sessionID.HasValue && sessionID.Value < -1) throw new ArgumentOutOfRangeException("sessionID"); this.SessionID = sessionID ?? Process.GetCurrentProcess().SessionId; } #endregion #region Properties /// <summary>Gets the Windows sessionID used to filter instances. /// If -1, uses instances from all sessions.</summary> /// <value>The sessionID.</value> public Int32 SessionID { get; private set; } #endregion #region Accessors /// <summary>Gets the Application associated with a given process.</summary> /// <param name="process">The process.</param> /// <returns>Application associated with process.</returns> /// <exception cref="System.ArgumentNullException">process</exception> public xlApp FromProcess(Process process) { if (process == null) throw new ArgumentNullException("process"); return InnerFromProcess(process); } /// <summary>Gets the Application associated with a given processID.</summary> /// <param name="processID">The process identifier.</param> /// <returns>Application associated with processID.</returns> public xlApp FromProcessID(Int32 processID) { try { return FromProcess(Process.GetProcessById(processID)); } catch (ArgumentException) { return null; } } /// <summary>Get the Application associated with a given window handle.</summary> /// <param name="mainHandle">The window handle.</param> /// <returns>Application associated with window handle.</returns> public xlApp FromMainWindowHandle(Int32 mainHandle) { return InnerFromHandle(ChildHandleFromMainHandle(mainHandle)); } /// <summary>Gets the main instance. </summary> /// <remarks>This is the oldest running instance. /// It will be used if an Excel file is double-clicked in Explorer, etc.</remarks> public xlApp PrimaryInstance { get { try { return Marshal.GetActiveObject(MarshalName) as xlApp; } catch (COMException) { return null; } } } /// <summary>Gets the top most instance.</summary> /// <value>The top most instance.</value> public xlApp TopMostInstance { get { var topMost = GetProcesses() //All Excel processes .Select(p => p.MainWindowHandle) //All Excel main window handles .Select(h => new { h = h, z = GetWindowZ(h) }) //Get (handle, z) pair per instance .Where(x => xz > 0) //Filter hidden instances .OrderBy(x => xz) //Sort by z value .First(); //Lowest z value return FromMainWindowHandle(topMost.h.ToInt32()); } } #endregion #region Methods /// <summary>Returns an enumerator that iterates through the collection.</summary> /// <returns> /// A <see cref="T:System.Collections.Generic.IEnumerator`1" /> /// that can be used to iterate through the collection. /// </returns> public IEnumerator<xlApp> GetEnumerator() { foreach (var p in GetProcesses()) yield return FromProcess(p); } IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } /// <summary>Gets all Excel processes in the current session.</summary> /// <returns>Collection of all Excel processing in the current session.</returns> public IEnumerable<Process> GetProcesses() { IEnumerable<Process> result = Process.GetProcessesByName(ProcessName); if (this.SessionID >= 0) result = result.Where(p => p.SessionId == SessionID); return result; } #endregion //------------Implementation #region Methods private static xlApp InnerFromProcess(Process p) { return InnerFromHandle(ChildHandleFromMainHandle(p.MainWindowHandle.ToInt32())); } private static Int32 ChildHandleFromMainHandle(Int32 mainHandle) { Int32 handle = 0; EnumChildWindows(mainHandle, EnumChildFunc, ref handle); return handle; } private static xlApp InnerFromHandle(Int32 handle) { xlWin win = null; Int32 hr = AccessibleObjectFromWindow(handle, DW_OBJECTID, rrid.ToByteArray(), ref win); return win.Application; } private static Int32 GetWindowZ(IntPtr handle) { var z = 0; for (IntPtr h = handle; h != IntPtr.Zero; h = GetWindow(h, GW_HWNDPREV)) z++; return z; } private static Boolean EnumChildFunc(Int32 hwndChild, ref Int32 lParam) { var buf = new StringBuilder(128); GetClassName(hwndChild, buf, 128); if (buf.ToString() == ComClassName) { lParam = hwndChild; return false; } return true; } #endregion #region Extern Methods [DllImport("Oleacc.dll")] private static extern Int32 AccessibleObjectFromWindow( Int32 hwnd, UInt32 dwObjectID, Byte[] riid, ref xlWin ptr); [DllImport("User32.dll")] private static extern Boolean EnumChildWindows( Int32 hWndParent, EnumChildCallback lpEnumFunc, ref Int32 lParam); [DllImport("User32.dll")] private static extern Int32 GetClassName( Int32 hWnd, StringBuilder lpClassName, Int32 nMaxCount); [DllImport("User32.dll")] private static extern IntPtr GetWindow(IntPtr hWnd, UInt32 uCmd); #endregion #region Constants & delegates private const String MarshalName = "Excel.Application"; private const String ProcessName = "EXCEL"; private const String ComClassName = "EXCEL7"; private const UInt32 DW_OBJECTID = 0xFFFFFFF0; private const UInt32 GW_HWNDPREV = 3; //3 = GW_HWNDPREV //The retrieved handle identifies the window above the specified window in the Z order. //If the specified window is a topmost window, the handle identifies a topmost window. //If the specified window is a top-level window, the handle identifies a top-level window. //If the specified window is a child window, the handle identifies a sibling window. private static Guid rrid = new Guid("{00020400-0000-0000-C000-000000000046}"); private delegate Boolean EnumChildCallback(Int32 hwnd, ref Int32 lParam); #endregion } } 

首先,你可以放心地说,如果Excel没有打开,那么你正在检查的文件没有打开,对吗?

所以,你的程序应该是检查Excel是否在运行。 如果不是,则返回false

如果Excel正在运行,所有需要做的就是为该进程创build一个新的Excel实例,并循环遍历工作簿。 没有必要尝试把这个过程变成一个实例。

 Process[] allopenexcel = Process.GetProcessesByName("EXCEL"); if(allopenexcel.count==0) { isOpened = false; break; } else { foreach (System.Diagnostics.Process excl in allopenexcel) { Excel.Application exl = new Excel.Application(); for (int i = 1; i <= exl.Workbooks.Count; i++) { if (exl.Workbooks(i).FullName == wbookname) { isOpened = true; break; } } exl.Quit(); } }