907 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
			
		
		
	
	
			907 lines
		
	
	
		
			30 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
using System;
 | 
						|
using System.Collections.Generic;
 | 
						|
using System.Text;
 | 
						|
using System.Reflection;
 | 
						|
using Microsoft.Win32;
 | 
						|
using System.Windows.Forms;
 | 
						|
using System.Text.RegularExpressions;
 | 
						|
using Read64bitRegistryFrom32bitApp;
 | 
						|
 | 
						|
namespace LBWordLibrary
 | 
						|
{
 | 
						|
	public partial class LBApplicationClass : LBComObject
 | 
						|
	{
 | 
						|
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 | 
						|
		/// <summary>
 | 
						|
		/// This gives the option of specifying Background = false to print in the foreground.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="Background">boolean BackGround
 | 
						|
		/// If true  - document will be printed in the background
 | 
						|
		/// If false - document will be printed in the foreground</param>
 | 
						|
		public void PrintOut(Boolean Background)
 | 
						|
		{
 | 
						|
			InvokeMethod("PrintOut", Background, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value);
 | 
						|
		}
 | 
						|
		public void Quit(bool save)
 | 
						|
		{
 | 
						|
			InvokeMethod("Quit", save, Missing.Value, Missing.Value);
 | 
						|
		}
 | 
						|
		public bool VolianPDFInstalled
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				foreach (string printer in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
 | 
						|
					if (printer == "VolianPDF Writer") return true;
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private static bool? _WordPDFExporterInstalled = null;
 | 
						|
		public static bool WordPDFExporterInstalled
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				if (_WordPDFExporterInstalled == null)
 | 
						|
				{
 | 
						|
					// this is to determine if ExportAsFixedFormat was installed in MSOffice
 | 
						|
					// This key only worked for Vista
 | 
						|
					//RegistryKey key = Registry.ClassesRoot.OpenSubKey(@"Installer\Components\12B306B24E250DD428FC7016B6FB4BD8");
 | 
						|
					// This key works for Windows Vista and Windows 7
 | 
						|
					try
 | 
						|
					{
 | 
						|
						string keyPath = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0E5C161912A2A6C4C93C76678926C56C";
 | 
						|
						bool validKey = RegistryWOW6432.CheckRegKey64Valid(RegHive.HKEY_LOCAL_MACHINE, keyPath);
 | 
						|
						_WordPDFExporterInstalled = validKey;
 | 
						|
						if(!validKey)
 | 
						|
							_MyLog.WarnFormat("MSWord2007 PDF Export Registry Key Missing");
 | 
						|
						//RegistryKey key = Registry.LocalMachine.OpenSubKey(keyPath, RegistryKeyPermissionCheck.ReadSubTree);
 | 
						|
						//if (key == null)
 | 
						|
						//{
 | 
						|
						//  RegistryKey localMachine64 = RegistryKey.OpenBaseKey(RegistryHive.LocalMachine, RegistryView.Registry64);
 | 
						|
						//  key = localMachine64.OpenSubKey(keystring, RegistryKeyPermissionCheck.ReadSubTree);
 | 
						|
						//}
 | 
						|
						//if (key != null)
 | 
						|
						//{
 | 
						|
						//  key.Close();
 | 
						|
						//  _WordPDFExporterInstalled = true;
 | 
						|
						//  return (bool) _WordPDFExporterInstalled;
 | 
						|
						//}
 | 
						|
						//_WordPDFExporterInstalled = FindEXP_PDF();
 | 
						|
						return (bool) _WordPDFExporterInstalled;
 | 
						|
					}
 | 
						|
					catch (Exception ex)
 | 
						|
					{
 | 
						|
						_MyLog.WarnFormat("MSWord2007 PDF Export Registry Key Failure {0} - {1}", ex.GetType().Name, ex.Message);
 | 
						|
						_WordPDFExporterInstalled = false;
 | 
						|
						return (bool) _WordPDFExporterInstalled;
 | 
						|
					}
 | 
						|
 | 
						|
				}
 | 
						|
				return (bool) _WordPDFExporterInstalled;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private static bool FindEXP_PDF()
 | 
						|
		{
 | 
						|
			bool retval = false;
 | 
						|
			DateTime dtStart = DateTime.Now;
 | 
						|
			try
 | 
						|
			{
 | 
						|
				//string keystr = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components\0E5C161912A2A6C4C93C76678926C56C";
 | 
						|
				RegistryKey key = null;
 | 
						|
				string keystr = @"SOFTWARE\Microsoft\Windows\CurrentVersion\Installer\UserData\S-1-5-18\Components";
 | 
						|
				while (key == null && keystr != "")
 | 
						|
				{
 | 
						|
					key = Registry.LocalMachine.OpenSubKey(keystr, RegistryKeyPermissionCheck.ReadSubTree);
 | 
						|
					keystr = keystr.Substring(0, keystr.LastIndexOf("\\"));
 | 
						|
				}
 | 
						|
				if (FindKeys(key, "EXP_PDF.DLL"))
 | 
						|
					retval = true;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				AddKeyFound(string.Format("{0} - {1}", ex.GetType().Name, ex.Message));
 | 
						|
			}
 | 
						|
			finally
 | 
						|
			{
 | 
						|
				DateTime dtEnd = DateTime.Now;
 | 
						|
				TimeSpan ts = TimeSpan.FromTicks(dtEnd.Ticks - dtStart.Ticks);
 | 
						|
				AddKeyFound(string.Format("{0} Seconds", ts.TotalSeconds));
 | 
						|
			}
 | 
						|
			return retval;
 | 
						|
		}
 | 
						|
		private static bool FindKeys(RegistryKey key, string find)
 | 
						|
		{
 | 
						|
			string[] keyNames = key.GetSubKeyNames();
 | 
						|
			foreach (string keyName in keyNames)
 | 
						|
			{
 | 
						|
				using (RegistryKey subKey = key.OpenSubKey(keyName, RegistryKeyPermissionCheck.ReadSubTree))
 | 
						|
				{
 | 
						|
					if (FindKeys(subKey, find)) return true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			if (FindNames(key, find)) return true;
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		private static bool FindNames(RegistryKey key, string find)
 | 
						|
		{
 | 
						|
			string[] names = key.GetValueNames();
 | 
						|
			foreach (string name in names)
 | 
						|
			{
 | 
						|
				if (FindNames(key, name, find)) return true;
 | 
						|
			}
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		private static bool FindNames(RegistryKey key, string name, string find)
 | 
						|
		{
 | 
						|
			RegistryValueKind kind = key.GetValueKind(name);
 | 
						|
			if (kind == RegistryValueKind.String)
 | 
						|
			{
 | 
						|
				string val = (string)key.GetValue(name);
 | 
						|
				if (val.Contains(find))
 | 
						|
				{
 | 
						|
					AddKeyFound(string.Format("'{0}'\r\n Value {1} = '{2}'", key.ToString(), name, val));
 | 
						|
					return true;
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		private static void AddKeyFound(string str)
 | 
						|
		{
 | 
						|
			_MyLog.WarnFormat("RegistryKeySearch: {0}",str);
 | 
						|
		}
 | 
						|
		private bool CanCreatePDFFile(string pdfFileName)
 | 
						|
		{
 | 
						|
			System.IO.FileInfo file = new System.IO.FileInfo(pdfFileName);
 | 
						|
			if (!file.Exists) return true;
 | 
						|
			try
 | 
						|
			{
 | 
						|
				file.Delete();
 | 
						|
				return true;
 | 
						|
			}
 | 
						|
			catch (System.IO.IOException exio)
 | 
						|
			{
 | 
						|
				if (exio.Message.StartsWith("The process cannot access the file")) return false;
 | 
						|
				throw new Exception(string.Format("Cannot Delete PDF file {0}", pdfFileName), exio);
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new Exception(string.Format("Cannot Delete PDF file {0}", pdfFileName), ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private string AvailableFileName(string pdfFileName)
 | 
						|
		{
 | 
						|
			if (CanCreatePDFFile(pdfFileName)) return pdfFileName;
 | 
						|
			string prefix = pdfFileName.Replace(".pdf", "");
 | 
						|
			for (int i = 1; i < 1000; i++)
 | 
						|
			{
 | 
						|
				string newname = string.Format("{0}_{1:000}.PDF", prefix, i);
 | 
						|
				if (CanCreatePDFFile(newname)) return newname;
 | 
						|
			}
 | 
						|
			throw new Exception("Cannot find a name to use");
 | 
						|
		}
 | 
						|
		public string CreatePDF(string pdfFileName, bool openPDF,int DebugStatus)
 | 
						|
		{
 | 
						|
			pdfFileName = CreatePDF(pdfFileName, DebugStatus);
 | 
						|
			if (openPDF) OpenPDF(pdfFileName);
 | 
						|
			return pdfFileName;
 | 
						|
		}
 | 
						|
		static List<System.Diagnostics.Process> _AcrobatProcesses=new List<System.Diagnostics.Process>(); 
 | 
						|
		private static void OpenPDF(string pdfFileName)
 | 
						|
		{
 | 
						|
			_AcrobatProcesses.Add(System.Diagnostics.Process.Start(pdfFileName));
 | 
						|
		}
 | 
						|
		public static void ClosePDFs()
 | 
						|
		{
 | 
						|
			foreach(System.Diagnostics.Process proc in _AcrobatProcesses)
 | 
						|
				if (!proc.HasExited)
 | 
						|
					KillAndWait(proc);
 | 
						|
		}
 | 
						|
		private static void KillAndWait(System.Diagnostics.Process proc)
 | 
						|
		{
 | 
						|
			Console.WriteLine("{0:s.ffff} Killing Adobe", DateTime.Now);
 | 
						|
			DateTime tStart = DateTime.Now;
 | 
						|
			proc.Kill();
 | 
						|
			DateTime tEnd = DateTime.Now.AddMilliseconds(100);
 | 
						|
			while (DateTime.Now < tEnd)
 | 
						|
			{
 | 
						|
				Application.DoEvents();
 | 
						|
			}
 | 
						|
			Console.WriteLine("{0:yyyy-MM-dd HH:mm:ss.ffff} {1:yyyy-MM-dd HH:mm:ss.ffff} {2}", DateTime.Now, proc.ExitTime
 | 
						|
				,TimeSpan.FromTicks(proc.ExitTime.Ticks - tStart.Ticks).TotalMilliseconds);
 | 
						|
		}
 | 
						|
		public string CreatePDF(string pdfFileName, int  DebugStatus)
 | 
						|
		{
 | 
						|
			pdfFileName = AvailableFileName(pdfFileName);
 | 
						|
			if (((int)Convert.ToSingle(Version)) > 12)
 | 
						|
				return CreatePDF2007(pdfFileName, DebugStatus);
 | 
						|
			if (((int)Convert.ToSingle(Version)) == 12 && WordPDFExporterInstalled)
 | 
						|
			{
 | 
						|
				//_MyLog.WarnFormat("Word PDF Exporter Installed - MSWord Version = '{0}'" , Version);
 | 
						|
				return CreatePDF2007(pdfFileName, DebugStatus);
 | 
						|
			}
 | 
						|
			if (VolianPDFInstalled)
 | 
						|
			{
 | 
						|
				_MyLog.WarnFormat("Using VolianPDFWriter - MSWord Version = '{0}'", Version);
 | 
						|
				return CreatePDF2003BG(pdfFileName);
 | 
						|
			}
 | 
						|
			//else // Force PDF Export
 | 
						|
			//{
 | 
						|
			//  _MyLog.WarnFormat("Force PDF Export for Michelle - MSWord Version = '{0}'", Version);
 | 
						|
			//  return CreatePDF2007(pdfFileName, DebugStatus);
 | 
						|
			throw new Exception("No PDF Writer support installed for MS Word sections");
 | 
						|
			//}
 | 
						|
		}
 | 
						|
		public string CreatePDF2003FG(string pdfFileName, bool openPDF)
 | 
						|
		{
 | 
						|
			pdfFileName = CreatePDF2003FG(pdfFileName);
 | 
						|
			if (openPDF) OpenPDF(pdfFileName);
 | 
						|
			return pdfFileName;
 | 
						|
		}
 | 
						|
		public string CreatePDF2003FG(string pdfFileName)
 | 
						|
		{
 | 
						|
			pdfFileName = AvailableFileName(pdfFileName);
 | 
						|
			if (!VolianPDFInstalled)
 | 
						|
				throw new Exception("VolianPDF Writer is not installed properly");
 | 
						|
			try
 | 
						|
			{
 | 
						|
				string printer = ActivePrinter;
 | 
						|
				RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\VolianPDF Writer");
 | 
						|
				key.SetValue("OutputFile", pdfFileName, RegistryValueKind.String);
 | 
						|
				key.SetValue("BypassSaveAs", "1", RegistryValueKind.String);
 | 
						|
				key.Close();
 | 
						|
				ActivePrinter = "VolianPDF Writer";
 | 
						|
				PrintOut(false);
 | 
						|
				ActivePrinter = printer;
 | 
						|
				Registry.CurrentUser.DeleteSubKeyTree(@"Software\VolianPDF Writer");
 | 
						|
				return pdfFileName;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new Exception("Error creating PDF - LBApplicationClass.CreatePDF2003FG", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public string CreatePDF2003BG(string pdfFileName, bool openPDF)
 | 
						|
		{
 | 
						|
			pdfFileName = CreatePDF2003BG(pdfFileName);
 | 
						|
			if (openPDF) OpenPDF(pdfFileName);
 | 
						|
			return pdfFileName;
 | 
						|
		}
 | 
						|
		public string CreatePDF2003BG(string pdfFileName)
 | 
						|
		{
 | 
						|
			pdfFileName = AvailableFileName(pdfFileName);
 | 
						|
			if (!VolianPDFInstalled)
 | 
						|
				throw new Exception("VolianPDF Writer is not installed properly");
 | 
						|
			try
 | 
						|
			{
 | 
						|
				string printer = ActivePrinter;
 | 
						|
				RegistryKey key = Registry.CurrentUser.CreateSubKey(@"Software\VolianPDF Writer");
 | 
						|
				key.SetValue("OutputFile", pdfFileName, RegistryValueKind.String);
 | 
						|
				key.SetValue("BypassSaveAs", "1", RegistryValueKind.String);
 | 
						|
				key.Close();
 | 
						|
				ActivePrinter = "VolianPDF Writer";
 | 
						|
				PrintOut(true);
 | 
						|
				do
 | 
						|
				{
 | 
						|
					//  Console.WriteLine("Background Printing Status = {0}", _MyApp.BackgroundPrintingStatus);
 | 
						|
					Application.DoEvents();
 | 
						|
				} while (BackgroundPrintingStatus == 1);
 | 
						|
				ActivePrinter = printer;
 | 
						|
				Registry.CurrentUser.DeleteSubKeyTree(@"Software\VolianPDF Writer");
 | 
						|
				return pdfFileName;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new Exception("Error creating PDF - LBApplicationClass.CreatePDF2003BG", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public string CreatePDF2007(string pdfFileName, bool openPDF, int DebugStatus)
 | 
						|
		{
 | 
						|
			pdfFileName = CreatePDF2007(pdfFileName, DebugStatus);
 | 
						|
			if (openPDF) OpenPDF(pdfFileName);
 | 
						|
			return pdfFileName;
 | 
						|
		}
 | 
						|
		public string CreatePDF2007(string pdfFileName,int DebugStatus)
 | 
						|
		{
 | 
						|
			pdfFileName = AvailableFileName(pdfFileName);
 | 
						|
			// Removed to support MSWord 2010 and beyond.
 | 
						|
			//if (!WordPDFExporterInstalled)
 | 
						|
			//  throw new Exception("MS Word PDF Exporter is not installed");
 | 
						|
			try
 | 
						|
			{
 | 
						|
				ActiveDocument.ExportAsFixedFormat(pdfFileName, LBWdExportFormat.wdExportFormatPDF, DebugStatus);
 | 
						|
				return pdfFileName;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				throw new Exception("Error creating PDF - LBApplicationClass.CreatePDF2007", ex);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBDocuments
 | 
						|
	{
 | 
						|
		public LBDocumentClass Open(string fileName, Boolean addToRecentFiles)
 | 
						|
		{
 | 
						|
			return Open(fileName, Missing.Value, Missing.Value, addToRecentFiles);
 | 
						|
		}
 | 
						|
		private LBDocumentClass Open(params object[] myParams)
 | 
						|
		{
 | 
						|
			return new LBDocumentClass(InvokeMethod("Open", myParams));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBDocumentClass : LBComObject
 | 
						|
	{
 | 
						|
		public void ExportAsFixedFormat(string OutputFileName, LBWdExportFormat ExportFormat, int DebugStatus)
 | 
						|
		{
 | 
						|
			// iso 19005-1 compliant (PDF/A) [UseISO19005_1] should be set to false. for compare print
 | 
						|
			// iso 19005-1 compliant (PDF/A) [UseISO19005_1] should be set to true for production print
 | 
						|
			InvokeMethod("ExportAsFixedFormat", OutputFileName, ExportFormat, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, DebugStatus == 0, Missing.Value);
 | 
						|
		}
 | 
						|
		private static readonly log4net.ILog _MyLog = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType);
 | 
						|
		public void SaveAs2000(string fileName)
 | 
						|
		{
 | 
						|
			if (fileName.ToUpper().EndsWith("DOC"))
 | 
						|
				SaveAs2000(fileName, LBWdSaveFormat.wdFormatDocument);
 | 
						|
			else if (fileName.ToUpper().EndsWith("RTF"))
 | 
						|
				SaveAs2000(fileName, LBWdSaveFormat.wdFormatRTF);
 | 
						|
			else
 | 
						|
				SaveAs2000(fileName);
 | 
						|
		}
 | 
						|
		public void SaveAs2000(params object[] myParams)
 | 
						|
		{
 | 
						|
			InvokeMethod("SaveAs2000", myParams);
 | 
						|
		}
 | 
						|
		public void SaveAs(string fileName)
 | 
						|
		{
 | 
						|
			if (fileName.ToUpper().EndsWith("DOC"))
 | 
						|
				SaveAs2(fileName, LBWdSaveFormat.wdFormatDocument, Missing.Value, Missing.Value, false);
 | 
						|
			else if (fileName.ToUpper().EndsWith("RTF"))
 | 
						|
				SaveAs2(fileName, LBWdSaveFormat.wdFormatRTF, Missing.Value, Missing.Value, false);
 | 
						|
			else if (fileName.ToUpper().EndsWith("TXT"))
 | 
						|
				SaveAs2(fileName, LBWdSaveFormat.wdFormatDOSText, Missing.Value, Missing.Value, false);
 | 
						|
			else if (fileName.ToUpper().EndsWith("DOCX"))
 | 
						|
				SaveAs2(fileName, LBWdSaveFormat.wdFormatXMLDocument, Missing.Value, Missing.Value, false);
 | 
						|
			else
 | 
						|
				SaveAs2(fileName, Missing.Value, Missing.Value, Missing.Value, false);
 | 
						|
		}
 | 
						|
		public void SaveAs2(params object[] myParams)
 | 
						|
		{
 | 
						|
			InvokeMethod("SaveAs", myParams);
 | 
						|
		}
 | 
						|
		public void SaveAs(string fileName, LBWdSaveFormat format)
 | 
						|
		{
 | 
						|
			SaveAs2(fileName, format, Missing.Value, Missing.Value, false);
 | 
						|
		}
 | 
						|
		public LBRange Range(int Start, int End)
 | 
						|
		{
 | 
						|
			return new LBRange(InvokeMethod("Range", Start, End));
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Length is Pages and Partial Pages
 | 
						|
		/// The integral part is the number of full pages
 | 
						|
		/// The decimal part is the size of the last page divided by 7200 
 | 
						|
		/// (the first two digits should be the number of inches)
 | 
						|
		/// </summary>
 | 
						|
		public float Length
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				ActiveWindow.ActivePane.View.Type = LBWdViewType.wdPrintView;
 | 
						|
				ActiveWindow.View.Type = LBWdViewType.wdPrintView;
 | 
						|
				LBPages myPages = ActiveWindow.ActivePane.Pages;// Start with pages
 | 
						|
				float retval = (float)myPages.Count - 1;
 | 
						|
				LBRange myRange = Range();
 | 
						|
                
 | 
						|
				myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToAbsolute, 0);
 | 
						|
				float mytop = myRange.PageSetup.TopMargin;
 | 
						|
                myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
         //float partial = (float) myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToTextBoundary);
 | 
						|
        // B2018-028  Word 2016  has a different value for the Vertical  Position Relative to the Text Boundary than older version of Word.
 | 
						|
        //            We now need to calculated the last row of text in the PROMS attachment differently.
 | 
						|
        //            We now subtract the TopMargin the Page Setup from the Vertical Position Relative to the Page
 | 
						|
        //            this works with older versions of MS Word as well.
 | 
						|
				float partial = (float)myRange.get_Information(LBWdInformation.wdVerticalPositionRelativeToPage) - mytop;
 | 
						|
				partial += myRange.Font.Size;
 | 
						|
				retval += partial / 7200;
 | 
						|
				return retval;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		public string Ascii
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				LBRange myRange = Range();
 | 
						|
				myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
				myRange.Start = 0;
 | 
						|
				return ReplaceSymbolCharacters(GetRangeText(myRange));
 | 
						|
			}
 | 
						|
		}
 | 
						|
		private static string[] SymbolFontName = { "VolianDraw", "WingDings", "VESymb", "VESymbFix", "Symbol" };
 | 
						|
		private static bool IsSymbolFont(string fontName)
 | 
						|
		{
 | 
						|
			foreach (string symbolFont in SymbolFontName)
 | 
						|
				if (fontName.ToUpper().StartsWith(symbolFont.ToUpper()))
 | 
						|
					return true;
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// If document contains symbol characters, returns problem font.
 | 
						|
		/// </summary>
 | 
						|
		public string FontHasSymbolCharacters
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				LBRange myRange = Range();
 | 
						|
				myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
				myRange.Start = 0;
 | 
						|
				int end = myRange.End;
 | 
						|
				string myText = GetRangeText(myRange);
 | 
						|
				//return _RegFindSymbol.IsMatch(myText);
 | 
						|
				MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
				int offset = 0;
 | 
						|
				List<string> alreadyProcessed = new List<string>();
 | 
						|
				List<string> fontHasSymbols = new List<string>();
 | 
						|
				foreach (Match problem in problems)
 | 
						|
				{
 | 
						|
					if (!alreadyProcessed.Contains(problem.Value))
 | 
						|
						{
 | 
						|
						myRange.Start = problem.Index + offset;
 | 
						|
						myRange.End = problem.Index + problem.Length + offset;
 | 
						|
						int newOffset = FindRangeOffset(myRange, problem, offset, end);
 | 
						|
						string fontName = myRange.Font.Name;
 | 
						|
						if (IsSymbolFont(fontName))
 | 
						|
						{
 | 
						|
							if( !fontHasSymbols.Contains(fontName))
 | 
						|
							{
 | 
						|
								fontHasSymbols.Add(fontName);
 | 
						|
								// Found symbol font
 | 
						|
								_MyLog.InfoFormat("Font '{0}' has Symbols", fontName);
 | 
						|
							}
 | 
						|
							//Console.WriteLine("Font '{0}' has Symbols", myRange.Font.Name);
 | 
						|
							//return true;
 | 
						|
						}
 | 
						|
						else
 | 
						|
							return myRange.Font.Name;
 | 
						|
						offset = newOffset;
 | 
						|
						alreadyProcessed.Add(problem.Value);
 | 
						|
					}
 | 
						|
				}
 | 
						|
				return null;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Debug Tool - Return a string containing a list of the fonts that have symbol characters.
 | 
						|
		/// </summary>
 | 
						|
		public string FontsHaveSymbolCharacters
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				string sep = "";
 | 
						|
				StringBuilder sb = new StringBuilder();
 | 
						|
				List<string> fonts=new List<string>();
 | 
						|
				LBRange myRange = Range();
 | 
						|
				myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
				myRange.Start = 0;
 | 
						|
				int end = myRange.End;
 | 
						|
				string myText = GetRangeText(myRange);
 | 
						|
				//return _RegFindSymbol.IsMatch(myText);
 | 
						|
				MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
				int offset = 0;
 | 
						|
				foreach (Match problem in problems)
 | 
						|
				{
 | 
						|
					myRange.Start = problem.Index + offset;
 | 
						|
					myRange.End = problem.Index + problem.Length + offset;
 | 
						|
					int newOffset = FindRangeOffset(myRange, problem, offset, end);
 | 
						|
					if (!fonts.Contains(myRange.Font.Name))
 | 
						|
					{
 | 
						|
						fonts.Add(myRange.Font.Name);
 | 
						|
						sb.Append(sep + "'" + myRange.Font.Name + "'");
 | 
						|
						sep = ",";
 | 
						|
					}
 | 
						|
					offset = newOffset;
 | 
						|
				}
 | 
						|
				if (sb.Length > 0) return sb.ToString();
 | 
						|
				return null;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Debug Tool - Return a list of symbol characters using VESYMB font.
 | 
						|
		/// </summary>
 | 
						|
		public string FontsHaveSymbolCharacters2
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				try
 | 
						|
				{
 | 
						|
					Dictionary<string, List<int>> fonts = new Dictionary<string, List<int>>();
 | 
						|
					LBRange myRange = Range();
 | 
						|
					myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
					myRange.Start = 0;
 | 
						|
					int end = myRange.End;
 | 
						|
					string myText = GetRangeText(myRange);
 | 
						|
					//return _RegFindSymbol.IsMatch(myText);
 | 
						|
					MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
					int offset = 0;
 | 
						|
					foreach (Match problem in problems)
 | 
						|
					{
 | 
						|
						myRange.Start = problem.Index + offset;
 | 
						|
						myRange.End = problem.Index + problem.Length + offset;
 | 
						|
						int newOffset = FindRangeOffset(myRange, problem, offset, end);
 | 
						|
						string sFont = myRange.Font.Name;
 | 
						|
						if (sFont.ToUpper().StartsWith("VESYM"))
 | 
						|
						{
 | 
						|
							if (!fonts.ContainsKey(sFont))
 | 
						|
							{
 | 
						|
								fonts.Add(sFont, new List<int>());
 | 
						|
							}
 | 
						|
							List<int> symbols = fonts[sFont];
 | 
						|
							string myTextSymb = GetRangeText(myRange);
 | 
						|
							foreach (char c in myTextSymb)
 | 
						|
							{
 | 
						|
								if (!symbols.Contains((int)c))
 | 
						|
									symbols.Add((int)c);
 | 
						|
							}
 | 
						|
						}
 | 
						|
						offset = newOffset;
 | 
						|
					}
 | 
						|
					if (fonts.Count > 0)
 | 
						|
					{
 | 
						|
						string sep = "";
 | 
						|
						StringBuilder sb = new StringBuilder();
 | 
						|
						foreach (string font in fonts.Keys)
 | 
						|
						{
 | 
						|
							sb.Append(sep + "'" + font + "'");
 | 
						|
							sep = ",";
 | 
						|
							foreach (int i in fonts[font])
 | 
						|
							{
 | 
						|
								sb.Append(sep);
 | 
						|
								sb.Append(i);
 | 
						|
							}
 | 
						|
						}
 | 
						|
						return sb.ToString();
 | 
						|
					}
 | 
						|
				}
 | 
						|
				catch (Exception ex)
 | 
						|
				{
 | 
						|
					Console.WriteLine("{0},{1},{2}", ex.GetType().Name, ex.Message, ex.StackTrace);
 | 
						|
				}
 | 
						|
				return null;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	
 | 
						|
		/// <summary>
 | 
						|
		/// Checks to see if the document contains symbol characters
 | 
						|
		/// </summary>
 | 
						|
		/// <returns></returns>
 | 
						|
		public bool HasSymbolCharacters
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				LBRange myRange = Range();
 | 
						|
				myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
				myRange.Start = 0;
 | 
						|
				int end = myRange.End;
 | 
						|
				string myText = GetRangeText(myRange);
 | 
						|
				//return _RegFindSymbol.IsMatch(myText);
 | 
						|
				MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
				int offset = 0;
 | 
						|
				foreach (Match problem in problems)
 | 
						|
				{
 | 
						|
					myRange.Start = problem.Index + offset;
 | 
						|
					myRange.End = problem.Index + problem.Length + offset;
 | 
						|
					int newOffset = FindRangeOffset(myRange, problem, offset, end);
 | 
						|
					if (IsSymbolFont(myRange.Font.Name))
 | 
						|
					{
 | 
						|
						Console.WriteLine("Font '{0}' has Symbols", myRange.Font.Name);
 | 
						|
						//return true;
 | 
						|
					}
 | 
						|
					else
 | 
						|
						return true;
 | 
						|
					offset = newOffset;
 | 
						|
				}
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		Regex _RegFindSymbol = new Regex("[\\uF020-\\uF07F]+");
 | 
						|
		/// <summary>
 | 
						|
		/// FixSymbolCharacters - Fix any symbol characters in the document
 | 
						|
		/// </summary>
 | 
						|
		public void FixSymbolCharacters()
 | 
						|
		{
 | 
						|
			// Set up range object to be used to process text
 | 
						|
			LBRange myRange = Range();
 | 
						|
			myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
			int end = myRange.End;
 | 
						|
			myRange.Start = 0;
 | 
						|
			string myText = GetRangeText(myRange);
 | 
						|
			MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
			int offset = 0;
 | 
						|
			foreach (Match problem in problems)
 | 
						|
			{
 | 
						|
				myRange.Start = problem.Index + offset;
 | 
						|
				myRange.End = problem.Index + problem.Length + offset;
 | 
						|
				int newOffset = FindRangeOffset(myRange, problem, offset, end);
 | 
						|
				if (myRange.Font.Name == "")
 | 
						|
				{
 | 
						|
					int wrdStart = myRange.Start;
 | 
						|
					int wrdEnd = myRange.End;
 | 
						|
					int wrdMiddle = wrdStart;
 | 
						|
					while (myRange.Font.Name == "")
 | 
						|
					{
 | 
						|
						do
 | 
						|
						{
 | 
						|
							myRange.End = ++wrdMiddle;
 | 
						|
						} while(myRange.Font.Name != "");
 | 
						|
						myRange.End = wrdMiddle - 1;
 | 
						|
						ReplaceSymbolCharacters(myRange);
 | 
						|
						myRange.Start = wrdMiddle -1;
 | 
						|
						myRange.End = wrdEnd;
 | 
						|
					}
 | 
						|
					ReplaceSymbolCharacters(myRange);
 | 
						|
				}
 | 
						|
				else
 | 
						|
				{
 | 
						|
					ReplaceSymbolCharacters(myRange);
 | 
						|
				}
 | 
						|
				offset = newOffset;
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Try to fix the first character in the symbol range F000 to F0FF.  If it cannot be
 | 
						|
		/// fixed, it is an indicator that the font is not installed properly.  Regardless of
 | 
						|
		/// whether there is success, the change is undone so that the document will not be
 | 
						|
		/// considered dirty, i.e. will not prompt user for save.
 | 
						|
		/// </summary>
 | 
						|
		/// <returns></returns>
 | 
						|
		public bool AttemptToFixASymbolCharacter()
 | 
						|
		{
 | 
						|
			// Set up range object to be used to process text
 | 
						|
			LBRange myRange = Range();
 | 
						|
			myRange = myRange.GoTo(LBWdGoToItem.wdGoToPercent, LBWdGoToDirection.wdGoToLast, 100);
 | 
						|
			
 | 
						|
			int end = myRange.End;
 | 
						|
			myRange.Start = 0;
 | 
						|
			string myText = GetRangeText(myRange);
 | 
						|
			MatchCollection problems = _RegFindSymbol.Matches(myText);
 | 
						|
			if (problems.Count>0)
 | 
						|
			{
 | 
						|
				Match problem = problems[0];
 | 
						|
				myRange.Start = problem.Index;
 | 
						|
				myRange.End = myRange.Start + 1;
 | 
						|
				if (IsSymbolFont(myRange.Font.Name)) return true;   // if it's a symbol font already, no issue.
 | 
						|
				string before = GetRangeText(myRange);
 | 
						|
				string updated = ReplaceSymbolCharacters(before);
 | 
						|
				myRange.Text = updated;
 | 
						|
				string after = GetRangeText(myRange);
 | 
						|
				Undo(1);
 | 
						|
				//Console.WriteLine("Undo1 results = {0}", tst);
 | 
						|
				//tst = Undo(1);
 | 
						|
				//Console.WriteLine("Undo2 results = {0}", tst);
 | 
						|
				//tst = Undo(1);
 | 
						|
				//Console.WriteLine("Undo3 results = {0}", tst);
 | 
						|
				return (updated == after);
 | 
						|
			}
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Get the Range Text with error handling.  myRange.Text sometimes will get a null reference exception.
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="myRange"></param>
 | 
						|
		/// <returns></returns>
 | 
						|
		internal static string GetRangeText(LBRange myRange)
 | 
						|
		{
 | 
						|
			string text="";
 | 
						|
			try
 | 
						|
			{
 | 
						|
				if (myRange.Start == myRange.End)// If Start and End equal return an empty string.
 | 
						|
					text = "";
 | 
						|
				else 
 | 
						|
					text = myRange.Text;
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				Console.WriteLine("GetRangeText {0} - {1}", ex.GetType().Name, ex.Message);
 | 
						|
			}
 | 
						|
			return text;
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Looks for the problem string and adjusts the range as necessary
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="myRange"></param>
 | 
						|
		/// <param name="problem"></param>
 | 
						|
		/// <param name="offset"></param>
 | 
						|
		/// <param name="end"></param>
 | 
						|
		/// <returns></returns>
 | 
						|
		private int FindRangeOffset(LBRange myRange, Match problem, int offset, int end)
 | 
						|
		{
 | 
						|
			// try to find the string
 | 
						|
			string text = GetRangeText(myRange);
 | 
						|
			if (text != problem.Value)
 | 
						|
			{
 | 
						|
				// Get the entire text starting at the offset of the first match
 | 
						|
				myRange.Start = problem.Index + offset;
 | 
						|
				myRange.End = end;
 | 
						|
				text = GetRangeText(myRange);
 | 
						|
				while (!text.StartsWith(problem.Value))
 | 
						|
				{
 | 
						|
					int newStart = text.IndexOf(problem.Value);// Find the string if it is not at the beginning
 | 
						|
					myRange.Start += myRange.Start == newStart ? newStart + 1 : newStart; // adjust the starting location
 | 
						|
					text = GetRangeText(myRange);// get the text to check
 | 
						|
				}
 | 
						|
				myRange.End = myRange.Start + problem.Length; // assume that the end should be the start plus the length
 | 
						|
				text = GetRangeText(myRange);
 | 
						|
				while (text.Length < problem.Length) // If the result is too short increase the length
 | 
						|
				{
 | 
						|
					myRange.End += (problem.Length - text.Length);
 | 
						|
					text = GetRangeText(myRange);
 | 
						|
				}
 | 
						|
			}
 | 
						|
			return myRange.Start - problem.Index;
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// ReplaceSymbolCharacters Replaces any symbol characters in the specified range
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="myRange"></param>
 | 
						|
		private static void ReplaceSymbolCharacters(LBRange myRange)
 | 
						|
		{
 | 
						|
			try
 | 
						|
			{
 | 
						|
				if (IsSymbolFont(myRange.Font.Name)) 
 | 
						|
					return;
 | 
						|
				string before = GetRangeText(myRange);
 | 
						|
				string updated = ReplaceSymbolCharacters(before);
 | 
						|
				myRange.Text = updated;
 | 
						|
				string after = GetRangeText(myRange);
 | 
						|
				if (after != updated)  // If the Word text doesn't match try including a character before and after and do it again.
 | 
						|
				{
 | 
						|
					Console.WriteLine("'TryEntireRange Failed',{0},{1},'{2}','{3}','{4}'", myRange.Start, myRange.End, before, updated, after);
 | 
						|
					int end = myRange.End;
 | 
						|
					myRange.Start = myRange.Start - 1;
 | 
						|
					myRange.End = end + 1;
 | 
						|
					myRange.Text = ReplaceSymbolCharacters(GetRangeText(myRange));
 | 
						|
					Console.WriteLine("'TryEntireRange Failed',{0},{1},'{2}'", myRange.Start, myRange.End, GetRangeText(myRange));
 | 
						|
				}
 | 
						|
			}
 | 
						|
			catch (Exception ex)
 | 
						|
			{
 | 
						|
				Console.WriteLine("'TryEntireRange Exception',{0},{1},'{2}'", myRange.Start, myRange.End, ex.Message);
 | 
						|
			}
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// ReplaceSymbolCharacters processes the string returned and changes any symbols (0xF0??) to normal characters
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="str"></param>
 | 
						|
		/// <returns></returns>
 | 
						|
		private static string ReplaceSymbolCharacters(string str)
 | 
						|
		{
 | 
						|
			StringBuilder results = new StringBuilder();
 | 
						|
			foreach (char c in str)
 | 
						|
			{
 | 
						|
				if ((c & 0xFF00) == 0xF000)
 | 
						|
					results.Append((char)(c & 0xFF));
 | 
						|
				else
 | 
						|
					results.Append((char)(c));
 | 
						|
			}
 | 
						|
			return results.ToString();
 | 
						|
		}
 | 
						|
		/// <summary>
 | 
						|
		/// Close the document
 | 
						|
		/// </summary>
 | 
						|
		/// <param name="SaveChanges">Save Changes</param>
 | 
						|
		public void Close(bool SaveChanges)
 | 
						|
		{
 | 
						|
			InvokeMethod("Close", SaveChanges, Missing.Value, Missing.Value);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBFind
 | 
						|
	{
 | 
						|
		public void ReplaceAll()
 | 
						|
		{
 | 
						|
			this.Execute(Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value, Missing.Value,
 | 
						|
			 Missing.Value, Missing.Value, Missing.Value, Missing.Value, LBWdReplace.wdReplaceAll, Missing.Value,
 | 
						|
			 Missing.Value, Missing.Value, Missing.Value);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBFontClass : LBComObject
 | 
						|
	{
 | 
						|
		public int TextColor
 | 
						|
		{
 | 
						|
			get { return (int)GetProperty("Color"); }
 | 
						|
			set { SetProperty("Color", value); }
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBRange : LBComObject
 | 
						|
	{
 | 
						|
		public Object get_Information(LBWdInformation info)
 | 
						|
		{
 | 
						|
			return GetProperty("Information", info);
 | 
						|
		}
 | 
						|
		public LBRange GoTo(LBWdGoToItem What, LBWdGoToDirection Which, int Count)
 | 
						|
		{
 | 
						|
			return new LBRange(InvokeMethod("GoTo", What, Which, Count, Missing.Value));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBSelection : LBComObject
 | 
						|
	{
 | 
						|
		public Object get_Information(LBWdInformation info)
 | 
						|
		{
 | 
						|
			return GetProperty("Information", info);
 | 
						|
		}
 | 
						|
		public int MoveStart(LBWdUnits Unit, int Count)
 | 
						|
		{
 | 
						|
			return InvokeMethod("MoveStart", Unit, Count) as int? ?? 0;
 | 
						|
		}
 | 
						|
		public int MoveEnd(LBWdUnits Unit, int Count)
 | 
						|
		{
 | 
						|
			return InvokeMethod("MoveEnd", Unit, Count) as int? ?? 0;
 | 
						|
		}
 | 
						|
		public int EndKey(LBWdUnits Unit, bool Extend)
 | 
						|
		{
 | 
						|
			return InvokeMethod("EndKey", Unit, Extend) as int? ?? 0;
 | 
						|
		}
 | 
						|
		public bool LastWasUpper
 | 
						|
		{
 | 
						|
			get
 | 
						|
			{
 | 
						|
				LBRange myRange = Range;
 | 
						|
				int start = myRange.Start - 1;
 | 
						|
				while (start >= 0)
 | 
						|
				{
 | 
						|
					myRange.Start = start;
 | 
						|
					myRange.End = start + 1;
 | 
						|
					string previous = LBDocumentClass.GetRangeText(myRange);
 | 
						|
					if (Regex.IsMatch(previous, "[A-Z]")) return true;
 | 
						|
					if (Regex.IsMatch(previous, "[a-z]")) return false;
 | 
						|
					start = start - 1;
 | 
						|
				}
 | 
						|
				return false;
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBInlineShapes : LBComObjectList<LBInlineShapes, LBInlineShape> /* Collection */
 | 
						|
	{
 | 
						|
		public LBInlineShape AddPicture(string FileName, LBRange Range)
 | 
						|
		{
 | 
						|
			return new LBInlineShape(InvokeMethod("AddPicture", FileName, false, true, Range));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public partial class LBShapes : LBComObjectList<LBShapes, LBShape> /* Collection */
 | 
						|
	{
 | 
						|
		public LBShape AddPicture(string FileName, float Left, float Top, LBRange Anchor)
 | 
						|
		{
 | 
						|
			return new LBShape(InvokeMethod("AddPicture", FileName, false, true, Left, Top, Missing.Value, Missing.Value, Anchor));
 | 
						|
		}
 | 
						|
		public LBShape AddPicture(string FileName, float Left, float Top)
 | 
						|
		{
 | 
						|
			return new LBShape(InvokeMethod("AddPicture", FileName, false, true, Left, Top, Missing.Value, Missing.Value, Missing.Value));
 | 
						|
		}
 | 
						|
	}
 | 
						|
	public enum LBMsoTriState
 | 
						|
	{
 | 
						|
		msoCTrue = 1,
 | 
						|
		msoFalse = 0,
 | 
						|
		msoTriStateMixed = -2,
 | 
						|
		msoTriStateToggle = -3,
 | 
						|
		msoTrue = -1
 | 
						|
	}
 | 
						|
	//public partial class ProcessKiller
 | 
						|
	//{
 | 
						|
	//  System.Diagnostics.Process _MyProcess;
 | 
						|
	//  private bool _Exited = false;
 | 
						|
	//  public ProcessKiller(System.Diagnostics.Process myProcess)
 | 
						|
	//  {
 | 
						|
	//    _MyProcess = myProcess;
 | 
						|
	//    _MyProcess.Exited += new EventHandler(_MyProcess_Exited);
 | 
						|
	//    _MyProcess.Kill();
 | 
						|
	//    DateTime next = DateTime.Now.AddMilliseconds(200);
 | 
						|
	//    while (DateTime.Now < next)
 | 
						|
	//      Application.DoEvents();
 | 
						|
	//    while (!_Exited)
 | 
						|
	//      Application.DoEvents();
 | 
						|
	//  }
 | 
						|
	//  void _MyProcess_Exited(object sender, EventArgs e)
 | 
						|
	//  {
 | 
						|
	//    Console.WriteLine("Exited");
 | 
						|
	//    _Exited = true;
 | 
						|
	//  }
 | 
						|
	//}
 | 
						|
}
 |