|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
FindWindow APIMy build is failing when I call some api's. Could someone help fix this code. Not sure how to declare the variables....already tried many different ways.....Thanks Public Declare Function WaitForSingleObject Lib "kernel32" _ (ByVal hHandle As System.IntPtr, _ ByVal dwMilliseconds As Integer) As Integer Public Auto Declare Function FindWindow Lib "user32" _ (ByVal lpClassName As String, _ ByVal lpWindowName As String) As System.IntPtr Public Declare Auto Function PostMessage Lib "user32" _ (ByVal hWnd As System.IntPtr, _ ByVal wMsg As Integer, _ ByVal wParam As Integer, _ ByVal lParam As Integer) As Boolean Public Declare Function OpenProcess Lib "kernel32" _ (ByVal dwDesiredAccess As Integer, _ ByVal bInheritHandle As Boolean, _ ByVal dwProcessId As System.IntPtr) As System.IntPtr Public Declare Function GetWindowThreadProcessId Lib "user32" _ (ByVal hWnd As System.IntPtr, _ ByRef lpdwProcessId As System.IntPtr) As System.IntPtr Dim hWindow As Long Dim hThread As Long Dim hProcess As Long Dim lProcessId As Long Dim lngResult As Long Dim lngReturnValue As Long Dim iLoopCnt As Integer hWindow = FindWindow(vbNullString, "(Inactive " & sDir & "\XXXX.EXE)") hThread = GetWindowThreadProcessId(hWindow, lProcessId) hProcess = OpenProcess(SYNCHRONIZE, 0&, lProcessId) lngReturnValue = PostMessage(hWindow, WM_CLOSE, 0&, 0&) lngResult = WaitForSingleObject(hProcess, 20000) Your FindWindow is pointing to a filename & not the window caption I think.
Do you have a window caption called: Inactive " & sDir & "\XXXX.EXE)") Whatever you have for sDir. Example Window Caption: --------------------------- Inactive C:\XXXX.EXE) I personally would change your 'Long's' for Integers & your IntPtr's to Integers. In fact I would do it all different. what is your full code & what is sDir? I changed the 'Long's' for Integers & your IntPtr's to Integers as you
suggested. IT WORKS! THANKS ALOT You mentioned you would do it differently....I've tried using .NET methods with no success... The FindWindow is actually hWindow = FindWindow(vbNullString, "(Inactive " & "C:\XXXX.EXE)") What I'm trying to do is this... My program kicks off an exe that creates a DOS window on the Desktop. I've tried for days to use the "pure .NET way" to close the spawned window. When I replace my XXXX.EXE, with for example Calc.exe, the .NET code works great. But when I use the XXXX.exe the code fails...acts as if the window isn't on the desktop. (No window hanlde ?) So now I'm trying the API methods which work with my VB6 version of the app using the XXX.exe. Now that I've got the declares correct it works. Show quoteHide quote "Crouchie1998" wrote: > Your FindWindow is pointing to a filename & not the window caption I think. > > Do you have a window caption called: > > Inactive " & sDir & "\XXXX.EXE)") > > Whatever you have for sDir. > > Example Window Caption: > --------------------------- > > Inactive C:\XXXX.EXE) > > I personally would change your 'Long's' for Integers & your IntPtr's to > Integers. In fact I would do it all different. what is your full code & what > is sDir? > > > In article <6227AD98-DD3A-41D4-83DA-63F687083***@microsoft.com>, Cutlass wrote:
Show quoteHide quote > Hello No disrespect for Crouchie1998 - he was trying to help you. But, if you> My build is failing when I call some api's. Could someone help fix this > code. Not sure how to declare the variables....already tried many different > ways.....Thanks > > Public Declare Function WaitForSingleObject Lib "kernel32" _ > (ByVal hHandle As System.IntPtr, _ > ByVal dwMilliseconds As Integer) As Integer > Public Auto Declare Function FindWindow Lib "user32" _ > (ByVal lpClassName As String, _ > ByVal lpWindowName As String) As System.IntPtr > Public Declare Auto Function PostMessage Lib "user32" _ > (ByVal hWnd As System.IntPtr, _ > ByVal wMsg As Integer, _ > ByVal wParam As Integer, _ > ByVal lParam As Integer) As Boolean > Public Declare Function OpenProcess Lib "kernel32" _ > (ByVal dwDesiredAccess As Integer, _ > ByVal bInheritHandle As Boolean, _ > ByVal dwProcessId As System.IntPtr) As System.IntPtr > Public Declare Function GetWindowThreadProcessId Lib "user32" _ > (ByVal hWnd As System.IntPtr, _ > ByRef lpdwProcessId As System.IntPtr) As System.IntPtr > > > Dim hWindow As Long > Dim hThread As Long > Dim hProcess As Long > Dim lProcessId As Long > Dim lngResult As Long > Dim lngReturnValue As Long > Dim iLoopCnt As Integer > > hWindow = FindWindow(vbNullString, "(Inactive " & sDir & "\XXXX.EXE)") > hThread = GetWindowThreadProcessId(hWindow, lProcessId) > hProcess = OpenProcess(SYNCHRONIZE, 0&, lProcessId) > lngReturnValue = PostMessage(hWindow, WM_CLOSE, 0&, 0&) > lngResult = WaitForSingleObject(hProcess, 20000) > > took his suggestion, then your declares are not correct. System handles should always be declared as IntPtr... I would leave your declares unchanged - but change your code to use them like this: Dim hWindow As IntPtr Dim hThread As IntPtr Dim hProcess As IntPtr Dim lProccessId As IntPtr Dim bResult As Boolean Dim iRet As Integer hWindow = FindWindow(Nothing, "(Inactive " & sDir & "\XXXX.EXE)") hThread = GetWindowThreadProcessId(hWindow, lProcessId) hProcess = OpenProcess(SYNCHRONIZE, False, lProcessId) bResult = PostMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero) iRet = WaitForSingleObject(hProcess, 20000) -- Tom Shelton [MVP] FYI
Tried coding Tom's way...it also works Don't know who is correct, but both methods work Show quoteHide quote "Tom Shelton" wrote: > In article <6227AD98-DD3A-41D4-83DA-63F687083***@microsoft.com>, Cutlass wrote: > > Hello > > My build is failing when I call some api's. Could someone help fix this > > code. Not sure how to declare the variables....already tried many different > > ways.....Thanks > > > > Public Declare Function WaitForSingleObject Lib "kernel32" _ > > (ByVal hHandle As System.IntPtr, _ > > ByVal dwMilliseconds As Integer) As Integer > > Public Auto Declare Function FindWindow Lib "user32" _ > > (ByVal lpClassName As String, _ > > ByVal lpWindowName As String) As System.IntPtr > > Public Declare Auto Function PostMessage Lib "user32" _ > > (ByVal hWnd As System.IntPtr, _ > > ByVal wMsg As Integer, _ > > ByVal wParam As Integer, _ > > ByVal lParam As Integer) As Boolean > > Public Declare Function OpenProcess Lib "kernel32" _ > > (ByVal dwDesiredAccess As Integer, _ > > ByVal bInheritHandle As Boolean, _ > > ByVal dwProcessId As System.IntPtr) As System.IntPtr > > Public Declare Function GetWindowThreadProcessId Lib "user32" _ > > (ByVal hWnd As System.IntPtr, _ > > ByRef lpdwProcessId As System.IntPtr) As System.IntPtr > > > > > > Dim hWindow As Long > > Dim hThread As Long > > Dim hProcess As Long > > Dim lProcessId As Long > > Dim lngResult As Long > > Dim lngReturnValue As Long > > Dim iLoopCnt As Integer > > > > hWindow = FindWindow(vbNullString, "(Inactive " & sDir & "\XXXX.EXE)") > > hThread = GetWindowThreadProcessId(hWindow, lProcessId) > > hProcess = OpenProcess(SYNCHRONIZE, 0&, lProcessId) > > lngReturnValue = PostMessage(hWindow, WM_CLOSE, 0&, 0&) > > lngResult = WaitForSingleObject(hProcess, 20000) > > > > > > No disrespect for Crouchie1998 - he was trying to help you. But, if you > took his suggestion, then your declares are not correct. System handles > should always be declared as IntPtr... > > I would leave your declares unchanged - but change your code to use them > like this: > > Dim hWindow As IntPtr > Dim hThread As IntPtr > Dim hProcess As IntPtr > Dim lProccessId As IntPtr > Dim bResult As Boolean > Dim iRet As Integer > > hWindow = FindWindow(Nothing, "(Inactive " & sDir & "\XXXX.EXE)") > hThread = GetWindowThreadProcessId(hWindow, lProcessId) > hProcess = OpenProcess(SYNCHRONIZE, False, lProcessId) > bResult = PostMessage(hWindow, WM_CLOSE, IntPtr.Zero, IntPtr.Zero) > iRet = WaitForSingleObject(hProcess, 20000) > > -- > Tom Shelton [MVP] > In article <5732DEF6-9EDB-4360-8C6B-88ACD3D8D***@microsoft.com>, Cutlass wrote:
> FYI Correct maybe a strong word here... Both methods work. It's a matter> Tried coding Tom's way...it also works > Don't know who is correct, but both methods work > of what's best practice. Handles as returned by the windows api's are the integer size of the underlying hardware. For example, on 32-bit systems the size of a handle is 32-bits, but on a 64-bit system they are 64-bits. Using Integer for these types of values makes your code non-portable to these systems. IntPtr is specifically designed to match that of the underlying platform (32-bit on 32-bit hardware and OS, 64-bit on 64-bit hardware and OS). This is the reason that the handle properties of controls in Windows.Forms are System.IntPtr :) Some go further, and actually use the specific .NET type in their declares rather then the VB.NET mapped keywords. In other words, they don't use Integer, Short, or Boolean in their declares - they use System.Int32, System.Int16, or System.Boolean. They do this to sheild themselves from future changes in the mapping of VB.NET datatypes. Anyway, when converting declares from VB.CLASSIC, you should be aware that data types no longer match. The sizes have changed in VB.NET. Here is a quick rundown: VB.CLASSIC VB.NET SIZE Byte Byte 8-bits Integer Short 16-bits Long Integer 32-bits Currency Long 64-bits Strings should be treated differently as well. When a string is being passed as a constant to an API call, then using String is fine. But, if that String is to be modified by the API call, then it should be passed as System.Text.StringBuilder instead.... For example, in VB6 you might declare the function GetUserName like this: Public Declare Function GetUserName _ Lib "Advapi32.dll" Alias "GetUserNameA" _ (ByVal lpBuffer As String, _ ByRef nSize As Long) As Long Well, in VB.NET that would translate to: Public Declare Auto Function GetUserName Lib "Advapi32.dll" _ (ByVal lpBuffer As System.Text.StringBuider, ByRef nSize As Integer) As Boolean Notice the lack of the alias? That's because .NET has the ability to determine the appropriate function to call (A vs W), based on the current OS. Also, since this buffer is going to be filled by the api, I declared it with System.Text.StringBuilder. This is not strictly necessary in VB.NET (it is in C#), since the VB.NET marshaller will actually do the extra work required to return the value if you were to declare it as string (remember, strings are immutable in .NET) - but, it can have a negative impact on performance and memory usage if the call is made frequently. So, calling it using stringbuilder: Imports System.Text .... Dim buffer As New StringBuilder (256) Dim nSize As Integer = buffer.Capacity GetUserName (buffer, nSize) Return buffer.ToString () Obviously, you might want to check the return value(s) etc. But, this should give you an idea. You should read the documentation on p/invoke and marshalling for further information. -- Tom Shelton [MVP] Thanks for the explanation and your time! I personally always like to know
the detailed explanation "how and whys" ! Show quoteHide quote "Tom Shelton" wrote: > In article <5732DEF6-9EDB-4360-8C6B-88ACD3D8D***@microsoft.com>, Cutlass wrote: > > FYI > > Tried coding Tom's way...it also works > > Don't know who is correct, but both methods work > > > > Correct maybe a strong word here... Both methods work. It's a matter > of what's best practice. Handles as returned by the windows api's are > the integer size of the underlying hardware. For example, on 32-bit > systems the size of a handle is 32-bits, but on a 64-bit system they are > 64-bits. Using Integer for these types of values makes your code > non-portable to these systems. IntPtr is specifically designed to match > that of the underlying platform (32-bit on 32-bit hardware and OS, > 64-bit on 64-bit hardware and OS). > > This is the reason that the handle properties of controls in > Windows.Forms are System.IntPtr :) > > Some go further, and actually use the specific .NET type in their > declares rather then the VB.NET mapped keywords. In other words, they > don't use Integer, Short, or Boolean in their declares - they use > System.Int32, System.Int16, or System.Boolean. They do this to sheild > themselves from future changes in the mapping of VB.NET datatypes. > > Anyway, when converting declares from VB.CLASSIC, you should be aware > that data types no longer match. The sizes have changed in VB.NET. > Here is a quick rundown: > > VB.CLASSIC VB.NET SIZE > Byte Byte 8-bits > Integer Short 16-bits > Long Integer 32-bits > Currency Long 64-bits > > Strings should be treated differently as well. When a string is being > passed as a constant to an API call, then using String is fine. But, if > that String is to be modified by the API call, then it should be passed > as System.Text.StringBuilder instead.... For example, in VB6 you might > declare the function GetUserName like this: > > Public Declare Function GetUserName _ > Lib "Advapi32.dll" Alias "GetUserNameA" _ > (ByVal lpBuffer As String, _ > ByRef nSize As Long) As Long > > Well, in VB.NET that would translate to: > Public Declare Auto Function GetUserName Lib "Advapi32.dll" _ > (ByVal lpBuffer As System.Text.StringBuider, > ByRef nSize As Integer) As Boolean > > Notice the lack of the alias? That's because .NET has the ability to > determine the appropriate function to call (A vs W), based on the > current OS. Also, since this buffer is going to be filled by the api, I > declared it with System.Text.StringBuilder. This is not strictly > necessary in VB.NET (it is in C#), since the VB.NET marshaller will > actually do the extra work required to return the value if you were to > declare it as string (remember, strings are immutable in .NET) - but, it > can have a negative impact on performance and memory usage if the call > is made frequently. So, calling it using stringbuilder: > > Imports System.Text > > .... > > Dim buffer As New StringBuilder (256) > Dim nSize As Integer = buffer.Capacity > > GetUserName (buffer, nSize) > > Return buffer.ToString () > > Obviously, you might want to check the return value(s) etc. But, this > should give you an idea. You should read the documentation on p/invoke > and marshalling for further information. > > -- > Tom Shelton [MVP] >
compression of a string , but must be interoptable someone an idea ??
FileSystemObject vs System.IO.File Array of Hash Tables VB to C# Problems with the PrintPreviewControl, PrintPreviewDialog controls Query database in VB.NET Create ListView columns dynamically from XML [String] C# to VB Set Desktop |
|||||||||||||||||||||||