Link to home
Start Free TrialLog in
Avatar of kenadelglass
kenadelglass

asked on

Closing A Notepad file opened with the shell command.

In one of my access programs I create a CSV file and then open it in Notepad using the shell command with a click of a button on my Access form.  I would also like the program to close the Notepad window when the user clicks another button if the file does not get closed manually.  Is there any easy way to close Notepad with VBA?  If yes, please include code..
Thx in advance...
Avatar of Deverill
Deverill

What action do you want to take if there are unsaved changes?

Access really has no direct control over notepad once it starts up.  The only thing I know is to have Windows identify the Notepad process and kill that but that would be ugly and involve Windows API calls and you would lose unsaved changes.  Hopefully someone else has an idea.
Avatar of Jim Dettman (EE MVE)
Send keys is about it.  The Win API would be a better way to go as Deverill suggested.

  As an alternative, you might consider Word as it can be controlled via automation.

Jim.
Avatar of kenadelglass

ASKER

For the program I am writing, there will be no unsaved changes made to the Notepad csv file as changes.  I guess I can use SendKeys.  Does anyone know that name of the Win API that closes a program?  I may want to try it...
Ummm, I have something similar, but not exactly what you want.  Heres some code that allows you to open a process, and then wait for it to finish before continuing.

'This module hosts the ExecCmd
'function, which allows you to
'execute a program, and then wait
'until the process is done, before
'returning to the calling procedure.
'
'*Note - This process works for
'Win95 and WinNT 4.0, except that
'it does not work for control
'panel applets in WinNT 4.0 (ie -
'control.exe xxxx.cpl

Private Type STARTUPINFO
    cb As Long
    lpReserved As String
    lpDesktop As String
    lpTitle As String
    dwX As Long
    dwY As Long
    dwXSize As Long
    dwYSize As Long
    dwXCountChars As Long
    dwYCountChars As Long
    dwFillAttribute As Long
    dwFlags As Long
    wShowWindow As Integer
    cbReserved2 As Integer
    lpReserved2 As Long
    hStdInput As Long
    hStdOutput As Long
    hStdError As Long
End Type

Private Type PROCESS_INFORMATION
    hProcess As Long
    hThread As Long
    dwProcessID As Long
    dwThreadID As Long
End Type

Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal _
    hHandle As Long, ByVal dwMilliseconds As Long) As Long

Private Declare Function CreateProcessA Lib "kernel32" (ByVal _
    lpApplicationName As Long, ByVal lpCommandLine As String, ByVal _
         lpProcessAttributes As Long, ByVal lpThreadAttributes As Long, _
         ByVal bInheritHandles As Long, ByVal dwCreationFlags As Long, _
         ByVal lpEnvironment As Long, ByVal lpCurrentDirectory As Long, _
         lpStartupInfo As STARTUPINFO, lpProcessInformation As _
         PROCESS_INFORMATION) As Long

Private Declare Function CloseHandle Lib "kernel32" (ByVal _
    hObject As Long) As Long

Private Const NORMAL_PRIORITY_CLASS = &H20&
      Private Const INFINITE = -1&

Public Sub ExecCmd(cmdline$)
    Dim proc As PROCESS_INFORMATION
    Dim start As STARTUPINFO

    ' Initialize the STARTUPINFO structure:
    start.cb = Len(start)

    ' Start the shelled application:
    ret& = CreateProcessA(0&, cmdline$, 0&, 0&, 1&, _
    NORMAL_PRIORITY_CLASS, 0&, 0&, start, proc)

    ' Wait for the shelled application to finish:
    ret& = WaitForSingleObject(proc.hProcess, INFINITE)
    ret& = CloseHandle(proc.hProcess)
End Sub

No I think if you have the info in PROCESS_INFORMATION you can then use another API function to kill the process.  However, I looked for it, but could not find it.  Maybe another expert will know.  Hope this points you in the right direction.

:) dapperry
Try this, it should work:

'---------------------------------------
Private Declare Function FindWindow Lib "user32" Alias _
                        "FindWindowA" (ByVal lpClassName As String, _
                                       ByVal lpWindowName As String) As Long
Private Declare Function SendMessage Lib "user32" Alias _
                        "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, _
                                        ByVal wParam As Integer, ByVal lParam As Long) As Long
Private Const WM_DESTROY = &H2


Public Function CloseNotepad() As Boolean
    Dim lHandle As Long, lResult As Long

    lHandle = FindWindow("Notepad", vbNullString)
    lResult = SendMessage(lHandle, WM_DESTROY, 0, 0)
    CloseNotepad = (lResult = 0)
End Function
'--------------------------------------

In stead of vbNullString in the FindWindow call you should use something like:

lHandle = FindWindow("Notepad", "YourFile.csv - Notepad")

The second string should be the title of the notepad window you want to close. NB: This depends on what language version you are using! In a Dutch version this would be "YourFile.csv - Kladblok" (Kladblok = Dutch for Notepad). If you don't specify the caption of the notepad window, I think it will close the first opened notepad window it encounters.
Darn, ever since this 'New Look' thingy my code doesn't fit in the windows anymore. Are we back to 640x480? Anyway, if you paste the code between the "'-------------------------------" lines into a module, the layout should be correct
I actually answered my own question.  I found the solution in the Book Access 95 How-To by Litwin and Getz.  I just had to alter their code slightly.  I will give Jeremy D the credit as his is closest to what I used...

Thx
kenadelglass
Do I need to submit an answer or can you find the 'reward comment' option?
BTW, can you post the solution you found? Just interested.
Yes, I'd like to see it too.  Jeremy D, your function works fine for closing notepad, but doesn't seem to work with other windows.  Does this just work with notepad?

:) dapperry
ASKER CERTIFIED SOLUTION
Avatar of Jeremy_D
Jeremy_D

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
The solution I found is probably the same solution as Jeremy's but I had to mess a bit with the calling function to get it to work the way I wanted...

Thx