Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations TouchToneTommy on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

terminate winword.exe with vba

Status
Not open for further replies.

marcello62

Technical User
Jun 19, 2006
42
NL
Hi there,

I'm running an app with code to manipulate a word document. The problem is that after running the code, including lines like wordvariablename.close and set wordvariablename = nothing, there are still numerous winword.exe processes active in the windows task manager. Does anyone know if it is possible to terminate these processes from within VBA?

Any help would be greatly appreciated.
 
Can you use something like this?

Code:
Function IsRunning()
 
    Dim strTerminateThis As String 'The variable to hold the process to terminate
    Dim objWMIcimv2 As Object
    Dim objProcess As Object
    Dim objList As Object
    Dim intError As Integer
    Dim blnRunning As Boolean
     
    
DoOver:
    strTerminateThis = "winword.exe" 'Process to terminate,
     'change notepad.exe to the process you want to terminate
     
    Set objWMIcimv2 = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\.\root\cimv2") 'Connect to CIMV2 Namespace
     
    Set objList = objWMIcimv2.ExecQuery _
    ("select * from win32_process where name='" & strTerminateThis & "'") 'Find the process to terminate
     
     
    If objList.Count = 0 Then 'If 0 then process isn't running
        blnRunning = False
    
    Else
        blnRunning = True
    End If
 
If blnRunning = True Then
    GoTo DoOver
End If
 
End Function
 
In my experience this issue is caused by not closing the child objects of the application before attempting to quit the application.

You should have something like this:

Code:
    Dim objWordApp as Word.Application
    Dim objWordDoc as Word.Document

    Set objWordApp = New Word.Application
    Set objWordDoc = objWordApp.OpenDocument("Filepath here")

    'Do some stuff with Word documents.
    ...
    ...
    ...

    'Close objects in reverse order of creation
    objWordDoc.Save
    objWordDoc.Close
    Set objWordDoc = Nothing

    objWordApp.Quit
    Set objWordApp = Nothing

(I don't have Office installed on the PC I'm using at the moment, so this code likely doesn't compile!)

If this doesn't solve the problem post your code.

The danger of simply killing the process is the user has another instance of the application, with unsaved work, which gets killed along with all the others. I'm guessing that wouldn't go down too well! :)

If there aren't loads of winword.exe processes I'd be more inclined to leave them running that kill them, however if you absolutely must terminate them I'd use the Shell() function to run the taskkill command.

Ed Metcalfe.

Please do not feed the trolls.....
 
I think the most common reason for this, is usage of unqualified referencing.

Every usage of methods, properties and objects of the automated application, needs to be "anchored" in it's parent object.

Here's a link pertaining to Excel, but the same goes for Word
See if this helps, else we'd probably need to see the code (or at least part of it).

Roy-Vidar
 
Thank you all for your reactions. I think indeed that the Quit statement terminates the winword executable. I was only familiar with the Set .. = nothing and the close statement.

Moxy 1, your code looks great! I tested it tests the active status of all kinds of executables. Do you perhaps know if it is possible to terminate the process you find in code?


 
If your automation code leaves an extra instance of the automated application left in memory, then there is something wrong with the code.

In stead of trying to fix the symptom (kill the instance afterwards), you should, in my opinion, avoid this extra instance in the first place.

It's usually not very hard to do, but can be a bit difficult to spot/find the first times. The link I gave should give some advice, and again, if you can't make it work, we will need to see your code (or at least some parts of it).

Roy-Vidar
 
My code looks like this:

Private Sub cmdSplits_Click()

'Splitsen stageverslagen
'Auteur: Paul Gransbergen

Dim db As Database
Dim rs As Recordset

Set db = CurrentDb()
Set rs = db.OpenRecordset("tblDocInhoud")
DoCmd.SetWarnings False

Dim wordApp As Word.Application
Dim wordDoc As Word.Document
Dim wordGesplitst As Word.Document
Dim transferRange As Word.Range
Dim eerste As String
Dim tmpStr As String
Dim sBestandsnaam As String
Dim sDiscipline As String
Dim sStage As String
Dim nieuweRegel As String
Dim sSql As String
Dim iPos As Integer
Dim iAantalDoc As Integer
Dim i As Integer
Dim iTmp As Integer
Dim j As Integer
Dim iBegin As Integer
Dim iEind As Integer
Dim iVerslagen As Integer
Dim iAantalGevonden As Integer
Dim iDiscipline As Integer
Dim iDoc As Integer
Dim iCounter As Long
Dim lngRegel As Long
Dim iSentences As Long
Dim bSplitsen As Boolean

Me.lblBezig.Visible = True
Me.lblBezig.Caption = "BEZIG ... "

sDiscipline = Me.cboDiscipline.Value
sStage = Me.cboPlaats.Value

If (sDiscipline = "" And sStage = "") Then
MsgBox ("Selecteer eerst een discipline of een stage!")
Exit Sub
End If

iAantalDoc = 0
iAantalGevonden = 0
iAantalVerslagen = Me.txtAantalVerslagen.Value
If sDiscipline <> "" Then iDiscipline = Len(sDiscipline)
iDoc = Len(sDoc)
sDir = Left(sDoc, (iDoc - 26))

Set wordApp = CreateObject("Word.application")
Set wordGesplitst = wordApp.Documents.Add

For j = 1 To iAantalVerslagen

bSplitsen = False
iAantalDoc = iAantalDoc + 1
Set wordDoc = wordApp.Documents.Open(sDoc, , False)
wordApp.Visible = False
sSql = "DELETE * FROM tblDocInhoud"
DoCmd.RunSQL (sSql)
iCounter = wordDoc.Sentences.Count

For i = 1 To iCounter
rs.AddNew
tmpStr = wordDoc.Sentences(i).Text
If i = 1 Then
iBegin = i
sEerste = tmpStr
End If
If ((i > 2) And tmpStr = sEerste) Then
iEind = i - 1
Exit For
End If
rs!positie = i
rs!tekst = tmpStr
rs.Update
If InStr(tmpStr, sDiscipline) <> 0 Then bSplitsen = True
Next i

If bSplitsen = False Then
Set transferRange = wordDoc.Range(wordDoc.Sentences(iBegin).Start, wordDoc.Sentences(iEind).End)
transferRange.Delete
End If

If bSplitsen Then
iAantalGevonden = iAantalGevonden + 1
Set transferRange = wordDoc.Range(wordDoc.Sentences(iBegin).Start, wordDoc.Sentences(iEind).End)
transferRange.Font.Name = "Times New Roman"
transferRange.Font.Size = 10
transferRange.Delete

wordGesplitst.Range(wordGesplitst.Sentences(wordGesplitst.Sentences.Count).Start, wordGesplitst.Sentences(wordGesplitst.Sentences.Count).End).Paste
MsgBox str(wordGesplitst.Sentences.Count)



wordGesplitst.PageSetup.LeftMargin = wordDoc.PageSetup.LeftMargin
wordGesplitst.PageSetup.RightMargin = wordDoc.PageSetup.RightMargin
wordGesplitst.PageSetup.Orientation = wordDoc.PageSetup.Orientation
wordGesplitst.PageSetup.BottomMargin = wordDoc.PageSetup.BottomMargin
wordGesplitst.PageSetup.TopMargin = wordDoc.PageSetup.TopMargin

wordGesplitst.Sentences(1).InsertBefore " " & vbLf
If sDiscipline = "Gyn/Obstetrie" Then sDiscipline = "Gyn_Obstetrie"
sBestandsnaam = sDir + sDiscipline + Trim(str(iAantalGevonden)) + ".docx"

If j = 1 Then lblVoortgang.Caption = lblVoortgang.Caption + "bestand: " + sBestandsnaam + " aangemaakt!"
Me.Repaint
If j > 1 Then lblVoortgang.Caption = lblVoortgang.Caption + vbCrLf + "bestand: " + sBestandsnaam + " aangemaakt!"
Me.Repaint
End If

wordDoc.Close
Set wordDoc = Nothing

Next j

wordGesplitst.SaveAs (sBestandsnaam)
wordGesplitst.Close
Set wordGesplitst = Nothing
wordApp.Quit
Set wordApp = Nothing

lblBezig.Caption = ""

If iAantalGevonden = 0 Then
lblVoortgang.Caption = lblVoortgang.Caption + vbCrLf + "Geen stageverslagen voor " & sDiscipline & " gevonden!"
End If

If iAantalGevonden > 0 Then
lblVoortgang.Caption = lblVoortgang.Caption + vbCrLf
lblVoortgang.Caption = lblVoortgang.Caption + vbCrLf + "Document voor " & sDiscipline & " gesplitst!"
End If

End Sub

Normally speaking, I would say no word instances should be left open? Still, several winword.exe entries appear in my taskmanager....
 
From a _very short_ browse of the code, it looks good.

I don't know, and I won't be able to test until in the evening, but one thought - could it be some race-condition? Perhaps the processes involved in closing the document, dereference etc, might not be finished when the new one is instantiated?

You could try to _test_ using a message box first, just after you close and release the "inner document", then, if that's the case, maybe a DoEvents might do? (there are some negative consequences of DoEvents, but...)

Roy-Vidar
 
Hi there,

I use code for file selection which contains, among others, the following lines:

Dim fDialog As Office.FileDialog
Set fDialog = Application.FileDialog (msoFileDialogFilePicker)
With fDialog
.AllowMultiSelect = False
.Title = "Selecteer de gele lijst"
.Filters.Clear
.Filters.Add "Worddocumenten", "*.DOC; *.DOCX"

This works fine.

Now, I want to use the same method for selecting a directory for output which users can select. They should only be able to select a directory, they should see no files. I can't find out how to accomplish this. Does anyone have an idea?

Any help will be greatly appreciated. Thanks.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top