When I use the code down below to start a cmd window and move it into a panel, everything works OK. But when I replace cmd with conhost, it fails with the following error: 'The system cannot find the file specified', even when I specify the complete path.
By the way, the reason why I'm trying to start conhost instead of cmd is just for testing purposes, I'm trying to find a way to find the PID of the conhost process for a process running through cmd.
Thanks for any help in advance!
Kind regards,
Eric van Loon
Imports System.Runtime.InteropServices
Public Class Form1
Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim proc As Process
proc = Process.Start("cmd")
proc.WaitForExit(600)
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, 274, 61488, 0)
End Sub
End Class
Like explained by Mofi:
%SystemRoot%\System32\conhost.exe exists on 64-bit Windows only as
64-bit application. There is no 32-bit
%SystemRoot%\SysWOW64\conhost.exe. The application running the posted
VB.Net code is obviously a 32-bit executable which means the Windows
File System Redirector is active and therefore redirects each access
to %SystemRoot%\System32 to %SystemRoot%\SysWOW64. That is the reason
why conhost.exe cannot be found while 32-bit
%SystemRoot%\SysWOW64\cmd.exe is found and executed by this code.
Related
I'm attempting to send automated keystrokes to an application that does not support copy+paste via a small VB form. The form loads data from a text file and uses SendKeys to fire it over once I click a button.
Everything appears to work except for the ShowWindow portion. I'm currently testing using Notepad and, with one exception, I can't seem to get ShowWindow to kick focus to Notepad. Obviously I'm worried it will do the same to the application I'll eventually be running this against (I don't currently have access to it). The only ShowWindow parameter that makes Notepad active is SW_SHOWMAXIMIZED. SW_SHOW and SW_SHOWNORMAL don't appear to do anything while SW_RESTORE will restore Notepad if minimized but my VB form remains the active window.
I'm not a programmer but I had made the mistake of telling my boss I dabbled in Pascal Turbo in high school (over a decade ago) so I'm the one stuck with trying to make this work. My current code cobbled together from S.O. and other sources:
(I'm running Windows 7 and using MVSE2013)
Imports System.Runtime.InteropServices
Public Class Form1
Private Declare Function FindWindow _
Lib "user32" _
Alias "FindWindowA" _
(ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow As ShowWindowCommands) As Boolean
End Function
Enum ShowWindowCommands As Integer
SW_SHOWNORMAL = 1
SW_SHOWMAXIMIZED = 3
SW_RESTORE = 9
End Enum
Private Sub Form1_Load
[form]
End Sub
Private Sub Button1_Click(ByVal sender As System.Object, _
ByVal e As System.EventArgs) Handles Button1.Click
Dim lHwnd As IntPtr = FindWindow("Notepad", vbNullString)
If lHwnd <> IntPtr.Zero Then
ShowWindow(lHwnd, ShowWindowCommands.SW_SHOWNORMAL)
SendKeys.Send(TextBox1.Text)
Else
[blah blah error handling]
End If
End Sub
I'd try another technique like SetForegroundWindow but I read it doesn't play nice with Windows 7.
Found what I hope will be a passable workaround from PInvoke. I ended up swapping this block:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function ShowWindow(ByVal hwnd As IntPtr, ByVal nCmdShow _
As ShowWindowCommands) As Boolean
End Function
For this:
Public Declare Function BringWindowToTop Lib "user32" (ByVal hwnd As IntPtr) As Boolean
And then this line:
ShowWindow(lHwnd, ShowWindowCommands.SW_SHOWNORMAL)
For this:
BringWindowToTop(lHwnd)
I realize there are functional differences between the two but the change works in my specific instance so I'm happy.
I have a bunch of related VB.NET console applications I've written for admin/management functions.
I now want to bring them together under a single Windows Forms application that works as a launcher, but instead of launching the apps as seperate programs, I want to embed the apps in the windows forms app, e.g. have a scrollable list of icons down the left hand side - clicking on one will launch the associated .exe in the right hand pane of the windows forms app.
For now I have a simple single form application with one panel, so I can test out if what I want to do is possible.
Having read around MSDN and SO, I've found other posts about this but none that seem to do what I want.
I don't want to intercept stin/stdout/stderr streams and attempt to emulate the console application, I want to actually run the compiled exe (which I can achieve) but have it run inside the windows form (which I can't achieve, it launches as a seperate process).
The main code for Form1 that I have right now is:
Public Class Form1
Declare Auto Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As Integer
Declare Auto Function SendMessage Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal Msg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
Private Const WM_SYSCOMMAND As Integer = 274
Private Const SC_MAXIMIZE As Integer = 61488
Dim proc As Process
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
proc = Process.Start("\\fileserver\datashare\path\WIN_MGR.exe")
proc.WaitForInputIdle()
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
End Sub
End Class
Anyone able to put me in the right direction to actually run the .exe application windowed within the windows form?
Based on the comments, change your Form_Load as follows:
proc = Process.Start("\\fileserver\datashare\path\WIN_MGR.exe")
Thread.Sleep(1000) 'Possibly replace this with polling MainWindowHandle
SetParent(proc.MainWindowHandle, Me.Panel1.Handle)
SendMessage(proc.MainWindowHandle, WM_SYSCOMMAND, SC_MAXIMIZE, 0)
WaitForInputIdle fails because the console application does not have a graphical interface. For a more accurate delay, Idle_Mind suggests polling MainWindowHandle in a while-loop until it returns a value other than IntPtr.Zero.
i'm trying to port code from VBA 32 (Excel) that doesn't work in Excel 2013 64bit.
I need to read a HASP key and usually use a hasvb32.dll.
' The main hasp API function
Private Declare Sub hasp Lib "haspvb32.dll" (ByVal Service, ByVal seed, ByVal lpt, ByVal pass1, ByVal pass2, retcode1, retcode2, retcode3, retcode4 As Any)
' WriteHaspBlock function prepares memory for the WriteBlock service
Private Declare Sub WriteHaspBlock Lib "haspvb32.dll" (ByVal Service, Buff As Any, ByVal Length)
' ReadHaspBlock function prepares memory for the WriteBlock service
Private Declare Sub ReadHaspBlock Lib "haspvb32.dll" (ByVal Service, Buff As Any, ByVal Length)
have made the changes to:
' The main hasp API function
Private Declare PtrSafe Sub hasp Lib "haspvb32.dll" (ByVal Service, ByVal seed, ByVal lpt, ByVal pass1, ByVal pass2, retcode1, retcode2, retcode3, retcode4 As Any)
' WriteHaspBlock function prepares memory for the WriteBlock service
Private Declare PtrSafe Sub WriteHaspBlock Lib "haspvb32.dll" (ByVal Service, Buff As Any, ByVal Length)
' ReadHaspBlock function prepares memory for the WriteBlock service
Private Declare PtrSafe Sub ReadHaspBlock Lib "haspvb32.dll" (ByVal Service, Buff As Any, ByVal Length)
with no success. any idea?
thanks
If it's a 32-bit DLL (which it most likely is), there isn't much you can do to make it run in Office 64-bit.
If you've written it, you may recompile it using instructions given in this example. It'll give you a better sense of the parameters to be declared such as your code being Pointer-Safe, etc.
Excellent example and reference by Jonathan Lhost
https://sites.google.com/site/jrlhost/links/excelcdll
i was programming an hack for a game in Visual basic, i want simulate a keypress with the code:
Private Sub Timer1_Tick(sender As Object, e As EventArgs) Handles Timer1.Tick
SendKeys.Send("a")
End Sub
In my window game didn't work, but in other windows such as chrome or a test textbox work, why?
if this is not a flash game , you can get the process of the game by:
Dim TheGame as Process = Process.GetProcessesByName("YourGame")(0)
get the handle of the game window:
Dim Handle As IntPtr = TheGame.MainWindowHandle
and then use sendmessage function to send the keys to the window:
SendMessage(Handle, 258, PUT KEY HERE, 0)
for example - instead of the "PUT KEY HERE" type:
&H41 (is "A")
you can find the keys list here:
http://www.pinvoke.net/default.aspx/Enums/VirtualKeys.html
the user32.dll sendmessage function:
Declare Function SendMessage Lib "user32" Alias "SendMessageA" _
(ByVal hWnd As IntPtr, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
Edit:
if the code is not working change the 258 (wm_char) in the sendmessage to 256(wm_keydown)
note:sendkeys sends keys to the current active window, and you should try to use pinvoke functions first and if you don't have any choice then use sendkeys.
Recommendation:
explore the functions: postmessage,sendmessage,setforegroundwindow and also explore spy++ tool :).
Using VB6, I cannot change to VB .NET or anything else.
I'm trying to register a COM Library programmatically in the Form_Load() method of the invoking application.
The method I'm using below works as expected on Windows 7, both x86 and x64. However when I try and use the same application on Windows XP, I receive the Library not registered error:
http://imgur.com/zus2bK6
I have verified that the Library is being registered and it shows properly in the registry at HKEY_LOCAL_MACHINE\SOFTWARE\Classes\MyDll.Component as well as in HKEY_CLASSES_ROOT\AppID\Mydll.DLL
Here is the code I am using, can anyone tell me why this would be occurring on XP only and how to resolve it?
Private Declare Function DllRegisterServer Lib "MyDLL.dll" () As Long
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As Long
Private Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As Long, ByVal lpProcName As String) As Long
Private Declare Function CallWindowProc Lib "user32" Alias "CallWindowProcA" (ByVal lpPrevWndFunc As Long, ByVal hwnd As Long, ByVal Msg As Any, ByVal wParam As Any, ByVal lParam As Any) As Long
Private Sub Form_Load()
ReDim ConfigFiles(0)
ReDim ConfigFilesToAdd(0)
libID = LoadLibrary("MyDLL.dll")
Dim pAdd As Long
pAdd = GetProcAddress(libID, "DllRegisterServer")
Dim lResult As Long
lResult = CallWindowProc(pAdd, 0&, 0&, 0&, 0&)
Set IGDep = CreateObject(MyDLL.Component")
End Sub
I have performed this process with all manner of permissions including the Administrator account and ensured that I had all permissions on the registry.
Thanks for any help you guys can give.