-
Need to start a command line window and send a string to it
I have a VB6 program that sends a command to the command line. The command line window then stays open asking for username. I think what I need to do is launch the command and grab the pid, then use the pid to send the string to the command window. Is this possible?
-
Re: Need to start a command line window and send a string to it
I can launch the code, get the process id and even the process handle, but not sure how to send to the command window once I know that info.
vb Code:
Dim retVal As Long, pID As Long, pHandle As Long
pID = Shell(cmdLine, vbNormalFocus)
pHandle = OpenProcess(&H100000, True, pID)
Can I somehow send a string to this process id or process handle?
-
Re: Need to start a command line window and send a string to it
-
Re: Need to start a command line window and send a string to it
I looked at the link, but I can't really make sense of that code. I'm guessing maybe the command window needs to be in focus and then maybe that will work. I'm sure there is a simple way to do this. I tried this, but it didn't work.
vb Code:
Option Explicit
Private Const INFINITE = &HFFFF ' Infinite timeout
Private Declare Function WaitForSingleObject Lib "kernel32" (ByVal hHandle As Long, ByVal dwMilliseconds As Long) As Long
Private Declare Function OpenProcess Lib "kernel32" (ByVal dwAccess As Long, ByVal fInherit As Integer, ByVal hObject As Long) As Long
Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, ByVal lpBuffer As String, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long
Private Sub Command1_Click()
Dim retVal As Long, pID As Long, pHandle As Long
Dim txt As String
Dim num_written As Long
txt = "a"
pID = Shell("cmd /c pause", vbNormalFocus)
pHandle = OpenProcess(&H100000, True, pID)
MsgBox pHandle
WriteConsole pID, txt, Len(txt), num_written, vbNullString
WriteConsole pHandle, txt, Len(txt), num_written, vbNullString
End Sub
I was trying to send text using first pID (process id) and then pHandle (process handle), but maybe WriteConsole doesn't work like this.
-
Re: Need to start a command line window and send a string to it
Ok, I have this working with SendKeys, but SendKeys can be very iffy so please let me know if anyone has a better solution. Here's my code...
vb Code:
pID = Shell("C:\Program Files\Cisco\Cisco AnyConnect VPN Client\vpncli.exe connect xyz.org", vbMinimizedFocus)
Sleep (1000)
AppActivate pID 'activate vpncli.exe command window
DoEvents 'do events is needed to allow Windows to switch focus
SendKeys Text1.Text, True 'send username to vpncli.exe
DoEvents
AppActivate pID
DoEvents 'do events is needed to allow Windows to switch focus
SendKeys "{Enter}" 'hit enter after username
DoEvents
AppActivate pID
DoEvents 'do events is needed to allow Windows to switch focus
SendKeys Text2.Text, True 'send password to vpncli.exe
DoEvents
AppActivate pID
DoEvents 'do events is needed to allow Windows to switch focus
SendKeys "{Enter}" 'hit enter after password
DoEvents
-
Re: Need to start a command line window and send a string to it
there is a better method, search on named pipes
or use a shell object
-
Re: Need to start a command line window and send a string to it
first you can open the command line as an object in your vb project
i found this class on P-S-C
Code:
VERSION 1.0 CLASS
BEGIN
MultiUse = -1 'True
Persistable = 0 'NotPersistable
DataBindingBehavior = 0 'vbNone
DataSourceBehavior = 0 'vbNone
MTSTransactionMode = 0 'NotAnMTSObject
END
Attribute VB_Name = "clsConsole"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = True
Attribute VB_PredeclaredId = False
Attribute VB_Exposed = False
Attribute VB_Ext_KEY = "SavedWithClassBuilder6" ,"Yes"
Attribute VB_Ext_KEY = "Top_Level" ,"Yes"
Option Explicit
'based upon the DOS Console posted on http://www.planet-source-code.com/ by Loreno Heer
Private Declare Function AllocConsole Lib "kernel32" () As Long
Private Declare Function FreeConsole Lib "kernel32" () As Long
Private Declare Function GetStdHandle Lib "kernel32" (ByVal nStdHandle As Long) As Long
Private Declare Function ReadConsole Lib "kernel32" Alias "ReadConsoleA" (ByVal hConsoleInput As Long, ByVal lpBuffer As String, ByVal nNumberOfCharsToRead As Long, lpNumberOfCharsRead As Long, lpReserved As Any) As Long
Private Declare Function SetConsoleMode Lib "kernel32" (ByVal hConsoleOutput As Long, dwMode As Long) As Long
Private Declare Function SetConsoleTextAttribute Lib "kernel32" (ByVal hConsoleOutput As Long, ByVal wAttributes As Long) As Long
Private Declare Function SetConsoleTitle Lib "kernel32" Alias "SetConsoleTitleA" (ByVal lpConsoleTitle As String) As Long
Private Declare Function WriteConsole Lib "kernel32" Alias "WriteConsoleA" (ByVal hConsoleOutput As Long, ByVal lpBuffer As Any, ByVal nNumberOfCharsToWrite As Long, lpNumberOfCharsWritten As Long, lpReserved As Any) As Long
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function ShowWindow Lib "user32" (ByVal hWnd As Long, ByVal nCmdShow As Long) As Long
Private Declare Function SetWindowPos Lib "user32" (ByVal hWnd As Long, ByVal hWndInsertAfter As Long, ByVal x As Long, ByVal Y As Long, ByVal cx As Long, ByVal cy As Long, ByVal wFlags As Long) As Long
Private Const STD_INPUT_HANDLE = -10&
Private Const STD_OUTPUT_HANDLE = -11&
Private Const STD_ERROR_HANDLE = -12&
Private Const FOREGROUND_RED = &H4
Private Const FOREGROUND_GREEN = &H2
Private Const FOREGROUND_BLUE = &H1
Private Const FOREGROUND_INTENSITY = &H8
Private Const BACKGROUND_RED = &H40
Private Const BACKGROUND_GREEN = &H20
Private Const BACKGROUND_BLUE = &H10
Private Const BACKGROUND_INTENSITY = &H80
Private Const ENABLE_LINE_INPUT = &H2
Private Const ENABLE_ECHO_INPUT = &H4
Private Const ENABLE_MOUSE_INPUT = &H10
Private Const ENABLE_PROCESSED_INPUT = &H1
Private Const ENABLE_WINDOW_INPUT = &H8
Private Const ENABLE_PROCESSED_OUTPUT = &H1
Private Const ENABLE_WRAP_AT_EOL_OUTPUT = &H2
Private hConsoleIn As Long
Private hConsoleOut As Long
Private hConsoleErr As Long
Private Const SWP_NOMOVE = 2
Private Const SWP_NOSIZE = 1
Private Const FLAGS = SWP_NOMOVE Or SWP_NOSIZE
Private Const HWND_TOPMOST = -1
Private Const HWND_NOTOPMOST = -2
Private Const SWP_SHOWWINDOW = &H40
Private Const WM_CLOSE = &H10
Private Const SW_HIDE = 0
Private Const SW_SHOWNORMAL = 1
Private Const SW_MAXIMIZE = 3
Private Const SW_SHOW = 5
Private Const SW_MINIMIZE = 6
Private Const SW_RESTORE = 9
'local variable(s) to hold property value(s)
Private mvarLogFilePathName As String 'local copy
Private mvarConsoleWindowTitle As String 'local copy
Public Property Let ConsoleWindowTitle(ByVal vData As String)
mvarConsoleWindowTitle = vData
End Property
Public Property Get ConsoleWindowTitle() As String
ConsoleWindowTitle = mvarConsoleWindowTitle
End Property
Public Sub WriteOut(ByVal Msg As String, Optional ByVal LogIt As Boolean = False)
Msg = Format(Now, "hh:nn:ss") & " " & Msg
Msg = Msg & vbCrLf
WriteConsole hConsoleOut, Msg, Len(Msg), vbNull, vbNull
If LogIt Then WriteLog Msg
End Sub
Public Sub Important(ByVal Msg As String, Optional ByVal LogIt As Boolean = False)
SetConsoleTextAttribute hConsoleOut, FOREGROUND_RED Or FOREGROUND_INTENSITY
WriteOut "---------------------------------------------------------------------", LogIt
WriteOut Msg, LogIt
WriteOut "---------------------------------------------------------------------", LogIt
SetConsoleTextAttribute hConsoleOut, FOREGROUND_RED Or FOREGROUND_GREEN Or FOREGROUND_BLUE
End Sub
Public Property Let LogFilePathName(ByVal vData As String)
mvarLogFilePathName = vData
End Property
Public Property Get LogFilePathName() As String
LogFilePathName = mvarLogFilePathName
End Property
Private Function CGet() As String
Dim sUserInput As String * 256
Call ReadConsole(hConsoleIn, sUserInput, Len(sUserInput), vbNull, vbNull)
CGet = Left$(sUserInput, InStr(sUserInput, Chr$(0)) - 3)
End Function
Public Sub CloseConsole()
FreeConsole
End Sub
Public Sub LoadConsole()
Dim lHwnd As Long
Dim ConsoleTitle As String
ConsoleTitle = ConsoleWindowTitle()
AllocConsole
SetConsoleTitle ConsoleTitle
hConsoleIn = GetStdHandle(STD_INPUT_HANDLE)
hConsoleOut = GetStdHandle(STD_OUTPUT_HANDLE)
hConsoleErr = GetStdHandle(STD_ERROR_HANDLE)
lHwnd = FindWindow("ConsoleWindowClass", ConsoleTitle)
ShowWindow lHwnd, SW_SHOWNORMAL
Call SetWindowPos(lHwnd, HWND_TOPMOST, 0, 0, 0, 0, FLAGS)
Call SetWindowPos(lHwnd, HWND_NOTOPMOST, 0, 0, 0, 0, FLAGS)
End Sub
Private Sub WriteLog(sMsg As String)
If LogFilePathName = "" Then Exit Sub
Dim intFile As Integer ' FreeFile variable
intFile = FreeFile()
Open LogFilePathName For Append As #intFile
Print #intFile, sMsg
Close #intFile
End Sub
Private Function FileExists(FullPathandFile As String) As Boolean
On Error Resume Next
If FileLen(FullPathandFile) > 0& Then
If Err = 0 Then FileExists = True
End If
End Function
Private Sub Class_Terminate()
CloseConsole
End Sub
-
Re: Need to start a command line window and send a string to it
second, you can try these functions to get/set the command line window text.
you need to find the Hwnd of the command line, first.
i didn't try them though, so i'll be happy if you have the time to test them and report the results.
Code:
Const WM_SETTEXT = &HC
Const WM_GETTEXT = &HD
Declare Function SetWindowText Lib "user32" Alias "SetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String) As Long
Declare Function GetWindowText Lib "user32" Alias "GetWindowTextA" (ByVal hwnd As Long, ByVal lpString As String, ByVal cch As Long) As Long
Declare Function GetWindowTextLength Lib "user32" Alias "GetWindowTextLengthA" (ByVal hwnd As Long) As Long
Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, lParam As Any) As Long
'Example Use of get window text
Dim Buf As String
Buf = Space(512)
' the hwnd should be the command line Window Handler
Call SendMessage(hWnd,WM_GETTEXT,Len(Buf),ByVal Buf)
in case this will give only the title,
you can use PSpy (on my signature), to see the name and window handler
of the object inside the command line (if there is any,)
and use this handler, instead.
Code:
'Example Use of set window text
Dim Buf As String
Buf = "this text is sended to command line window"
' the hwnd should be the command line Window Handler or
' the object handler inside command line, if there is any.
Call SendMessage(hWnd,WM_SETTEXT,Len(Buf),ByVal Buf)
-
Re: Need to start a command line window and send a string to it
I would rather use SendMessage as you suggested, but I couldn't figure out the window handle for the command line window. I thought this would get me the handle, but it didn't...
vb Code:
pID = Shell("cmd /c pause", vbNormalFocus)
pHandle = OpenProcess(&H100000, True, pID)
Any ideas on how I can get the handle of the command line window?
-
Re: Need to start a command line window and send a string to it
Quote:
Originally Posted by
BrianPaul
I would rather use SendMessage as you suggested, but I couldn't figure out the window handle for the command line window. I thought this would get me the handle, but it didn't...
vb Code:
pID = Shell("cmd /c pause", vbNormalFocus)
pHandle = OpenProcess(&H100000, True, pID)
Any ideas on how I can get the handle of the command line window?
there is a program on my signature called PSpy
you can see everything you want
it comes in source code.
EDIT: i just checked this, this only changed the title text,
and i looked in PSpy, and couldn't find any other object inside command line.
so i think the only solution (if you don't want the class) to use send keys.
if send keys doesn't work well for you, you better try the API version.
ofcourse don't forget to set focus on command line, first.
the handle you can find by class:
Code:
Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
hWnd = FindWindow("ConsoleWindowClass", vbNullString)
the code below show how to use API sendkey
Code:
Const KEYEVENTF_EXTENDEDKEY = &H1
Const KEYEVENTF_KEYUP = &H2
Declare Sub keybd_event Lib "user32" Alias "keybd_event" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
'Simulate Key Press>
keybd_event VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY, 0
'Simulate Key Release
keybd_event VK_CAPITAL, &H45, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0
-
Re: Need to start a command line window and send a string to it
-
Re: Need to start a command line window and send a string to it
i made a little research
and this is a working tested example
Code:
'put all the code below in a form
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Const KEYEVENTF_EXTENDEDKEY = &H1
Const KEYEVENTF_KEYUP = &H2
Private Declare Sub keybd_event Lib "user32" (ByVal bVk As Byte, ByVal bScan As Byte, ByVal dwFlags As Long, ByVal dwExtraInfo As Long)
Private Declare Function SetForegroundWindow Lib "user32" (ByVal Hwnd As Long) As Long
Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Const VK_BACK = &H08
Private Const VK_TAB = &H09
Private Const VK_RETURN = &H0D
Private Const VK_SHIFT = &H10
Private Const VK_CONTRL = &H11
Private Const VK_MENU = &H12
Private Const VK_PAUSE = &H13
Private Const VK_CAPITAL = &H14
Private Const VK_ESCAPE = &H1B
Private Const VK_OEM_PLUS = &HBB
Private Const VK_OEM_COMMA = &HBC
Private Const VK_OEM_MINUS = &HBD
Private Const VK_OEM_PERIOD = &HBE
' :
Private Const VK_OEM_1 = &HBA
' /?
Private Const VK_OEM_2 = &HBF
' \|
Private Const VK_OEM_5 = &HDC
Private Sub SendKey(ByVal k As Byte)
'Simulate Key Press
Call keybd_event(k, 0, KEYEVENTF_EXTENDEDKEY, 0)
'Simulate Key Release
Call keybd_event(k, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
End Sub
Private Sub apiSendKeys(ByVal Str1)
Dim Str2 As String
Dim i1 As Integer, i2 As Integer
Dim flag As Boolean
Dim k As Byte
i2 = Len(Str1)
For i1 = 1 To i2
flag = False
Str2 = Mid(Str1, i1, 1)
k = Asc(Str2)
Select Case k
Case Asc("\")
k = VK_OEM_5
Case Asc(".")
k = VK_OEM_PERIOD
Case Asc(":")
GoSub SendShift0000
k = VK_OEM_1
Case Asc("?")
GoSub SendShift0000
k = VK_OEM_2
Case Else
If k >= Asc("A") And k <= Asc("Z") Then GoSub SendShift0000
k = Asc(UCase$(Str2))
End Select
Call SendKey(k)
If flag Then Call keybd_event(VK_SHIFT, 0, KEYEVENTF_EXTENDEDKEY Or KEYEVENTF_KEYUP, 0)
Next
Exit Sub
SendShift0000:
Call keybd_event(VK_SHIFT, 0, KEYEVENTF_EXTENDEDKEY, 0)
flag = True
Return
End Sub
Private Sub form_load()
Dim Hwnd As Long
Dim Buf As String
Hwnd = FindWindow("ConsoleWindowClass", vbNullString)
Call SetForegroundWindow(Hwnd)
Call Sleep(500)
Call apiSendKeys("AaBbCd?\.:1234" + vbCr)
Unload Me
End Sub
-
Re: Need to start a command line window and send a string to it
Thanks whatsup, but the problem that I have is with this line...
Call SetForegroundWindow(Hwnd)
This line is setting putting the command line window in focus, but with other apps can steal that focus away, which is the big downfall of SendKeys. Right now I am using SendKeys with AppActivate to get the focus and it works, but know it's not a foolproof way to do it. The other issue is that I cannot hide the window. If I use vbHide, it will not work, but with SendMessage, it will work even if the window is hidden.
I tried using SendMessage in this way...
vb Code:
h = FindWindow(vbNullString, CStr("c:\windows\cisco\vpncli.exe"))
h = CStr(h)
Dim Buf As String
Buf = "this text is sent to command line window"
Call SendMessage(h, WM_SETTEXT, Len(Buf), ByVal 0)
It ends up changing the title of the command line window instead of entering the text at the command prompt. Now the last post here seems to be saying it can't be done...
http://www.vbforums.com/showthread.php?t=238185
But I found if I do this, it will send the letter 'a' to the command prompt.
vb Code:
h = FindWindow(vbNullString, CStr("c:\windows\cisco\vpncli.exe"))
h = CStr(h)
Call SendMessageBynum(h, WM_CHAR, 97, ByVal 0)
I think there must be a way to do this using WM_SETTEXT. I can do it a letter at a time, but it just seems that WM_SETTEXT should work.
-
Re: Need to start a command line window and send a string to it
Quote:
Originally Posted by
BrianPaul
But I found if I do this, it will send the letter 'a' to the command prompt.
If the window is accepting the one character then you could just create a sub to send each character of the string for you, see the SendTxt Function in the example...
Code:
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_CHAR = &H102
Private Sub Form_Load()
'open a hidden dos prompt window (WinXP).
Shell "c:\windows\system32\cmd.exe", vbHide
End Sub
Private Sub Command1_Click()
Dim h As Long
Dim result As Boolean
' find dos prompt window
h = FindWindow(vbNullString, "c:\windows\system32\cmd.exe")
If h Then
' send "calc.exe" followed by carraige return
result = SendTxt(h, "calc.exe" & vbCr)
' optional, check postmessage result
If result = False Then MsgBox "postmessage failed!"
'close the hidden dos prompt window
SendTxt h, "exit" & vbCr
Else
MsgBox "dos prompt window not found"
End If
End Sub
Private Function SendTxt(ByVal Handle As Long, ByVal sText As String) As Boolean
Dim i As Integer
Dim lngReturn As Long
For i = 1 To Len(sText)
lngReturn = PostMessage(Handle, WM_CHAR, Asc(Mid$(sText, i, 1)), 0&)
If lngReturn <> 1 Then Exit Function ' failed
Next i
SendTxt = True ' passed
End Function
btw, Look up WM_SETTEXT on MSDN, I believe its mainly used for edit controls and title text.
-
Re: Need to start a command line window and send a string to it
Quote:
h = FindWindow(vbNullString, CStr("c:\windows\cisco\vpncli.exe"))
h = CStr(h)
Call SendMessageBynum(h, WM_CHAR, 97, ByVal 0)
this is very good to know.
so as Edgemeal said, just send char by char, shouldn't be a problem.
-
Re: Need to start a command line window and send a string to it
Edgemeal, that's awesome and very much appreciated! I do seem to have a strange issue with the code though. If there are duplicate letters, it seems to strip them out. It works fine in your program, but when I put it into my program, it seems to strip out duplicate characters... like MILLER would show up as MILER. Here's my code...
vb Code:
Private Sub Command1_Click()
Dim Result As Integer 'ping result
Dim cnt As Integer 'loop counter
Dim hwnd As Long 'handle of command window
Dim username As String: username = Text1.Text
Dim pwd As String: pwd = Text2.Text
Call Shell("C:\Program Files\Cisco\Cisco AnyConnect VPN Client\vpncli.exe connect myDomain", vbNormalFocus)
Sleep (1000)
hwnd = FindWindow(vbNullString, "C:\Program Files\Cisco\Cisco AnyConnect VPN Client\vpncli.exe") 'find VPN commandline window
If hwnd Then 'Check if commandline window was found
Result = SendTxt(hwnd, Text1.Text & vbCr) 'Send username to command line
If Result = False Then MsgBox "postmessage failed!" 'check if postmessage failed
Else
MsgBox "VPN Connection failed, commandline window not found!"
Exit Sub
End If
hwnd = FindWindow(vbNullString, "C:\Program Files\Cisco\Cisco AnyConnect VPN Client\vpncli.exe") 'find VPN commandline window
If hwnd Then 'Check if commandline window was found
Result = SendTxt(hwnd, Text2.Text & vbCr) 'Send password to command line
If Result = False Then MsgBox "postmessage failed!" 'check if postmessage failed
Else
MsgBox "VPN Connection failed"
Exit Sub
End If
End Sub
vb Code:
Private Function SendTxt(ByVal Handle As Long, ByVal sText As String) As Boolean
Dim i As Integer
Dim lngReturn As Long
For i = 1 To Len(sText)
lngReturn = PostMessage(Handle, WM_CHAR, Asc(Mid$(sText, i, 1)), 0&)
If lngReturn <> 1 Then Exit Function ' failed
Next i
SendTxt = True ' passed
End Function
-
Re: Need to start a command line window and send a string to it
Ok, got it... put a sleep statement right after it posts a letter and it fixed the problem. Now it looks like this...
Code:
Private Function SendTxt(ByVal Handle As Long, ByVal sText As String) As Boolean
Dim i As Integer
Dim lngReturn As Long
For i = 1 To Len(sText)
lngReturn = PostMessage(Handle, WM_CHAR, Asc(Mid$(sText, i, 1)), 0&)
Sleep 25
If lngReturn <> 1 Then Exit Function ' failed
Next i
SendTxt = True ' passed
End Function
-
Re: Need to start a command line window and send a string to it
Quote:
Originally Posted by
BrianPaul
Ok, got it... put a sleep statement right after it posts a letter and it fixed the problem.
You might want to try using SendMessage instead of Postmessage?....
The SendMessage function calls the window procedure for the specified window and does not return until the window procedure has processed the message.
PostMessage Function: Places (posts) a message in the message queue associated with the thread that created the specified window and returns without waiting for the thread to process the message.
SendMessageTimeOut might also be worth a look as you can set a max wait time to return, Sendmesssage can hang your program (or make it appear hung) if the program the message is sent is busy in say a loop.
-
Re: Need to start a command line window and send a string to it
Ok, I tried SendMessageTimeout and got the same results... if there are same characters in a row, the duplicate character(s) are omitted. It seems like this command line program doesn't agree very well with SendMessage or PostMessage. SendKeys seems to be more reliable in this application, which shocks me. I won't be able to hide the command line window if I use SendKeys, but I'm willing to give in on that if it makes the program more reliable.
-
Re: Need to start a command line window and send a string to it
a little improve to Edgemeal code and it works as you wanted.
Code:
Option Explicit
Private Const WM_CHAR = &H102
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Sub Form_Load()
'open a hidden dos prompt window (WinXP).
Shell "c:\windows\system32\cmd.exe"
End Sub
Private Sub Command1_Click()
Dim h As Long
Dim result As Boolean
' find dos prompt window
h = FindWindow(vbNullString, "c:\windows\system32\cmd.exe")
If h Then
' send "calc.exe" followed by carraige return
result = SendTxt(h, "calc.exe" & vbCr)
result = SendTxt(h, "echo tteesstt" & vbCr)
' optional, check postmessage result
If result = False Then MsgBox "postmessage failed!"
'close the hidden dos prompt window
'SendTxt h, "exit" & vbCr
Else
MsgBox "dos prompt window not found"
End If
End Sub
Private Function SendTxt(ByVal Handle As Long, ByVal sText As String) As Boolean
Dim i As Integer
Dim lngReturn As Long
Dim i1 As Long, last1 As Long
For i = 1 To Len(sText)
i1 = Asc(Mid$(sText, i, 1))
If i1 = last1 Then Call PostMessage(Handle, WM_CHAR, 0, 0&)
lngReturn = PostMessage(Handle, WM_CHAR, i1, 0&)
If lngReturn <> 1 Then Exit Function ' failed
last1 = i1
Next i
SendTxt = True ' passed
End Function
-
Re: Need to start a command line window and send a string to it
If the old vpncli supports the stdin command line option there is a better way. You can send commands to the program via an anonymous pipe.
-
Re: Need to start a command line window and send a string to it
Sounds promising! How would I do that, dilettante?
-
Re: Need to start a command line window and send a string to it
BrianPaul i hope you didn't miss my last post, because it's working very well,
and IMO, this is the most correct way to do what you want.
-
Re: Need to start a command line window and send a string to it
Quote:
Originally Posted by
BrianPaul
Sounds promising! How would I do that, dilettante?
When you started this thread there was an almost identical one posted next to it. I provided a possible answer there that you might look at:
How to create a front end in VB for a C code?
Of course this only works for a console subsystem program that was written with the intent of being scripted. In other words the program needs to use the Standard I/O streams instead of interacting through Console Device APIs.
The important question is whether or not your vpncli.exe supports "scripting" via pipes.
The newer vpnclient.exe from Cisco seems to, if I can believe the many anguished posts on this subject I found when Googling. But the only advice for vpncli.exe users I found went something like "well try it!" In other words try running vpncli.exe /? to see what options it supports.
This should also be clearly documented in your Cisco manual. I couldn't find an answer by checking the online version of the manual for vpncli.exe though.
If your older VPN client doesn't support I/O redirection then of course you're back to the flaky "window hijacking" techniques (SendKeys, SendMessage/PostMessage, etc.) you've been struggling with.
-
Re: Need to start a command line window and send a string to it
Unfortunately vpncli.exe doesn't support switches like vpnclient.exe. With vpnclient.exe, you can do...
vpnclient connect <profile> [user <username>][eraseuserpwd | pwd <password>]
The only thing vpncli.exe supports is sending commands like connect with the IP address, stats and disconnect, but there is no switch for username and password. I spoke with a Cisco engineer to verify this. I can use vpnclient.exe, but the Cisco engineer recommended using vpncli.exe. He explained that Cisco AnyConnect is the direction that Cisco is moving customers toward and that it has more functionality. I might need to consider if the added functions are anything we would be using. Maybe using vpnclient.exe would be a better fit for us since I would be able send the entire command (including username and password) to the command line.
-
Re: Need to start a command line window and send a string to it
Quote:
Originally Posted by
Edgemeal
If the window is accepting the one character then you could just create a sub to send each character of the string for you, see the SendTxt Function in the example...
Code:
Option Explicit
Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Long
Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Long, ByVal wMsg As Long, ByVal wParam As Long, ByVal lParam As Long) As Long
Private Const WM_CHAR = &H102
Private Sub Form_Load()
'open a hidden dos prompt window (WinXP).
Shell "c:\windows\system32\cmd.exe", vbHide
End Sub
Private Sub Command1_Click()
Dim h As Long
Dim result As Boolean
' find dos prompt window
h = FindWindow(vbNullString, "c:\windows\system32\cmd.exe")
If h Then
' send "calc.exe" followed by carraige return
result = SendTxt(h, "calc.exe" & vbCr)
' optional, check postmessage result
If result = False Then MsgBox "postmessage failed!"
'close the hidden dos prompt window
SendTxt h, "exit" & vbCr
Else
MsgBox "dos prompt window not found"
End If
End Sub
Private Function SendTxt(ByVal Handle As Long, ByVal sText As String) As Boolean
Dim i As Integer
Dim lngReturn As Long
For i = 1 To Len(sText)
lngReturn = PostMessage(Handle, WM_CHAR, Asc(Mid$(sText, i, 1)), 0&)
If lngReturn <> 1 Then Exit Function ' failed
Next i
SendTxt = True ' passed
End Function
btw, Look up WM_SETTEXT on MSDN, I believe its mainly used for edit controls and title text.
I found this code very usefull for my project, only one thing missing,
how to get output from cmd promt ?
I use this code for sending commands to running proces, but I would also
like to capture answer to a rtf.text from console!
B.R
-
Re: Need to start a command line window and send a string to it
-
Re: Need to start a command line window and send a string to it
Try this example from Planet Source Code, I checked it and it seems to work.
"This is User-Friendly, CPU-Friendly, NON-BLOCKING Standard Input-Output code to grab output of a command line interface program, AND, for the first time ever (in open source in VB), to send input to it as well."
http://www.planet-source-code.com/vb...61262&lngWId=1
-
Re: Need to start a command line window and send a string to it
What about redirecting input?
program.exe < keys.txt
where program.exe is the program to run and keys.txt contains the input for the program.
I haven't tried it but I would expect it would work via shell
-
Re: Need to start a command line window and send a string to it
The POS Code thing is a sort of defective example of the sort of thing I already posted a link to. Amazing how much the guy drools on his shoes over something with Sleep() calls sapping performance and uncontrolled DoEvents() calls along with those.
-
Re: Need to start a command line window and send a string to it
dilettante, I checked the example you referred to here: http://www.vbforums.com/showthread.php?t=614897; however, it doesn't look like it was designed for the command line interface. I tested the example I posted from PSC and did not notice any defects; what seems to be the problem with it?
-
Re: Need to start a command line window and send a string to it
I think you need to look closer. The example I provided does exactly that.
The one you linked to has the problem that once you call its run/execute method it never returns to the caller until the program it runs gets done. All of the rest of your program is trapped there, waiting on a slow and costly DoEvents + Sleep loop. I'm not even sure how you'd use it to run two or more parallel child processes.
Not to mention the code is full of slow String operations and slower Variant operations, does silly things like adding NULs where there are already NULs. The code is of very poor quality, and even haphazardly uses the silly Call statement making the style something best described as "ransom note." It looks like a typical example of the bad programming you find at that site.
-
Re: Need to start a command line window and send a string to it
dilettante, I looked at your example again, and again I was unable to use it to interact with the command line; it looks like it would need a substantial amount of work to get it to the level of functionality provided in the example from PSC.
Quote:
The one you linked to has the problem that once you call its run/execute method it never returns to the caller until the program it runs gets done. All of the rest of your program is trapped there, waiting on a slow and costly DoEvents + Sleep loop.
These examples are just about reading from and writing to pipes attached to processes to allow a Vb6 application to interact with external applications, which is relatively easy to implement (if you have a good example to work from) and happens to work nicely in the case of cmd.exe. Writing to a pipe is not very difficult, reading data from a pipe means programatically checking the pipe for any new data that arrives, and one method to do this involves using a timer. In the PSC example he uses a do loop containing sleep 30 to emulate a timer with the the interval set to 30 milliseconds which checks for new data. Your version uses a timer with the interval set to 300 milliseconds which also calls doevents, so for me there is not any fundamental difference between your approaches in this regard.
Additionally the programmer states it was only a couple of days work: "It took me a few days (with the help of two friends Zak and Espen w/ debugging and C++ testing, etc) to code this", which also needs to be factored into any criticism.
After looking at both examples, I can indicate that the PSC code is a working example of how to use pipes to fully interact with the command line which contains clear and easy to read code which is extensively documented and that it is definitely a good place to start for anyone trying to establish full interactivity with the command line from their vb6 application. By contrast your example doesn't include a working example showing how to use pipes to interact with the command line, and contains almost no code documentation, which makes it much more difficult to understand, and essentially impossible to use as the basis for a cmd line interface if the developer has no prior knowledge of pipe IPC. As a result the PSC example certainly does not deserve to be called bad programming much less a ransom note especially given the charitable nature of the example. In fact, taking all factors into account, I think that these attacks might actually be deemed libelous and that you should be much more careful with your use of language in the future. For example Article 17 of the International Covenant on Civil and Political Rights states that: "1. No one shall be subjected to [...] unlawful attacks on his honour and reputation. 2. Everyone has the right to the protection of the law against such interference or attacks." http://www2.ohchr.org/english/law/ccpr.htm