Я оставил оригинальный фрагмент кода без изменений, но я воспользовался помощью Эндрю, но в основном помощью моего хорошего друга, который, к сожалению, не подписан на SO.Excel кажется мертвым!Кроме того, он закодировал его так, чтобы он передавал обратно индикатор, сообщающий форме, были ли у него проблемы с Excel или нет.Также дает нам возможность построить максимальное время выполнения для каждого процесса Excel.
Он использовал следующий SO ответ , чтобы помочь избавиться от Excel
1. В планировщикепрограмма
- Переместить таймер туда
- Реализовать код очистки excel в случае, если в vba нет ошибок, и в противоположном случае, когда достигнуто максимальное время выполнения (используйте метод Kill)
- Из планировщика вернуть 0 в приложение форм, если Excel завершил работу нормально, или 1, если он был уничтожен
2. В приложении форм проанализировать возвращаемое значение из планировщика в обработчике событий ProcessExited и включитькнопка и т. д.
Итак, новый планировщик:
using System;
using System.Text;
using System.Runtime.InteropServices;
using System.Diagnostics;
using Excel = Microsoft.Office.Interop.Excel;
using System.Timers;
class Program
{
private const int SLEEP_AMOUNT = 1000;
private const int MAXIMUM_EXECUTION_TIME = 10000;
private Excel.Application excelApp =null;
private Excel.Workbook book =null;
private Timer myTimer;
private int elapsedTime;
private int exitCode=0;
[DllImport("user32.dll", SetLastError =true)]
static extern uint GetWindowThreadProcessId(IntPtr hWnd,out uint lpdwProcessId);
static int Main(string[] args)
{
Program myProgram = newProgram();
myProgram.RunExcelReporting(1);
return myProgram.exitCode;
}
void myTimer_Elapsed(object sender,ElapsedEventArgs e)
{
myTimer.Stop();
elapsedTime += SLEEP_AMOUNT;
if (elapsedTime > MAXIMUM_EXECUTION_TIME)
{
//error in vba or maximum time reached. abort excel and return 1 to the calling windows forms application
GC.Collect();
GC.WaitForPendingFinalizers();
if (book != null)
{
book.Close(false,Type.Missing, Type.Missing);
Marshal.FinalReleaseComObject(book);
book =null;
}
if (excelApp != null)
{
int hWnd = excelApp.Hwnd;
uint processID;
GetWindowThreadProcessId((IntPtr)hWnd,out processID);
if (processID != 0)
Process.GetProcessById((int)processID).Kill();
excelApp =null;
exitCode = 1;
}
}
else
{
myTimer.Start();
}
}
void RunExcelReporting(int x)
{
myTimer =new Timer(SLEEP_AMOUNT);
elapsedTime = 0;
myTimer.Elapsed +=new ElapsedEventHandler(myTimer_Elapsed);
myTimer.Start();
try{
excelApp =new Excel.Application();
excelApp.Visible =true;
book = excelApp.Workbooks.Open(@"c:\jsauto.xlsm");
excelApp.Run("ThisWorkbook.rr");
book.Close(false,Type.Missing, Type.Missing);
}
catch (Exception ex){
Console.WriteLine(ex.ToString());
}
finally
{
//no error in vba and maximum time is not reached. clear excel normally
GC.Collect();
GC.WaitForPendingFinalizers();
if (book != null)
{
try {
book.Close(false,Type.Missing, Type.Missing);
}
catch { }
Marshal.FinalReleaseComObject(book);
}
if (excelApp != null)
{
excelApp.Quit();
Marshal.FinalReleaseComObject(excelApp);
excelApp =null;
}
}
}
}
И новое приложение форм:
public partial class Form1 : Form
{
SqlDataAdapter myAdapt = null;
DataSet mySet =null;
DataTable myTable =null;
public Form1()
{ InitializeComponent();}
privatevoid Form1_Load(object sender,EventArgs e){
InitializeGridView();
}
private Process myProcess;
private void btRunProcessAndRefresh_Click(object sender,EventArgs e)
{
myProcess =new Process();
myProcess.StartInfo.FileName =@"c:\VS2010Projects\ConsoleApplication2\ConsoleApplication4\bin\Debug\ConsoleApplication4.exe";
myProcess.Exited +=new EventHandler(MyProcessExited);
myProcess.EnableRaisingEvents =true;
myProcess.SynchronizingObject =this;
btRunProcessAndRefresh.Enabled =false;
myProcess.Start();
}
privatevoid MyProcessExited(Object source,EventArgs e)
{
InitializeGridView();
btRunProcessAndRefresh.Enabled =true;
if (((Process)source).ExitCode == 1)
{
MessageBox.Show("Excel was aborted");
}
else
{
MessageBox.Show("Excel finished normally");
}
}
private void btnALWAYSWORKS_Click(object sender,EventArgs e) {
InitializeGridView();
}
privatevoid InitializeGridView() {
using (SqlConnection conn =new SqlConnection(@"Data Source=sqliom3;Integrated Security=SSPI;Initial Catalog=CCL"))
{
myAdapt =new SqlDataAdapter("SELECT convert(varchar(25),getdate(),120) CurrentDate", conn);
mySet =new DataSet();
myAdapt.Fill(mySet,"AvailableValues");
myTable = mySet.Tables["AvailableValues"];
this.dataGridViewControlTable.DataSource = myTable;
this.dataGridViewControlTable.AllowUserToOrderColumns =true;
this.dataGridViewControlTable.Refresh();
}
}
}