开发者

Create a service to execute an exe after one screen opens in different exe ( VB.NET)

My question maybe not be very clear, but I just want to know how this process is called or references needed to create something similar, so I can investigate on my own ( but if you have code is welcome.. LOL...)

Basically I have 2 desktop programs ( A and B). For A, I do not have the source code, for B I do. What I need is to create some service/program that after a screen pops up from program A, automatically runs B. IN other words, capture the moment a specific screen is shown in A and execute B.

My real life scenario is that I have a very basic POS where I can't collect customer demographics ( zip code, etc), so I created a secon开发者_开发问答d application to capture that but my cashiers are always forgetting to run the program and I need to find a way to run it after a screen is shown ( let's say the "Change Due" in the POS, so they don't forget to run it.

Any pointings will be appreciated!

Thanks


So here's a very quick example of how you can do this with VB which should be very easy to convert to C# if needed. The code search visible windows by title. If your open window doesn't have a title you'll have to work a little more. You can probably find the title of your main app and just enumerate its child windows.

First, some unmanaged code to talk to Win32 directly:

Option Strict On
Option Explicit On

Imports System.Runtime.InteropServices
Imports System.Text

Public Class Unmanaged
    <DllImport("user32.dll")>
    Public Shared Function EnumWindows(ByVal lpEnumFunc As CallBack, ByVal lParam As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function
    <DllImport("user32.dll", SetLastError:=True)>
    Public Shared Function GetWindowLong(ByVal hWnd As IntPtr, ByVal nIndex As Integer) As Integer
    End Function
    <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
    Public Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
    End Function
    <DllImport("user32.dll", SetLastError:=True)> _
    Public Shared Function IsWindowVisible(ByVal hWnd As IntPtr) As <MarshalAs(UnmanagedType.Bool)> Boolean
    End Function

    Public Const SW_SHOW = 5
    Public Const SW_RESTORE = 9
    Public Const GW_OWNER = 4
    Public Const GWL_HWNDPARENT = (-8)
    Public Const GWL_EXSTYLE = (-20)
    Public Const WS_EX_TOOLWINDOW = &H80
    Public Const WS_EX_APPWINDOW = &H40000

    Public Delegate Function CallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
End Class

Then a non-GUI module which should be set as the startup object:

Option Explicit On
Option Strict On

Module Module1
    ''//Code loosely base on http://msdntracker.blogspot.com/2008/03/list-currently-opened-windows-with.html

    ''//This is the title of the window that we are looking for
    Public ReadOnly WatchForTitle As String = "About Mozilla Firefox"

    ''//This is the form that we will show when we find the above
    Private MainForm As Form1

    <STAThread()>
    Public Sub Main()
        ''//Create the form but don not show it
        MainForm = New Form1()

        ''//Create an infinite loop that checks to see if the target window is open and sleeps for a bit between checks
        Do While True
            Unmanaged.EnumWindows(AddressOf fEnumWindowsCallBack, IntPtr.Zero)
            ''//Sleep for a bit
            System.Threading.Thread.Sleep(500)
        Loop
    End Sub

    Private Function fEnumWindowsCallBack(ByVal hwnd As IntPtr, ByVal lParam As Integer) As Boolean
        ''//Ignore our own handle
        If hwnd <> Form1.Handle Then
            ''//Make sure its visible
            If Unmanaged.IsWindowVisible(hwnd) Then
                Dim lExStyle = Unmanaged.GetWindowLong(hwnd, Unmanaged.GWL_EXSTYLE)

                ''//We probably want to ignore tool windows, but remove this if needed
                If (((lExStyle And Unmanaged.WS_EX_TOOLWINDOW) = 0)) Then

                    ''//Create a buffer to store the title of the window
                    Dim sWindowText As New System.Text.StringBuilder(256)

                    ''//Get the title of the window
                    Dim lReturn = Unmanaged.GetWindowText(hwnd, sWindowText, sWindowText.Length - 1)

                    ''//When you are looking for window title uncomment this line
                    'Trace.WriteLine(sWindowText)

                    ''//Sanity check, make sure we found a window title
                    If lReturn <> 0 Then
                        ''//See if it matches what we are looking for
                        If sWindowText.ToString() = WatchForTitle Then
                            ''//If so, show our form
                            Form1.ShowDialog()
                        End If
                    End If
                End If
            End If
        End If
        fEnumWindowsCallBack = True
    End Function
End Module

Lastly create a regular Windows Form called Form1 (or whatever you want, you'll just need to change it in the Module above).

If you test this it will pop open the form if you go to Firefox's Help->About menu.

I should point out, this is just a start. You'll want to perform better error checking and handle when the program closes or exists or whatever.


It's very unlikely that there is any 'good' way to interact with program A. There won't be a traditional 'event' that fires or anything like that.

Your best bet is going to be looking at some WIN32 API calls. For example, you can use GetPixel() to return the color at a specific location on the screen. So, if program A displays a particular image or screen that is measurably different from any other screen, you can write code that monitors the screen and checks for a match. When the match is found you can execute any code you want, including launching B.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜