Results 1 to 7 of 7
  1. #1
    Silver Lounger
    Join Date
    Dec 2000
    Location
    California, USA
    Posts
    1,758
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Shell Command (XP)

    I am using the shell command to execute a program and an icon appears in the systray for the program. I would like to be able to close or exit the application via the icon on the systray. If I right click on the icon, I can manually select exit to exit but I am looking for a way to do it by code.

    Perhaps there is another way (I do not want to use SendKey).

    Thanks,
    John

  2. #2
    Lounger
    Join Date
    Jan 2004
    Location
    Derry, Derry, Ireland, Northern
    Posts
    35
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Shell Command (XP)

    Hi John,

    Is it another MS Office Product you are trying to control through code? If so, automation might work better for you than Shell.

    Wendell pointed me in the direction of some useful info (for Access, but you can adapt for Excel) - click here

    Also, when you say "systray", do you mean that (the little area beside the clock) or the taskbar?

  3. #3
    Bronze Lounger
    Join Date
    Nov 2001
    Location
    Arlington, Virginia, USA
    Posts
    1,394
    Thanks
    0
    Thanked 3 Times in 3 Posts

    Re: Shell Command (XP)

    You can close an application window (including an application iconized in the System Tray) by using the Windows PostMessage API function to post a message to the window telling it to close. Example:

    Public Function CloseAppWindow(ByVal strClassName As String, _
    ByVal strWindowText As String)

    Dim hwnd As Long

    ' To get application window hwnd, provide either Windows class name or _
    Windows text (caption), for other argument specify vbNullString:
    hwnd = FindWindow(strClassName, strWindowText)
    CloseAppWindow = PostMessage(hwnd, WM_CLOSE, 0, vbNullString)

    End Function

    To do so, you first need to determine the main application window handle (hwnd). The FindWindow API function returns a window's handle, given either the Windows class name for the application, or the window text (ie, the caption that appears in window's title bar or when minimized in the Task Bar). As an example, to close an running instance of Word, where a doc named "Document 1" is open, use either of the following:

    ' CloseAppWindow "OpusApp", vbNullString
    ' or:
    ' CloseAppWindow vbNullString, "Document1 - Microsoft Word"

    ("OpusApp" is the Windows class name for MS Word. ) Since you do not specify the name of the application you want to close, I have no idea what its class name may be. To determine the class name, you can use the EnumWindows API function to enumerate all top-level windows currently open. Some sample output (see TestEnumWindows sub in attached file):

    ' Windows Class = ExploreWClass, Title = C_W2K, Hwnd = 786688
    ' Windows Class = IEFrame, Title = Excel - Microsoft Internet Explorer, Hwnd = 2883804
    ' Windows Class = OpusApp, Title = Document1 - Microsoft Word, Hwnd = 3539674
    ' Windows Class = VBFloatingPalette, Title = Immediate, Hwnd = 11207226
    ' Windows Class = Avg60ControlCenter, Title = AVG Control Center - FREE Edition, Hwnd = 131264

    Note the last example (AVG anti-virus program) is running in the system tray, not as an open window on the desktop. So you should be able to determine the class name of the application you want to close using this method, or its window text, if it uses some standard caption. The attached text file is an exported VBA module that provides the necessary API declarations and other functions necessary to use these examples, which you may be able to adapt for your own project.

    BTW, I'm not sure what this has to do with Excel...

    HTH

  4. #4
    Silver Lounger
    Join Date
    Dec 2000
    Location
    California, USA
    Posts
    1,758
    Thanks
    0
    Thanked 0 Times in 0 Posts

    Re: Shell Command (XP)

    Mark,

    I use XL VBA inconjunction with Outlook to send E-mail messages with attachments. Outlook has a security warning that basically states that someone is trying to send an E-mail on your behalf and requires you to click "Yes" if you want to send it. I am using Express Click Yes to automatically click "Yes". It runs just like the anti-virus program you mentioned ie not window just the icon in the systray. I can call Click Yes to run but I am not sure how to exit it via vba. There have been some threads on ClickYes in the lounge.

    Any assistance is appreciated.

    Thanks,
    John

  5. #5
    WS Lounge VIP sdckapr's Avatar
    Join Date
    Jul 2002
    Location
    Pittsburgh, Pennsylvania, USA
    Posts
    11,225
    Thanks
    14
    Thanked 342 Times in 335 Posts

    Re: Shell Command (XP)

    You don't have to use SHELL to work with outlook in vb

    See this site

    Steve

  6. #6
    Bronze Lounger
    Join Date
    Nov 2001
    Location
    Arlington, Virginia, USA
    Posts
    1,394
    Thanks
    0
    Thanked 3 Times in 3 Posts

    Re: Shell Command (XP)

    To test this, I downloaded the ClickYes program from the ExpressSoft ClickYes site. The usual method you'd use to close an application window "cleanly":

    ' Class Name: "EXCLICKYES_WND" Title:"Express ClickYes 1.0.7"
    hwnd = FindWindow(strClassName, vbNullString)
    lngReturnValue = PostMessage(hwnd, WM_CLOSE, 0&, 0&)

    didn't work. If you look at the web site, there's some sample code for VB & other languages that allow you to Resume or Suspend program in limited fashion. Example:

    Public Sub SuspendClickYes()
    Dim hwnd As Long
    Dim msg As Long
    Dim rtn As Long
    msg = RegisterWindowMessage("CLICKYES_SUSPEND_RESUME")
    hwnd = FindWindow("EXCLICKYES_WND", vbNullString)
    ' Suspend ClickYes:
    rtn = SendMessage(hwnd, msg, 0, 0)
    End Sub

    There's similar code to Resume ClickYes. The use of RegisterWindowMessage API function to register the CLICKYES_SUSPEND_RESUME message signifies that the application is using subclassing. In subclassing, the window function for a window is replaced with a new function defined by the application. Incoming messages are processed by the subclass window function, which may or may not call the original window function specific to the message. This may explain why posting the standard Windows WM_CLOSE message to close application does not work.

    Another way to close an application is the TerminateProcess API function. This should be used only as a last resort. It is the equivalent of opening Windows Task Manager and clicking the End Process button. According to MSKB 176391 (HOWTO: Programmatically Close a Single Instance of a Windows-Based Program): "Microsoft does not recommended that you use this extreme approach. Although you may have stopped the handle process, the dynamic-link libraries (DLLs) that are used by the handle may still reside in memory, which causes a memory leak. Use the TerminateProcess function with caution." The attached file has an example of using TerminateProcess to close an open instance of ClickYes (see TestTerminateProcess) but do not recommend this approach. Another option is to use CreateProcess API rather than VBA Shell command to create a new instance of an application. For example, see TestCreateProcess sub. This sub creates, then terminates the process. (In testing with ClickYes it worked, but the icon was slow to exit from System Tray, which may or may not be a good sign....) You could use this in conjunction with the Resume/Suspend subs to manipulate ClickYes in code. Whenever using CreateProcess function, it is important to close any process or thread handles you create by calling the CloseHandle API. As noted in MSKB 129797 HOWTO: Launch a Win32 Application from Visual Basic, "CAUTION: It is very important to close these handles. Failure to do so can result in a system memory leak because some Windows NT or Windows 2000 Executive objects are never destroyed."

    The ideal solution would be if the ExpressSoft sample code also provided a "CLICKYES_EXIT" message that could be used to safely close the application. My recommendation would be, use the sample code to Suspend or Resume ClickYes as necessary, and leave it in iconized in System Tray. In Task Manager the app consumes a trivial amount of resources even in "Resume" mode. Forcing it to terminate may result in unwanted "issues" such as memory leaks, etc.

    HTH

  7. #7
    Bronze Lounger
    Join Date
    Nov 2001
    Location
    Arlington, Virginia, USA
    Posts
    1,394
    Thanks
    0
    Thanked 3 Times in 3 Posts

    Re: Shell Command (XP)

    In further reply, while "researching" an unrelated topic, I realized that in place of sending a WM_CLOSE message to a window to tell it to close, you can send a WM_DESTROY message (value = &H2). The main distinction is, if the application, when closed, normally pops up some type of dialog for user to confirm before exiting the program, this dialog will not be displayed if you use the WM_DESTROY message. WM_CLOSE is equivalent to closing an application "manually". Example:

    Public Sub CloseClickYes()

    Dim hwnd As Long
    Dim rtn As Long

    ' Get handle:
    hwnd = FindWindow("EXCLICKYES_WND", vbNullString)

    ' Does not work:
    ' rtn = PostMessage(hwnd, WM_CLOSE, 0&, 0&)

    ' Works:
    rtn = PostMessage(hwnd, WM_DESTROY, 0&, 0&)

    End Sub

    If interested, see attached demo file. When opened, a simple UserForm with four command buttons will be displayed:

    1 - Open ClickYes
    2 - Resume ClickYes
    3 - Suspend ClickYes
    4 - Close ClickYes

    Note: The OpenClickYes sub uses ShellExecute function to open ClickYes; assumes default installation path:

    "C:Program FilesExpress ClickYesClickYes.exe"

    Modify path if necessary. Each button when clicked performs the task as indicated by button caption. See Module1 for the API functions & declarations used for this. This is a lot simpler and safer than fooling around with CreateProcess, TerminateProcess, etc.

    HTH

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •