J'écris une application en C # qui ouvre un fichier de modèle Excel pour les opérations de lecture/écriture. Je souhaite que lorsque l'utilisateur ferme l'application, le processus d'application Excel a été fermé, sans enregistrer le fichier Excel. Voir mon gestionnaire de tâches après plusieurs exécutions de l'application.
J'utilise ce code pour ouvrir le fichier Excel:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbook excelBook;
excelBook = excelApp.Workbooks.Add(@"C:/pape.xltx");
et pour accéder aux données, j'utilise ce code:
Excel.Worksheet excelSheet = (Worksheet)(excelBook.Worksheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Je vois des questions similaires dans stackoverflow telles que cette question et ceci , et les réponses test, mais cela ne fonctionne pas.
Essaye ça:
excelBook.Close(0);
excelApp.Quit();
Lors de la fermeture du classeur, vous avez trois paramètres facultatifs:
Workbook.close SaveChanges, filename, routeworkbook
Workbook.Close(false)
ou si vous utilisez une liaison tardive, il est parfois plus facile d'utiliser zéro Workbook.Close(0)
C'est ce que j'ai fait lors de l'automatisation de la fermeture des classeurs.
Je suis aussi allé chercher la documentation à ce sujet et je l’ai trouvée ici: Excel Workbook Close
Merci,
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
essayez ceci .. cela a fonctionné pour moi ... vous devriez libérer cet objet application xl pour arrêter le processus.
Pensez-y, cela tue le processus:
System.Diagnostics.Process[] process=System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName))
{
try
{
p.Kill();
}
catch { }
}
}
Aussi, avez-vous essayé de le fermer normalement?
myWorkbook.SaveAs(@"C:/pape.xltx", missing, missing, missing, missing, missing, Microsoft.Office.Interop.Excel.XlSaveAsAccessMode.xlNoChange, missing, missing, missing, missing, missing);
excelBook.Close(null, null, null); // close your workbook
excelApp.Quit(); // exit Excel application
Excel = null; // set to NULL
Réf.: https://stackoverflow.com/a/17367570/132599
Évitez d’utiliser des expressions appelant deux points, telles que:
var workbook = Excel.Workbooks.Open(/*params*/)
... parce que de cette manière, vous créez des objets RCW non seulement pour classeur, mais également pour classeurs, et vous devez également le publier (ce qui est impossible si une référence à l'objet n'est pas conservée).
Cela a résolu le problème pour moi. Votre code devient:
public Excel.Application excelApp = new Excel.Application();
public Excel.Workbooks workbooks;
public Excel.Workbook excelBook;
workbooks = excelApp.Workbooks;
excelBook = workbooks.Add(@"C:/pape.xltx");
...
Excel.Sheets sheets = excelBook.Worksheets;
Excel.Worksheet excelSheet = (Worksheet)(sheets[1]);
excelSheet.DisplayRightToLeft = true;
Range rng;
rng = excelSheet.get_Range("C2");
rng.Value2 = txtName.Text;
Et puis relâchez tous ces objets:
System.Runtime.InteropServices.Marshal.ReleaseComObject(rng);
System.Runtime.InteropServices.Marshal.ReleaseComObject(excelSheet);
System.Runtime.InteropServices.Marshal.ReleaseComObject(sheets);
excelBook .Save();
excelBook .Close(true);
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlBook);
System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
J'emballe ceci dans un try {} finally {}
pour m'assurer que tout est publié, même en cas de problème (que pourrait-il bien se passer?), P. Ex.
public Excel.Application excelApp = null;
public Excel.Workbooks workbooks = null;
...
try
{
excelApp = new Excel.Application();
workbooks = excelApp.Workbooks;
...
}
finally
{
...
if (workbooks != null) System.Runtime.InteropServices.Marshal.ReleaseComObject(workbooks);
excelApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
}
Tuer Excel n'est pas toujours facile. voir cet article: 50 façons de tuer Excel
Cet article tient compte des meilleurs conseils de Microsoft ( Article de base de la base de connaissances Microsoft ) sur la façon de bien arrêter Excel, mais s’assure également que le processus est arrêté si nécessaire. J'aime avoir un deuxième parachute.
Assurez-vous de fermer tous les classeurs ouverts, de quitter l'application et de libérer l'objet xlApp. Enfin, vérifiez si le processus est toujours actif et si c'est le cas, tuez-le.
Cet article garantit également que nous ne supprimons pas tous les processus Excel, mais uniquement le processus exact qui a été démarré.
Voir aussi Obtenir le processus depuis la poignée de fenêtre
Voici le code que j'utilise: (fonctionne à chaque fois)
Sub UsingExcel()
'declare process; will be used later to attach the Excel process
Dim XLProc As Process
'call the sub that will do some work with Excel
'calling Excel in a separate routine will ensure that it is
'out of scope when calling GC.Collect
'this works better especially in debug mode
DoOfficeWork(XLProc)
'Do garbage collection to release the COM pointers
'http://support.Microsoft.com/kb/317109
GC.Collect()
GC.WaitForPendingFinalizers()
'I prefer to have two parachutes when dealing with the Excel process
'this is the last answer if garbage collection were to fail
If Not XLProc Is Nothing AndAlso Not XLProc.HasExited Then
XLProc.Kill()
End If
End Sub
'http://msdn.Microsoft.com/en-us/library/ms633522%28v=vs.85%29.aspx
<System.Runtime.InteropServices.DllImport("user32.dll", SetLastError:=True)> _
Private Shared Function GetWindowThreadProcessId(ByVal hWnd As IntPtr, _
ByRef lpdwProcessId As Integer) As Integer
End Function
Private Sub ExcelWork(ByRef XLProc As Process)
'start the application using late binding
Dim xlApp As Object = CreateObject("Excel.Application")
'or use early binding
'Dim xlApp As Microsoft.Office.Interop.Excel
'get the window handle
Dim xlHWND As Integer = xlApp.hwnd
'this will have the process ID after call to GetWindowThreadProcessId
Dim ProcIdXL As Integer = 0
'get the process ID
GetWindowThreadProcessId(xlHWND, ProcIdXL)
'get the process
XLProc = Process.GetProcessById(ProcIdXL)
'do some work with Excel here using xlApp
'be sure to save and close all workbooks when done
'release all objects used (except xlApp) using NAR(x)
'Quit Excel
xlApp.quit()
'Release
NAR(xlApp)
End Sub
Private Sub NAR(ByVal o As Object)
'http://support.Microsoft.com/kb/317109
Try
While (System.Runtime.InteropServices.Marshal.ReleaseComObject(o) > 0)
End While
Catch
Finally
o = Nothing
End Try
End Sub
Vous pouvez tuer le processus avec votre propre objet COM
Excel pid
ajouter quelque part sous le code d'importation dll
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
et utilise
if (excelApp != null)
{
int excelProcessId = -1;
GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId);
Process ExcelProc = Process.GetProcessById(excelProcessId);
if (ExcelProc != null)
{
ExcelProc.Kill();
}
}
J'ai rencontré les mêmes problèmes et essayé de nombreuses méthodes pour le résoudre mais cela ne fonctionne pas… .. Enfin, j'ai trouvé le moyen. Quelques références entrez la description du lien ici
J'espère que mon code peut aider quelqu'un de l'avenir. J'ai passé plus de deux jours à le résoudre . Voici mon code:
//get current in useing Excel
Process[] excelProcsOld = Process.GetProcessesByName("Excel");
Excel.Application myExcelApp = null;
Excel.Workbooks excelWorkbookTemplate = null;
Excel.Workbook excelWorkbook = null;
try{
//DO sth using myExcelApp , excelWorkbookTemplate, excelWorkbook
}
catch (Exception ex ){
}
finally
{
//Compare the Excel ID and Kill it
Process[] excelProcsNew = Process.GetProcessesByName("Excel");
foreach (Process procNew in excelProcsNew)
{
int exist = 0;
foreach (Process procOld in excelProcsOld)
{
if (procNew.Id == procOld.Id)
{
exist++;
}
}
if (exist == 0)
{
procNew.Kill();
}
}
}
excelBook.Close (); excelApp.Quit (); ajouter la fin du code, cela pourrait être suffisant. ça marche sur mon code
La plupart des méthodes fonctionnent, mais le processus Excel reste toujours jusqu'à la fermeture de l'application.
Lorsque tuer le processus Excel une fois, il ne peut pas être exécuté à nouveau dans le même thread - je ne sais pas pourquoi.
wb.Close();
app.Quit();
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (!string.IsNullOrEmpty(p.ProcessName) && p.StartTime.AddSeconds(+10) > DateTime.Now)
{
try
{
p.Kill();
}
catch { }
}
}
Il ferme le dernier processus de 10 secondes avec le nom "Excel"
Basé sur une autre solution. J'ai utilisé ceci:
IntPtr xAsIntPtr = new IntPtr(excelObj.Application.Hwnd);
excelObj.ActiveWorkbook.Close();
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (p.MainWindowHandle == xAsIntPtr)
{
try
{
p.Kill();
}
catch { }
}
}
Utilisation du "MainWindowHandle" pour identifier le processus et le fermer.
excelObj: Ceci est mon application Interop Excel objet
La bonne façon de fermer tous les processus Excel
var _Excel = new Application();
foreach (Workbook _workbook in _Excel.Workbooks) {
_workbook.Close(0);
}
_Excel.Quit();
_Excel = null;
var process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (var p in process) {
if (!string.IsNullOrEmpty(p.ProcessName)) {
try {
p.Kill();
} catch { }
}
}
Utilisez une variable pour chaque objet Excel et devez boucler Marshal.ReleaseComObject >0
. Sans la boucle, le processus Excel reste toujours actif.
public class test{
private dynamic ExcelObject;
protected dynamic ExcelBook;
protected dynamic ExcelBooks;
protected dynamic ExcelSheet;
public void LoadExcel(string FileName)
{
Type t = Type.GetTypeFromProgID("Excel.Application");
if (t == null) throw new Exception("Excel non installato");
ExcelObject = System.Activator.CreateInstance(t);
ExcelObject.Visible = false;
ExcelObject.DisplayAlerts = false;
ExcelObject.AskToUpdateLinks = false;
ExcelBooks = ExcelObject.Workbooks;
ExcelBook = ExcelBooks.Open(FileName,0,true);
System.Runtime.InteropServices.Marshal.GetActiveObject("Excel.Application");
ExcelSheet = ExcelBook.Sheets[1];
}
private void ReleaseObj(object obj)
{
try
{
int i = 0;
while( System.Runtime.InteropServices.Marshal.ReleaseComObject(obj) > 0)
{
i++;
if (i > 1000) break;
}
obj = null;
}
catch
{
obj = null;
}
finally
{
GC.Collect();
}
}
public void ChiudiExcel() {
System.Threading.Thread.CurrentThread.CurrentCulture = ci;
ReleaseObj(ExcelSheet);
try { ExcelBook.Close(); } catch { }
try { ExcelBooks.Close(); } catch { }
ReleaseObj(ExcelBooks);
try { ExcelObject.Quit(); } catch { }
ReleaseObj(ExcelObject);
}
}
Nous pouvons fermer l'application Excel lors de la conversion de xls en xlsx en utilisant le code suivant: . Lorsque nous effectuons ce type de tâche, l'application Excel s'exécute dans le gestionnaire de tâches. Interop est un composant Com, pour libérer le composant com utilisé, nous avons utilisé Marshal.FinalReleaseComObject.
private void button1_Click(object sender, EventArgs e)
{
Excel03to07("D:\\TestExls\\TestExcelApp.XLS");
}
private void Excel03to07(string fileName)
{
string svfileName = Path.ChangeExtension(fileName, ".xlsx");
object oMissing = Type.Missing;
var app = new Microsoft.Office.Interop.Excel.Application();
var wb = app.Workbooks.Open(fileName, oMissing, oMissing,
oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing, oMissing);
wb.SaveAs(svfileName, XlFileFormat.xlOpenXMLWorkbook, Type.Missing, Type.Missing, Type.Missing, Type.Missing, XlSaveAsAccessMode.xlNoChange, Type.Missing, Type.Missing, Type.Missing, Type.Missing, Type.Missing);
wb.Close(false, Type.Missing, Type.Missing);
app.Quit();
GC.Collect();
Marshal.FinalReleaseComObject(wb);
Marshal.FinalReleaseComObject(app);
}