Fermeture du processus de demande Excel en C# après accès aux données
j'écris une application en C# qui ouvre un fichier de modèle Excel pour les opérations de lecture/écriture. Je veux quand l'utilisateur ferme la demande, le processus de demande excel a été fermé, sans enregistrer le fichier excel. Voir mon Gestionnaire des tâches après plusieurs passages 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 l'accès 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 cette , et des réponses d'essai, mais cela ne fonctionne pas.
15 réponses
essayez ceci:
excelBook.Close(0);
excelApp.Quit();
lors de la fermeture du cahier de travail, vous avez trois paramètres optionnels:
Workbook.close SaveChanges, filename, routeworkbook
Workbook.Close(false)
ou si vous faites une fixation tardive, il est parfois plus facile d'utiliser zéro
Workbook.Close(0)
C'est ce que j'ai fait en automatisant la fermeture des classeurs.
Aussi j'ai regardé la documentation pour elle, et l'a trouvé ici: Classeur Excel Fermer
Merci,
xlBook.Save();
xlBook.Close(true);
xlApp.Quit();
System.Runtime.InteropServices.Marshal.ReleaseComObject(xlApp);
essayez ceci.. il a travaillé pour moi... vous devez libérer cet objet XL application pour arrêter le processus.
pensez à ça, ça 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 { }
}
}
avez-vous essayé de la 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
éviter d'utiliser des expressions à double point, comme ceci:
var workbook = excel.Workbooks.Open(/*params*/)
...parce que de cette façon, vous créez des objets RCW non seulement pour les classeurs, mais aussi pour les classeurs, et vous devriez les publier aussi (ce qui n'est pas possible si une référence à l'objet n'est pas maintenue).
cela a résolu la question pour je. 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 libérer 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);
Je l'enroule dans un try {} finally {}
pour m'assurer que tout est libéré même si quelque chose tourne mal (qu'est-ce qui pourrait mal tourner?) par exemple
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 prend le meilleur conseil de Microsoft ( article de base de MS Knowlege ) sur la façon D'obtenir Excel pour cesser de fumer bien, mais puis s'assure également à ce sujet en tuant le processus si nécessaire. J'aime avoir un second parachute.
assurez-vous de fermer tous les manuels ouverts, quitter l'application et libérer le xlApp objet. Vérifiez enfin si le processus est toujours en vie et si oui, tuez-le.
cet article s'assure également que nous ne tuons pas tous les processus Excel, mais ne tuons que le processus exact qui a été démarré.
Voir aussi obtenir le processus à partir de la poignée de la 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
excelBook.Proche(); excelApp.Quitter(); ajoutez la fin du code, ça pourrait suffire. il travaille sur mon code
j'ai rencontré les mêmes problèmes et j'ai essayé de nombreuses méthodes pour les résoudre mais ça ne marche pas. Enfin , j'ai trouvé ma voie. Quelques référence entrez la description du lien ici
J'espère que mon code peut aider quelqu'un à l'avenir. J'ai été passé plus de deux jours pour le résoudre. Ci-dessous 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();
}
}
}
vous pouvez tuer le processus avec votre propre COM
objet excel pid
ajouter quelque part au-dessous de dll code d'importation
[DllImport("user32.dll", SetLastError = true)]
private static extern int GetWindowThreadProcessId(IntPtr hwnd, ref int lpdwProcessId);
et utilisation
if (excelApp != null)
{
int excelProcessId = -1;
GetWindowThreadProcessId(new IntPtr(excelApp.Hwnd), ref excelProcessId);
Process ExcelProc = Process.GetProcessById(excelProcessId);
if (ExcelProc != null)
{
ExcelProc.Kill();
}
}
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"
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 { }
}
}
basé sur une autre solution. Je l'ai utilisé:
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 { }
}
}
utilisant le "MainWindowHandle" pour identifier le processus et le fermer.
excelObj: C'est mon application Interop excel objecto
utiliser une variable pour chaque objet Excel et doit boucler Marshal.ReleaseComObject >0
. Sans la boucle, le processus Excel reste 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 en convertissant xls en xlsx en utilisant le code suivant. Lorsque nous effectuons ce genre de tâche puis L'application Excel est en cours d'exécution dans le Gestionnaire des tâches, nous devrions fermer cet excel qui est en cours d'exécution en arrière-plan. Interop est un composant Com, pour libérer le composant com que 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);
}
la plupart des méthodes fonctionnent, mais le processus excel reste toujours jusqu'à la fin de l'application.
quand kill excel process une fois qu'il ne peut pas être exécuté une fois de plus dans le même thread - ne sait pas pourquoi.
GetWindowThreadProcessId((IntPtr)app.Hwnd, out iProcessId);
wb.Close(true,Missing.Value,Missing.Value);
app.Quit();
System.Diagnostics.Process[] process = System.Diagnostics.Process.GetProcessesByName("Excel");
foreach (System.Diagnostics.Process p in process)
{
if (p.Id == iProcessId)
{
try
{
p.Kill();
}
catch { }
}
}
}
[DllImport("user32.dll")]
private static extern uint GetWindowThreadProcessId(IntPtr hWnd, out uint lpdwProcessId);
uint iProcessId = 0;
ce GetWindowThreadProcessId trouve le bon Id de processus o excell .... Après le tue.... Profitez-En!!!