vb@rchiv
VB Classic
VB.NET
ADO.NET
VBA
C#
Brandneu! sevEingabe v3.0 - Das Eingabecontrol der Superlative!  
 vb@rchiv Quick-Search: Suche startenErweiterte Suche starten   Impressum  | Datenschutz  | vb@rchiv CD Vol.6  | Shop Copyright ©2000-2024
 
zurück

 Sie sind aktuell nicht angemeldet.Funktionen: Einloggen  |  Neu registrieren  |  Suchen

VB.NET - Ein- und Umsteiger
Prozess 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

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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...
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: Manfred X
Datum: 24.04.14 13:55

Hallo!

Hier eine kleine Übersicht mit Beispielen:
http://www.dotnetperls.com/process

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: Marcus W
Datum: 24.04.14 14:12

Hallo Manfred,

meinst Du wirklich, dass es sinnvoll ist, einem VB-User einen Link auf eine C#-Seite zu geben?

Gruß
Marcus

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.)
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: Manfred X
Datum: 24.04.14 14:43

Niemand streitet ....

Aber: Ich verstehe das Problem nicht:
http://msdn.microsoft.com/de-de/library/system.diagnostics.process.startinfo%28v=vs.100%29.aspx

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: catweazle2k3
Datum: 24.04.14 15:55

Super !! Danke, das funktioniert !!
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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?
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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....
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: Manfred X
Datum: 25.04.14 14:06

Funktioniert die Beispielanwendung korrekt, deren Code am Ende dieses Tipps angegeben ist
(Windows-Rechner fernsteuern)?
http://msdn.microsoft.com/en-us/library/ms171548%28v=vs.110%29.aspx

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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...

Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

Re: Prozess starten und in eigene Anwendung einbinden 
Autor: catweazle2k3
Datum: 25.04.14 14:57

...genau dasselbe
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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 ....
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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?


Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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....
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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?





Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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....
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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.
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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....
Themenbaum einblendenGesamtübersicht  |  Zum Thema  |  Suchen

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

Funktionen:  Zum Thema  |  GesamtübersichtSuchen 

nach obenzurück
 
   

Copyright ©2000-2024 vb@rchiv Dieter Otter
Alle Rechte vorbehalten.
Microsoft, Windows und Visual Basic sind entweder eingetragene Marken oder Marken der Microsoft Corporation in den USA und/oder anderen Ländern. Weitere auf dieser Homepage aufgeführten Produkt- und Firmennamen können geschützte Marken ihrer jeweiligen Inhaber sein.

Diese Seiten wurden optimiert für eine Bildschirmauflösung von mind. 1280x1024 Pixel