| |
VB.NET - Ein- und UmsteigerProzess starten und in eigene Anwendung einbinden | | | Autor: Marcus W | Datum: 13.01.14 21:09 |
| Hallo zusammen,
zunächst möchte ich sagen, dass ich etwas eingerostet bin was VB.Net angeht. Wenn mein Anliegen also zu sehr nach "Mach das mal für mich" klingt, möchte ich mich vorab entschuldigen. Da läge mir fern. Es geht mir darum, das Prinzip zu verstehen und daraus die Lösung selbst herauszuarbeiten.
Ich suche eine Möglichkeit, in meiner Forms-Anwendung einen Prozess (namentlich ein CMD-Skript) mit einem Butten zu starten und den dann gleich in ein Panel auf meiner Form einzubinden.
Um genau zu sein hab ich ein TabControl mit drei Seiten auf denen drei verschiedene Skripts eingebunden werden sollen. Das werde ich aber sicher alleine schaffen, wenn ich das Prinzip verstanden habe.
Wie man einen Prozess startet, weiß ich. Wie ich einen laufenden Prozess in ein Panel auf meiner Form bringe, hab ich hier gefunden: http://www.vb-paradise.de/allgemeines/sourcecode-austausch/11599-prozess-in-die-eigene-anwendung-einbetten-und-wieder-freigeben/#post62453
Ich hab mir schon Gedanken gemacht, dass ich beim Start des Prozesses dessen Handle abfangen muss um ihn damit an mein Panel zu binden.
So, wie ich das sehe, muss ich irgendwo zwischen Zeile 30 und 47 im verlinkten Code aktiv werden.
Wenn ich dann noch gesagt bekäme, wie die die eingebundenen Prozesse beim FormClosing-Event beenden kann, wäre das das Sahnehäubchen.
Für Eure Hilfe schon mal vielen Dank im voraus.
Ich hoffe, dass das kein Dopplepost ist. Über die Suche hab ich nix gefunden.
Gruß
Marcus | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: killroy | Datum: 13.01.14 22:45 |
| Schau mal hier, habe das gleiche Problem mit alten DOS-Programmen gehabt, die ich auch im Fenster plazieren wollte. Sieht insgesamt etwas anders aus, ist aber prinzipiell gleich.
Module Deklarationen
Public ETCAWin As NativeWindow 'ist mein DOS-Fenster
Private Sub mainForm_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
ETCAWin = New NativeWindow
Private Sub mainForm_FormClosed(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) Handles Me.FormClosed
If ETCAWin.Handle <> 0 Then ETCAWin.DestroyHandle()
That's all | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Marcus W | Datum: 14.01.14 19:38 |
| @killroy:
Danke für den Tip.
Jetzt funktioniert's.
Gruß
Marcus | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Marcus W | Datum: 18.01.14 18:33 |
| So, ich hab das jetzt wie folgt gelöst:
Public Class frmMain
'benötigte APIs
Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As _
IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hWnd As IntPtr, _
ByVal flag As Integer) As IntPtr
Public Declare Function MoveWindow Lib "user32" (ByVal hwnd As Int32, _
ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal bRepaint As Boolean) As Boolean
'ShowWindow-Konstanten
Private Const SW_NORMAL As Integer = 1
'ProzessID des eingebetteten fensters merken
Private intProgrammID As Integer
Private Sub Starten
StartProgramm("cmd.exe", TabPage1, intProgrammID)
End Sub
Private Sub Stoppen
Try
Process.GetProcessById(intProgrammID).Kill()
Catch
End Try
End Sub
Private Sub StartProgramm(ByVal Programm As String, ByVal Seite As TabPage, _
ByRef ProgrammID As Integer)
'<übergebene Parameter>
'Programm = das Programm, das gestartet werden soll
'Seite = die Seite eines TabControls, auf der das Programm angezeigt
' werden soll
'ProgrammID = ProzessID des aufgerufenen Programms
' ByRef, um mit dem Aufruf des Programms der globalen Variable
' intProgrammID die ProzessID zu übergeben
' (wird in der Prozdur "Stoppen gebraucht)
'</übergebene Parameter>
Dim Handle As IntPtr 'MainWindowHandle des gestarteten Programms
'Programm starten
ProgrammID = Process.Start(Programm).Id
'Warten, bis aufgerufenes Programm ein MainWindowsHandle hat
Do
Application.DoEvents()
Loop Until Process.GetProcessById(ProgrammID).MainWindowHandle <> 0
Handle = Process.GetProcessById(ProgrammID).MainWindowHandle
'DOS-Box in Tabpage einbetten
SetParent(Handle, Seite.Handle)
'WindowState der DOS-Box auf "normal" setzen
ShowWindow(Handle, SW_NORMAL)
'DOS-Box auf TabPage zentrieren
MoveWindow(Handle, 10, 8, 670, 440, True)
End Sub
End Class Im Beispiel könnte man das im Sub Starten abfackeln. Da ich aber 4 Programme starte, hab ich das über das Sub StartProgramm mit Parameterübergabe gemacht.
Die Subs Starten und Stoppen sind normalerweise Buttons. Der Lesbarkeit halber, habe ich hier auf die lange Button_Click(...)-Zeile verzichtet.
Gruß
Marcus
Beitrag wurde zuletzt am 18.01.14 um 18:39:03 editiert. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: killroy | Datum: 20.01.14 13:13 |
| Hi,
fast exakt das Gleiche, was ich bei meiner Anwendung gemacht habe.
Auch ich starte optional mehrere DOS-Sitzungen parallel, das Ganze aus einer gemeinsamen Oberfläche raus, allerdings über ein Auswahlmenü.
Ich würde auf jeden Fall, auch wenn es nur eine Instanz gäbe, stets eine separate Startroutine haben wollen, ist einmal pflegeleichter und ... warum nicht sauber modularisiern, ggf, für spätere Einsatzzwecke.
ACHTUNG: Ich hatte da noch ein weiteres Problem, nämlich dass die Positionierung einfach nicht angenommen wurde.
Eine (pragmatische) Lösung dazu war der Einbau von Wartezeiten nach dem Start des DOS-Fensters
Hier meine Startroutine:
Private Sub ETCAStart()
...If ETCAWin IsNot Nothing Then
......If Not CBool(IsWindowVisible(ETCAWin.Handle)) Then
.........ShowWindow(ETCAWin.Handle, 1)
.........If Not CBool(IsWindowVisible(ETCAWin.Handle)) Then Exit Sub
......Else
.........ShowWindow(ETCAWin.Handle, 1)
.........If CBool(IsWindowVisible(ETCAWin.Handle)) Then Exit Sub
......End If
...End If
...ETCA.StartInfo.WorkingDirectory = PointOfKalk & "ETCASIE"
...PrgDrive.Text = ETCA.StartInfo.WorkingDirectory
...ETCA.StartInfo.FileName = "cmd"
...ETCA.StartInfo.Arguments = "/K""GEATEC.EXE ETCA"""
...ETCA.StartInfo.CreateNoWindow = False
...ETCA.StartInfo.UseShellExecute = True
...ETCA.Start()
...Dim hwnd As IntPtr = IntPtr.Zero
...System.Threading.Thread.Sleep(500)
...Application.DoEvents()
...hwnd = ETCA.MainWindowHandle
...Try
......ETCAWin.AssignHandle(ETCA.MainWindowHandle)
...Catch ex As Exception
...End Try
...SetParent(hwnd.ToInt32, ETCAPanel.Handle.ToInt32)
...System.Threading.Thread.Sleep(300)
...Application.DoEvents()
...SetWindowTextW(ETCAWin.Handle, "ETCA Siemensversion")
...SetWindowPos(ETCAWin.Handle, 0, 0, 0, 0, 0, &H1 + &H40)
...System.Threading.Thread.Sleep(200)
...Application.DoEvents()
End Sub
Ob nun 500 oder 300 ms, muss man einfach ausprobieren.
Ich bin eben auf diese Werte gekommen.
Hängt vielleicht damit zusammen, dass nach dem Öffnen des Fensters einige vorbereitende und relativ zeitaufwändige Operationen durchgeführt werden, wie gesagt, nur 'ne Vermutung.
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 20.01.14 15:26 |
| Wenn Du Demo-Code postest, solltest Du auch die erforderlichen
Variablen-Deklarationen, APIs und (Nicht-Standard-)Imports angeben.
Private Sub ETCAStart()
If ETCAWin IsNot Nothing Then
If Not CBool(IsWindowVisible(ETCAWin.Handle)) Then
ShowWindow(ETCAWin.Handle, 1)
If Not CBool(IsWindowVisible(ETCAWin.Handle)) Then Exit Sub
Else
ShowWindow(ETCAWin.Handle, 1)
If CBool(IsWindowVisible(ETCAWin.Handle)) Then Exit Sub
End If
End If
ETCA.StartInfo.WorkingDirectory = PointOfKalk & "ETCASIE"
PrgDrive.Text = ETCA.StartInfo.WorkingDirectory
With ETCA.StartInfo
.FileName = "cmd"
.Arguments = "/K""GEATEC.EXE ETCA"""
.CreateNoWindow = False
.UseShellExecute = True
End With
ETCA.Start()
Dim hwnd As IntPtr = IntPtr.Zero
System.Threading.Thread.Sleep(500)
Application.DoEvents()
hwnd = ETCA.MainWindowHandle
Try
ETCAWin.AssignHandle(ETCA.MainWindowHandle)
Catch ex As Exception
'??????????
End Try
SetParent(hwnd.ToInt32, ETCAPanel.Handle.ToInt32)
System.Threading.Thread.Sleep(300)
Application.DoEvents()
SetWindowTextW(ETCAWin.Handle, "ETCA Siemensversion")
SetWindowPos(ETCAWin.Handle, 0, 0, 0, 0, 0, &H1 + &H40)
System.Threading.Thread.Sleep(200)
Application.DoEvents()
End Sub | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: killroy | Datum: 20.01.14 22:45 |
| Jau, hast recht...
Hier ...
#Region "APIs"
<Runtime.InteropServices.DllImport("User32", _
CharSet:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=True)> _
Public Function IsWindowVisible(ByVal hWnd As Integer) As Integer
End Function
<Runtime.InteropServices.DllImport("User32", _
CharSet:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=True)> _
Public Function ShowWindow(ByVal hWnd As Integer, ByVal nCmdShow As _
Integer) As Integer
End Function
<Runtime.InteropServices.DllImport("User32", _
CharSet:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=True)> _
Public Function SetParent(ByVal hWndChild As IntPtr, ByVal hWndParent As _
IntPtr) As IntPtr
End Function
<Runtime.InteropServices.DllImport("User32", _
CharSet:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=True)> _
Public Sub SetWindowTextW(ByVal hWnd As Integer, ByVal lpString As String)
End Sub
<Runtime.InteropServices.DllImport("User32", _
CharSet:=Runtime.InteropServices.CharSet.Auto, ExactSpelling:=True)> _
Public Sub SetWindowPos(ByVal hWnd As Integer, ByVal hWndInsertAfter As _
Integer, ByVal X As Integer, ByVal Y As Integer, ByVal cx As Integer, ByVal _
cy As Integer, ByVal wFlags As Integer)
End Sub
#End Region | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 24.04.14 13:41 |
| Das ist eine super Lösung!!!
Wie kann ich denn bei Marcus W's Lösung noch Startinfos festlegen...irgendwie hänge ich da fest!?
Also zB so in dieser Art:
StartInfo.FileName = "Programmname"
StartInfo.Arguments = "StartArgument1"
StartInfo.Arguments = "StartArgument2"
'usw Danke Euch im Voraus... | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 24.04.14 14:12 |
| Danke....grundsätzlich ist mir das bekannt. Deshalb anders gefragt:
wie kann ich anhand von Marcus W's Beispiel dem Programm, welches ich ins Panel einbette, Startargumente übergeben? Also irgendwo hier müsste das doch noch rein, oder nicht?:
Private Sub StartProgramm(ByVal Programm As String, ByVal Seite As TabPage, _
ByRef ProgrammID As Integer)
'<übergebene Parameter>
'Programm = das Programm, das gestartet werden soll
'Seite = die Seite eines TabControls, auf der das Programm angezeigt
' werden soll
'ProgrammID = ProzessID des aufgerufenen Programms
' ByRef, um mit dem Aufruf des Programms der globalen Variable
' intProgrammID die ProzessID zu übergeben
' (wird in der Prozdur "Stoppen gebraucht)
'</übergebene Parameter>
Dim Handle As IntPtr 'MainWindowHandle des gestarteten Programms
'Programm starten
ProgrammID = Process.Start(Programm).Id
'Warten, bis aufgerufenes Programm ein MainWindowsHandle hat
Do
Application.DoEvents()
Loop Until Process.GetProcessById(ProgrammID).MainWindowHandle <> 0
Handle = Process.GetProcessById(ProgrammID).MainWindowHandle
'DOS-Box in Tabpage einbetten
SetParent(Handle, Seite.Handle)
'WindowState der DOS-Box auf "normal" setzen
ShowWindow(Handle, SW_NORMAL)
'DOS-Box auf TabPage zentrieren
MoveWindow(Handle, 10, 8, 670, 440, True)
End Sub Zudem haut er mir bei
'DOS-Box auf TabPage zentrieren
MoveWindow(Handle, 10, 8, 670, 440, True) folgenden Fehler raus:
PInvokeStackImbalance wurde erkannt.
Message: Ein Aufruf an die PInvoke-Funktion "ExternesProgrammEinbetten!WindowsApplication1.Form1::MoveWindow" hat das Gleichgewicht des Stapels gestört. Wahrscheinlich stimmt die verwaltete PInvoke-Signatur nicht mit der nicht verwalteten Zielsignatur überein. Überprüfen Sie, ob die Aufrufkonvention und die Parameter der PInvoke-Signatur mit der nicht verwalteten Zielsignatur übereinstimmen.
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 24.04.14 14:27 |
| Ja, das meine ich!
Zum einen, weil der dort wiedergegebene Code trivial ist
und zum anderen, weil man sich den Code auf developerfusion.com
in VB.Net übersetzen lassen kann
(Es gibt im Internet wesentlich mehr Code-Beispiel zu C#, die
aber gewöhnlich auf für VB.Net-Anwender relevant sind.)
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 24.04.14 14:34 |
| Streitet euch doch nicht
Die Eigenschaften der Process.Start-Methode sind mir bekannt....
Ich bitte nur um Hilfe, diese in o.g. Beispiel einzubauen, bitte.
...und vlt noch Hilfe bei dem genannten Fehler.
Danke
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 24.04.14 15:01 |
|
Zitat: | | Aber: Ich verstehe das Problem nicht: | |
Ok,ok...ich merke es schon (nicht bös gemeint)
Den Fehler bei MoveWindow habe ich ausgemerzt, das funktioniert schonmal jetzt.
Ich versuche es noch einmal
Ich möchte in diesem Code von Marcus W die cmd.exe mit Startargumenten versehen und dann in dem Panel starten. WIE ich Startargumente setze weiss ich, ich frage lediglich nach einer Hilfestellung WO in diesem Beispiel ich diese setzen muss... :
Public Class frmMain
'benötigte APIs
Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As _
IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hWnd As IntPtr, _
ByVal flag As Integer) As IntPtr
Public Declare Function MoveWindow Lib "user32" (ByVal hwnd As Int32, _
ByVal x As Long, ByVal y As Long, _
ByVal nWidth As Long, ByVal nHeight As Long, _
ByVal bRepaint As Boolean) As Boolean
'ShowWindow-Konstanten
Private Const SW_NORMAL As Integer = 1
'ProzessID des eingebetteten fensters merken
Private intProgrammID As Integer
Private Sub Starten
StartProgramm("cmd.exe", TabPage1, intProgrammID)
End Sub
Private Sub Stoppen
Try
Process.GetProcessById(intProgrammID).Kill()
Catch
End Try
End Sub
Private Sub StartProgramm(ByVal Programm As String, ByVal Seite As TabPage, _
ByRef ProgrammID As Integer)
'<übergebene Parameter>
'Programm = das Programm, das gestartet werden soll
'Seite = die Seite eines TabControls, auf der das Programm angezeigt
' werden soll
'ProgrammID = ProzessID des aufgerufenen Programms
' ByRef, um mit dem Aufruf des Programms der globalen Variable
' intProgrammID die ProzessID zu übergeben
' (wird in der Prozdur "Stoppen gebraucht)
'</übergebene Parameter>
Dim Handle As IntPtr 'MainWindowHandle des gestarteten Programms
'Programm starten
ProgrammID = Process.Start(Programm).Id
'Warten, bis aufgerufenes Programm ein MainWindowsHandle hat
Do
Application.DoEvents()
Loop Until Process.GetProcessById(ProgrammID).MainWindowHandle <> 0
Handle = Process.GetProcessById(ProgrammID).MainWindowHandle
'DOS-Box in Tabpage einbetten
SetParent(Handle, Seite.Handle)
'WindowState der DOS-Box auf "normal" setzen
ShowWindow(Handle, SW_NORMAL)
'DOS-Box auf TabPage zentrieren
MoveWindow(Handle, 10, 8, 670, 440, True)
End Sub
End Class Falls immer noch nicht verstanden ist, was ich suche, dann versuche ich es erst einmal allein weiter. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: powerzone3000 | Datum: 24.04.14 15:11 |
| Indem du der Process.Start-Methode deine Argumente oder ein ProcessStartInfo-Objekt mitgibst:
'Programm starten
ProgrammID = Process.Start(Programm, "argument1 argument2").Id oder
Dim psi As New ProcessStartInfo
With psi
.FileName = Programm
.Arguments = "argument1 argument2"
End With
ProgramID = Process.Start(psi).Id | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 24.04.14 15:55 |
| Super !! Danke, das funktioniert !! | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 12:18 |
|
Noch eine Frage....
Kann ich neben den Startargumenten auch noch Befehle an den "gekidnappten" Prozess senden (via Code)?
Schriftart und -farbe des "gekidnappten" Prozesses kann man wahrscheinlich nicht verändern, oder?
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: killroy | Datum: 25.04.14 12:45 |
| ... denke mal, gemeint ist nach dem Start, situationsbezogen.
Es gibt im Prozessbereich die StandartIn/Out-Kanäle für den Prozess, die dazu genutzt werden können.
Bin derzeit leider nicht im Code, deshalb nur der Tip dazu, hilft vielleicht schon. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 13:42 |
| Hallo!
Du kannst Tastencodes an das jeweils aktive Fenster senden:
http://msdn.microsoft.com/en-us/library/system.windows.forms.sendkeys.send%28v=vs.110%29.aspx
Erlaubt das Ziel-Programm die Wahl von Schriftart/-farbe durch den User, kannst Du die dafür erforderliche Folge von Tastencodes senden.
Muß die Ziel-Anwendung erst aktiviert werden, ist die Nutzung von Windows-Apis nötig:
[I]Because there is no managed method to activate another application, you can either use this class within the current application or use native Windows methods, such as FindWindow and SetForegroundWindow, to force focus on other applications.[/I]
Beitrag wurde zuletzt am 25.04.14 um 13:50:10 editiert. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 13:51 |
| Ja, Danke Manfred...
Mit sendkeys probiere ich es gerade. Proplem ist, wenn ich z.B. sage:
SendKeys.Send("cd \di") Dann bekomme ich als Ausgabe zB: ccddddddddddddd \\\\\\\\\\\\\\di
Wobei die Anzahl der einzelnen Zeichen nie gleich bleibt!
SendKeys.SendWait("cd \di") hilft auch nicht weiter. Genausowenig, das senden der einzelnen Keys nacheinander.... | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 14:18 |
|
Das Beispiel funktioniert irgendwie so garnicht...
Bei mir wird nur ein leeres Formular angezeigt, sonst nichts...leider auch kein Fehler...
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 14:44 |
| Probier mal diese Variante ... (Code in ein frisches Startformular einfügen)
Imports System
Imports System.Runtime.InteropServices
Imports System.Drawing
Imports System.Windows.Forms
Public Class frmCalculator
Inherits Form
Private WithEvents button1 As New Button()
Public Sub New()
button1.Location = New Point(10, 10)
button1.TabIndex = 0
button1.Text = "Click to automate Calculator"
button1.AutoSize = True
Me.Controls.Add(button1)
End Sub
' Get a handle to an application window.
Declare Auto Function FindWindow Lib "USER32.DLL" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As IntPtr
' Activate an application window.
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
' Send a series of key presses to the Calculator application.
Private Sub button1_Click(ByVal sender As Object, _
ByVal e As EventArgs) Handles button1.Click
' Get a handle to the Calculator application. The window class
' and window name were obtained using the Spy++ tool.
Dim calculatorHandle As IntPtr = FindWindow("SciCalc", "Rechner")
' Verify that Calculator is a running process.
If calculatorHandle = IntPtr.Zero Then
MsgBox("Calculator is not running.")
Return
End If
' Make Calculator the foreground application and send it
' a set of calculations.
SetForegroundWindow(calculatorHandle)
SendKeys.SendWait("111")
SendKeys.SendWait("*")
SendKeys.SendWait("11")
SendKeys.SendWait("=")
End Sub
' Send a key to the button when the user double-clicks anywhere
' on the form.
Private Sub Form1_DoubleClick(ByVal sender As Object, _
ByVal e As EventArgs) Handles Me.DoubleClick
' Send the enter key to the button, which raises the click
' event for the button. This works because the tab stop of
' the button is 0.
SendKeys.Send("{ENTER}")
End Sub
Private Sub InitializeComponent()
Me.SuspendLayout()
'
'frmCalculator
'
Me.ClientSize = New System.Drawing.Size(292, 273)
Me.Name = "frmCalculator"
Me.ResumeLayout(False)
End Sub
End Class | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 14:57 |
| ...genau dasselbe | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 15:30 |
| Noch einfacher kann ic nicht.
Neues Formular erstellen und folgenden Code einfügen:
Public Class frmNotePad
'Ab hier einfügen
' Activate an application window.
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
Dim WithEvents btnsenden As New Button With {.Parent = Me, .Text = "Senden"}
Private Sub btnsenden_Click(sender As Object, e As System.EventArgs) _
Handles btnsenden.Click
Dim p As Diagnostics.Process = Diagnostics.Process.Start("Notepad.exe")
If p.Handle = IntPtr.Zero Then
MsgBox("Editor konnte nicht gestartet werden")
Else
If Not SetForegroundWindow(p.Handle) Then
MsgBox("Fenster konnte nicht in den Vordergrund gebracht" & _
"werden")
Else
Threading.Thread.Sleep(2000)
SendKeys.Send("Das muß jetzt aber geklappt haben!!!")
End If
End If
End Sub
'Bis hier einfügen
End Class | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 15:50 |
| Ja sorry....*Brett vorm Kopf habe*
Das funktioniert einwandfrei .... | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 15:53 |
| Kann es sein, daß Du eine bestimmte Tastenkombination an die
andere Anwendung sendest, die dazu führt, daß für die folgenden
Eingaben eine Wiederhol-Funktion aktiviert wird?
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 15:58 |
| Nein, das ist nicht der Fall....
Wenn ich deinen letzten Code so abändere dass meine gewünschte Anwendung gestartet wird (eine DOS Konsole, aber nicht cmd.exe) und das
SendKeys.Send("Das muß jetzt aber geklappt haben!!!") in
SendKeys.Send("cd \di") ändere, so wird mir "cdi" also ohne Leerzeichen und ohne Backslash ausgegeben.... | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 16:06 |
| In "cmd.exe" käme die gesendete Zeichenfolge korrekt an.
Kann der Benutzer diese Zeichenfolge direkt an der Console eingeben,
ohne daß es während der Eingabe bereits zu Reaktionen kommt?
| |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 16:10 |
| (Wollte gerade editieren, da hattest du wohl schon geantwortet)
In Notepad wird einwandfrei alles geschrieben...Leerzeichen und \ ...
In cmd.exe wird das Leerzeichen ausgelassen und cd\i geschrieben
Ja, in der Konsole kann ich es "von Hand" einwandfrei eingeben, ohne Reaktionen während der Eingabe. Möchte es allerdings gern automatisiert, nach dem "cd \di" würden noch 2 weitere Eingaben erfolgen.... | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 16:24 |
| Das verschluckte Leerzeichen im "cmd"-Fenster kann ich nicht bestätigen.
Sende nach jeder Eingabefolge ein "{Enter}" und schicke danach
die nächste Anweisung ab (falls es dabei nicht um irreversible
Modifikationen im Dateisystem geht!)
Vielleicht benötigt das Argument Hochkommas:
SendKeys.Send("cd " & Chr(34) & "/di" & Chr(34))
Beitrag wurde zuletzt am 25.04.14 um 16:27:33 editiert. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 25.04.14 16:46 |
|
Hochkommas sind auch nicht die Lösung
Das ist alles ganz nett, bringt mich nur irgendwie nicht weiter.
Ich denke ich sollte zuerst die Konsole inkl Argumenten und Befehlen starten und DANN erst "kidnappen".
Denn so wie momentan funktioniert es leider nicht....
Gemäß Marcus W's Beispiel:
Public Sub StartProgramm(ByVal Programm As String, ByVal Seite As TabPage, _
ByRef ProgrammID As Integer)
'<übergebene Parameter>
'Programm = das Programm, das gestartet werden soll
'Seite = die Seite eines TabControls, auf der das Programm angezeigt
' werden soll
'ProgrammID = ProzessID des aufgerufenen Programms
' ByRef, um mit dem Aufruf des Programms der globalen
' Variable
' intProgrammID die ProzessID zu übergeben
' (wird in der Prozdur "Stoppen gebraucht)
'</übergebene Parameter>
Dim Handle As IntPtr 'MainWindowHandle des gestarteten Programms
'********************************************************
Dim psi As New ProcessStartInfo
With psi
.FileName = Programm
.Arguments = "/k c:\lib\se ts510502 -pts510502"
.Arguments = "/k c:\lib\se g7sis -pts510502"
End With
ProgrammID = Process.Start(psi).Id
'********************************************************
'Warten, bis aufgerufenes Programm ein MainWindowsHandle hat
Do
Application.DoEvents()
Loop Until Process.GetProcessById(ProgrammID).MainWindowHandle <> 0
Handle = Process.GetProcessById(ProgrammID).MainWindowHandle
'DOS-Box in Tabpage einbetten
SetParent(Handle, Seite.Handle)
'WindowState der DOS-Box auf "normal" setzen
ShowWindow(Handle, SW_NORMAL)
'DOS-Box auf TabPage zentrieren
MoveWindow(Handle, -3, -28, 670, 440, True)
End Sub Dann der Aufruf des Programms (und da wollte ich eigtl direkt die Befehlseingabe setzen, was ja nicht klappt):
Private Sub btnStart_Click(sender As Object, e As EventArgs) Handles _
btnStart.Click
StartProgramm("C:\4D\tcc.exe", TabPage1, intProgrammID)
SendKeys.Send("cd \di")
End Sub | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 17:02 |
| Wie wäre es, wenn Du das ForeGroundwindow setzt, ehe Du sendest:
SetForegroundWindow(intProgrammID) 'Process-Handle
Beitrag wurde zuletzt am 25.04.14 um 17:14:33 editiert. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: Manfred X | Datum: 25.04.14 17:55 |
| Imports System.Diagnostics
Public Class frmtest4
'benötigte APIs
Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As _
IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
Private Declare Function ShowWindow Lib "user32.dll" (ByVal hWnd As _
Integer, _
ByVal flag As Integer) As IntPtr
Public Declare Function MoveWindow Lib "user32" (ByVal hWnd As IntPtr, _
ByVal x As Integer, ByVal y As Integer, _
ByVal nWidth As Integer, ByVal nHeight As Integer, _
ByVal bRepaint As Boolean) As Boolean
' Activate an application window.
Declare Auto Function SetForegroundWindow Lib "USER32.DLL" _
(ByVal hWnd As IntPtr) As Boolean
'ShowWindow-Konstanten
Private Const SW_NORMAL As Integer = 1
'ProzessID des eingebetteten fensters merken
Private intProgrammID As Integer
Dim tc As New TabControl With {.Parent = Me, .Width = 600, .Height = 650}
Private Sub frmtest4_Load(sender As System.Object, _
e As System.EventArgs) Handles MyBase.Load
Me.Width = 650 : Me.Height = 680
tc.TabPages.Add("Test")
Starten()
End Sub
Private Sub Starten()
Dim handle As IntPtr
StartProgramm("cmd.exe", tc.TabPages(0), intProgrammID, Handle)
If Not SetForegroundWindow(handle) Then Stop
SendKeys.Send("Color f0")
SendKeys.Send("{Enter}")
Dim direc As String = _
My.Computer.FileSystem.SpecialDirectories.MyPictures
SendKeys.Send("Cd " & direc)
SendKeys.Send("{Enter}")
End Sub
Public Sub StartProgramm(ByVal Programm As String, ByVal Seite As TabPage, _
ByRef ProgrammID As Integer, ByRef procHandle As IntPtr)
Dim psi As New ProcessStartInfo
With psi
.FileName = Programm
End With
Dim p As Process = Process.Start(psi)
Threading.Thread.Sleep(1000)
procHandle = p.MainWindowHandle
ProgrammID = p.Id
'DOS-Box in Tabpage einbetten
SetParent(procHandle, Seite.Handle)
'WindowState der DOS-Box auf "normal" setzen
ShowWindow(CInt(procHandle), SW_NORMAL)
'DOS-Box auf TabPage zentrieren
Dim mw As Boolean = _
MoveWindow(procHandle, 0, 0, Seite.Width, Seite.Height, True)
End Sub
End Class
Beitrag wurde zuletzt am 25.04.14 um 18:02:48 editiert. | |
Re: Prozess starten und in eigene Anwendung einbinden | | | Autor: catweazle2k3 | Datum: 09.07.14 14:26 |
| Hallo zusammen,
es läuft jetzt bei mir wie ich es gewollt habe (längere Zeit schon)! Alles vielen Dank für die Hilfe.
Noch eine Sache: Wenn ich die Größe der Form veränder, durch ziehen am Rand oder an der Ecke, hätte ich gerne dass sich das eingefangene Fenster entsprechend auch verkleinert bzw vergrössert. Ich habe schon mehrere Varianten versucht, aber es ändert sich immer nur die Größe des Containers...das eingefangene Fenster behält immer seine ursprüngliche Größe....
Hat jemand eine Idee oder einen Ansatz?
Danke nochmal.... | |
| Sie sind nicht angemeldet! Um auf diesen Beitrag zu antworten oder neue Beiträge schreiben zu können, müssen Sie sich zunächst anmelden.
Einloggen | Neu registrieren |
|
|
sevISDN 1.0
Überwachung aller eingehender Anrufe!
Die DLL erkennt alle über die CAPI-Schnittstelle eingehenden Anrufe und teilt Ihnen sogar mit, aus welchem Ortsbereich der Anruf stammt. Weitere Highlights: Online-Rufident, Erkennung der Anrufbehandlung u.v.m. Weitere InfosTipp des Monats sevGraph (VB/VBA)
Grafische Auswertungen
Präsentieren Sie Ihre Daten mit wenig Aufwand in grafischer Form. sevGraph unterstützt hierbei Balken-, Linien- und Stapel-Diagramme (Stacked Bars), sowie 2D- und 3D-Tortendiagramme und arbeitet vollständig datenbankunabhängig! Weitere Infos
|