my application creates a new instance of winword embedded in a windows form.
new Microsoft.Office.Interop.Word.ApplicationClass()
Once the user finishes editing I close the window but the winword instance is still running in the background.
How can I kill that particular instance? I know how to kill all instances running on a machine but this isn't an option.
You need to call
application.Quit()
In your code.
One thing I had to do on my system (it's an excel processing tool) is do a process kill if after the Quit things were still going on.
var openedExcel = System.Diagnostics.Process.GetProcessesByName("EXCEL");
if (openedExcel.Any())
{
foreach (var excel in openedExcel)
{
try { excel.Kill(); }
catch { }
}
}
There are different methods for this (Marshal.ReleaseComObject is the most used I believe).
I suggest you should read the official documentation about releasing Office applications instances. it's available here: Microsoft .NET Development for Microsoft Office / Releasing COM Objects
I Suggest you combine / add to Flaviotsf's answer the following code - which will determine what actual process is on the run:
Process[] myProcList = Process.GetProcesses();
for (int i = 0; i <= myProcList.Length - 1; i ++) {
string strProcessName = myProcList [i].ProcessName;
string strProcessTitle = myProcList [i].MainWindowTitle();
//check for your process name.
if (strProcessName.ToLower().Trim().Contains("access")) {
myProcList [i].Kill();
}
}
Kill particular instance of Winword Document.
foreach (var process in Process.GetProcessesByName("WINWORD"))
{
if (process.MainWindowTitle.Contains("Temp")) // Temp is document name.
process.Kill();
}
Related
I've been trying to create a PPT with C# using something like the code below.
Microsoft.Office.Interop.PowerPoint.Application pptApp = new Microsoft.Office.Interop.PowerPoint.Application();
The problem is, if there's another powerpnt process running, the line of code above doesn't do anything (even when debugging it). The application just hangs infinitely.
Is there a way to be able to generate PPTs without having to kill an existing powerpnt process?
With Aspose.Slides for .NET, you don't need to install PowerPoint to generate presentations with a single line of code:
using (Presentation presentation = new Presentation())
{
// Add content to the presentation here
// ...
presentation.Save("output.pptx", SaveFormat.Pptx); // You can choose many other formats
}
Also, you can see your results by using Online Viewer here.
I work at Aspose.
In NET Framework you can hook into the "Running Object Table" (ROT) and get a running Powerpoint instance using InteropServices.Marshal.
Then you can work with the running instance. If it is not running you can start it.
using System.Runtime.InteropServices;
using PowerPointApp = Microsoft.Office.Interop.PowerPoint.Application;
PowerPointApp ppApp = null;
try
{
var ppType = System.Type.GetTypeFromProgID("PowerPoint.Application");
var ppRaw = Marshal.GetActiveObject("PowerPoint.Application");
ppApp = ppRaw as PowerPointApp;
}
catch
{
}
if (ppApp == null)
{
ppApp = new PowerPointApp();
}
Marshal.GetActiveObject is not available in .NET Core and current .NET 5/6
I have a small issues which i was not able to find any solution on StackOverFlow.
The Situation:
I have an application that automatically opens up EXCEL application. When it opens it right away gives a dialog box that says "The file format and extension of xxx don't match. The file could be corrupted or unsafe..."
I am trying to create an application that focus on this running EXCEL application and hit the "YES" and resave the excel with VERSION 2007 so this error message will not come up again.
Here is what i have so far:
var excelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
var c = excelApp.ActiveDialog;
Not sure how to do a click event on the YES using the excelApp variable.
I also tried through
foreach (Process proc in Process.GetProcesses())
{
if (proc.MainWindowTitle.Contains("Excel"))
....
}
Nov. 06 2017:
This is what i have so far now:
var oExcelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
Process[] processlist = Process.GetProcessesByName("Excel"); //Shows number of running Excel apps
foreach (Process theprocess in processlist) //foreach Excel app running
{
if (oExcelApp.Workbooks.Count >= 0) //for worbooks in each Excel app
{
foreach (Excel.Workbook wkb in oExcelApp.Application.Workbooks)
{
wkb.SaveAs(filePath, Excel.XlFileFormat.xlExcel8);
wkb.Close(true, null, null);
Marshal.FinalReleaseComObject(wkb);
}
oExcelApp.Workbooks.Close();
}
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
oExcelApp.Quit();
Marshal.ReleaseComObject(oExcelApp);
}
This works ONLY If there was no error message at the beginning. If the process automatically opens excel and has error message showing this will throw an exception because the application is busy on the error message.
I don't know of a way to do exactly what you describe -- to intercept a dialog box within the application.
What I think you want to do is have Excel suspend warnings in the first place. You can do this by modifying the DisplayAlerts property to false.
var excelApp = (Excel.Application)Marshal.GetActiveObject("Excel.Application");
excelApp.DisplayAlerts = false;
// This should not give you any warnings
excelApp.Workbooks.Open("c:/cdh/test.xls");
And when you are done, put things back as they were:
excelApp.DisplayAlerts = true;
hi you can create another application in which you can write logic of close alert box of Excel and execute from your main application
foreach (Process proc in Process.GetProcesses())
{
if (proc.MainWindowTitle.Contains("Excel"))
....
},
so no need to user interaction for close this alert box,
and you can save different alert message in database and check if this message come in alert box you can close
Thanks all for your help. I was able to go around this and disable all alerts for Microsoft Excel Application using the REGEDIT. This was the only way to go around this situation. Just posting an answer to help others in the same situation:
REGEDIT Solution (Read near the bottom)
I've created a windows service project that will use the TiffCP exe in order to split any tiff files its found into multiple tiff files. I'm using the code that was given as an example on the site:
public static class SplitTiffImage
{
public static void Main()
{
string[] arguments =
{
#"Sample Data\multipage.tif,1",
"SplitTiffImage_2ndPage.tif"
};
TiffCP.Program.Main(arguments);
Process.Start("SplitTiffImage_2ndPage.tif");
}
}
This works as expected and splits the file. However, a process is created (MSPVIEW.EXE) and I'm unable to access the file because it is being edited in another program. I have to manually kill the process to access it. I've also tried creating the process as a variable and then trying to close or kill it but that doesn't seem to be working either. Any ideas? Thanks.
Edit: I've put this code before accessing the process again and when the service stops and it seems to do the trick. It works but I'm wondering if there is a better way.
Process[] process = Process.GetProcessesByName("MSPVIEW");
if (process.Length > 0)
{
foreach (var p in process)
{
p.Kill();
}
}
Remove the
Process.Start("SplitTiffImage_2ndPage.tif");
from the code above.
The line opens the output in a default viewer. In your case it's Microsoft Office Document Imaging (MSPVIEW.EXE). You clearly don't need the output to be opened in a viewer.
I'm trying to determine whether or not an instance of Excel of running with a particular file open, and if so attach to it so I can control that instance.
I've searched around and the majority of what I've got have come from this question. It has a reference to another site, but unfortunately it's dead for me so I cannot read up on it.
My code so far is;
//Is Excel open?
if (Process.GetProcessesByName("EXCEL").Length != 0)
{
Process[] processes = Process.GetProcesses();
foreach (Process process in processes)
{
//Find the exact Excel instance
if (process.ProcessName.ToString() == "EXCEL" && process.MainWindowTitle == ("Microsoft Excel - " + fileName))
{
//Get the process ID of that instance
int processID = (int)Process.GetProcessById(process.Id).MainWindowHandle;
//Attach to the instance...
Excel.Application existingExcel = (Excel.Application)System.Runtime.InteropServices.Marshal.GetActiveObject(process.Id);
}
}
}
So far I've managed to get the process ID of the instance I want to attach to, but I'm lost when it comes to using that ID.
Any ideas on how to proceed?
Marshal.GetActiveObject() doesn't take a process ID as a parameter. What you want is:
Marshal.GetActiveObject("Excel.Application");
Note that this doesn't require keeping track of the process at all, there just needs to be one.
It gets a lot more complicated if you can have multiple processes and want to attach to a specific one. That is where the answer to the other question comes in.
There is also a good article at http://blogs.msdn.com/b/andreww/archive/2008/11/30/starting-or-connecting-to-office-apps.aspx with a more full description of different ways of launching excel. Note that not all of them are necessarily up to date with Excel 2013, where having a single process for all Excel windows complicates things. For your purposes though, the GetActiveObject solution should be fine.
I'm getting this exception when running some code to add text to a Lucene.net index:
The process cannot access the file
'E:\SomeProject\SomeProject.Webroot\App_Data\Lucene\segments.new'
because it is being used by another
process.
What's the easiest way of finding out what the 'other process' is? (I'm running on Win XP) Here's a stripped down code fragment (the exception is being thrown by the 'AddDocument' line after 50+ iterations) in case that's any help:
using l = Lucene.Net;
public void IndexText(List<TextToIndex> textToIndexList)
{
l.Analysis.Standard.StandardAnalyzer standardAnalyzer =
new l.Analysis.Standard.StandardAnalyzer();
l.Index.IndexWriter indexWriter =
new l.Index.IndexWriter(_LuceneIndexPath, standardAnalyzer, false);
foreach (TextToIndex textToIndex in textToIndexList)
{
l.Documents.Document luceneDoc =
CreateLuceneDoc(textToIndex.TypeId,
textToIndex.TextId,
textToIndex.Text,
textToIndex.Title,
textToIndex.ModifiedDate,
textToIndex.CultureCode);
indexWriter.AddDocument(luceneDoc);
}
indexWriter.Close();
}
You can use sysinternal's (now part of Microsoft) "process explorer" to find out what processes have what files open:
http://technet.microsoft.com/en-us/sysinternals/bb896653.aspx
When you run it, click on the "find handle" button (or from the menu find->find handle), then enter "segments.new" - it will show you any processes that have that file open.
Try "unlocker" http://www.emptyloop.com/unlocker/