Prozess in die eigene Anwendung einbetten und wieder freigeben.

    • VB.NET

    Es gibt 19 Antworten in diesem Thema. Der letzte Beitrag () ist von sodah.

      Prozess in die eigene Anwendung einbetten und wieder freigeben.

      Hallo,

      Wie kann man einen Prozess z.b. ICQ in die eigene Anwendung einbetten ?
      Geht das überhaupt ? Und wenn ja wie ?

      Vorneweg - es geht.

      Für das Beispiel braucht ihr ein Panel, zwei Button und eine Listbox.

      In der Listbox führe ich alle in frage kommenden Prozesse auf.
      Durch Button1 wird die Anwendung in die eigene Integriert und verschwindet aus den Prozessen.
      Durch Button2 wird die Anwendung wieder in die Freiheit entlassen.

      Aber nun genug - hier der Code

      VB.NET-Quellcode

      1. 'Imports System.Runtime.InteropServices
      2. Public Class Form1
      3. 'benötigte api's
      4. Private Declare Function ShowWindow Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal flag As Integer) As IntPtr
      5. Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
      6. 'showwindow konstanten
      7. Private Const SW_NORMAL As Integer = 1
      8. Private Const SW_MAXIMIZE As Integer = 3
      9. 'handle des eingebetteten fensters merken
      10. Private h As IntPtr
      11. 'timer zum aktualisieren der prozess liste
      12. Private WithEvents t As New Timer
      13. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      14. 'wenn ein eintrag aus der listbox ausgewählt wurde,
      15. 'kann dieser prozess auch aufgerufen und eingebettet werden
      16. If Me.ListBox1.SelectedItem IsNot Nothing Then
      17. SetApplicationAsChild(Me.ListBox1.SelectedItem, Me.Panel1)
      18. End If
      19. End Sub
      20. ''' <summary>Einbetten der Anwendung in die eigene Form.</summary>
      21. ''' <param name="CallingApplication">Die einzubettende Anwendung.</param>
      22. ''' <param name="p">Panel, in das die Anwendung eingebettet werden soll.</param>
      23. Private Sub SetApplicationAsChild(ByVal CallingApplication As String, ByVal p As System.Windows.Forms.Panel)
      24. Dim hProcess As System.Diagnostics.Process = Process.GetProcessesByName(CallingApplication)(0)
      25. If hProcess.MainWindowHandle <> 0 Then
      26. ' Parent Fenster setzen.
      27. SetParent(hProcess.MainWindowHandle, p.Handle)
      28. 'hProcess.WaitForInputIdle()
      29. 'Fenster anzeigen.
      30. ShowWindow(hProcess.MainWindowHandle, SW_MAXIMIZE)
      31. 'handle merken, um beim freigeben weniger stress zu haben
      32. h = hProcess.MainWindowHandle
      33. Me.Button1.Enabled = False
      34. Me.Button2.Enabled = True
      35. Else
      36. MessageBox.Show("Kein gültiges Fensterhandle - Anwendung kann nicht eingebettet werden.")
      37. 'Me.Button1.Enabled = True
      38. 'Me.Button2.Enabled = False
      39. End If
      40. End Sub
      41. Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click
      42. 'eingebettete anwendung wieder freigeben
      43. ReleaseApplicationAsChild()
      44. End Sub
      45. Private Sub ReleaseApplicationAsChild()
      46. 'parent der anwendung wieder löschen
      47. SetParent(h, Nothing)
      48. 'fenster der anwendung anzeigen
      49. ShowWindow(h, SW_NORMAL)
      50. 'button sperren
      51. Me.Button2.Enabled = False
      52. Me.Button1.Enabled = True
      53. End Sub
      54. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
      55. 'wenn eine anwendung gefangen wurde, beim beenden freilassen
      56. If Button2.Enabled = True Then
      57. ReleaseApplicationAsChild()
      58. End If
      59. End Sub
      60. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      61. 'button sperren
      62. Me.Button2.Enabled = False
      63. Me.Button1.Enabled = True
      64. 'button texte setzen
      65. Me.Button1.Text = "Anwendung einbetten"
      66. Me.Button2.Text = "Anwendung freigeben"
      67. 'timer starten
      68. t.Interval = 1000
      69. t.Start()
      70. End Sub
      71. Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
      72. 'prozessliste aktualisieren - um alle geöffneten fenster erfassen zu können
      73. t.Stop()
      74. Dim index As Integer = Me.ListBox1.SelectedIndex
      75. 'alle prozesse die einen fenstertitel haben in die listbox eintragen
      76. Me.ListBox1.Items.Clear()
      77. For Each p As Process In Process.GetProcesses
      78. If p.MainWindowTitle <> "" Then
      79. Me.ListBox1.Items.Add(p.ProcessName)
      80. End If
      81. Next
      82. Me.ListBox1.SelectedIndex = index
      83. t.Start()
      84. End Sub
      85. End Class

      Interessant wäre es, ob das ganze auch ohne Api - rein durch das Framework - umsetzbar ist.

      Kommentare erwünscht.

      Gruss

      mikeb69
      Hallo mike,

      dein Tipp funktioniert soweit ganz gut,

      nur wer es nicht klüger, eine fremde Anwendung einzubetten mit Hilfe des Fensternamen´s anstat des Prozess namens??

      Weil wenn man die fremd Anwendung einbettet, dann verschwindet ja das ganze aus der Taskleiste und der 2 Client bleibt ja aktiv in der Taskleiste.

      Weil ich habe das mit ein Spiel ausprobiert was man 2 mal starten kann,

      beim erstenmal funktioniert das ganze aber beim 2 Client von dem Spiel nicht mehr,

      da sagt er mir das:

      Kein gültiges Fensterhandle - Anwendung kann nicht eingebettet werden.

      Wenn das ganze auch geht, dann würde ich bzw. auch andere Leute sich darüber freuen.



      Edit:

      Folgender Code sucht nach dem Fensternamen und wenn er verfügbar ist meldet er das.



      VB.NET-Quellcode

      1. Public Class Form1
      2. Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As Integer, ByVal lpWindowName As String) As Integer
      3. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      4. Dim window As String
      5. Dim hwnd As Integer
      6. window = "Unbenannt - Editor"
      7. hwnd = FindWindow(0, window)
      8. If hwnd <> 0 ThenMsgBox("Fenster gefunden")
      9. ElseMsgBox("Fenster nicht gefunden")
      10. End IfEnd Sub
      11. End Class


      Das könnte man doch nehmen um dann das fremdProgramm in die eigene Anwendung zu integrieren mit dem Fensternamen.

      Nur habe ich noch nicht so viele Erkenntnisse um das zu realisieren.

      Für eine ToolTip Erweiterung Wehren wir sehr dankbar.

      Dieser Beitrag wurde bereits 3 mal editiert, zuletzt von „dreamboy5883“ ()

      hallo dreamboy,

      ich hab mir für dein problem zeit genommen, und das ergebnis hier - für alle - gepostet.
      mir scheint jedoch, dass du eine fertige anwendung suchst.

      der sinn eines forums ist es nicht fertige programme zu liefern.
      der sinn ist es eher ideen und denkansätze für ein problem zu liefern.

      auf basis meines codes kannst du sicher, recht einfach, deine eigenen wünsche umsetzen.
      alles andere als ein beispiel wie dieses wirst du nicht umsonst kriegen - zumindest nicht von mir

      was sollte eigentlich deine abschlussbemerkung ?
      Für eine ToolTip Erweiterung Wehren wir sehr dankbar.


      gruss

      mikeb69
      Das war mir schon klar, das das im falschen Hals genommen wird.

      Meine AbschlussBemerkung sollte keine beleidigung sein oder der gleichen.

      Ich wollte damit nur ausdrücken, das sich andere darüber auch freuen würden.

      Da ich denke das nicht nur ich das Problem habe.
      hallo dreamboy,

      ich bekomme gar nichts in den falschen hals.
      nur - wie soll ich auf deinen beitrag reagieren.

      fakt ist:
      1. du kannst das nicht selbst
      2. du fragst mich um hilfe
      3. ich verfasse einen beitrag indem ich code poste
      4. du bist unzufrieden

      also - was willst du ?

      ein tipp stellt kein fertiges programm dar !
      das der code nicht in allen fällen funktioniert - mag schon sein.

      vorschlag:
      beglücke die welt mit einem besseren fehlerfreieren code

      gruss

      mikeb69
      Ich habe nie gesagt das dein Code nicht funktioniert.

      Ich habe lediglich darauf hingewiesen das man eine fremdAnwendung die man 2 mal starten kann,

      nicht ein 2 mal einfangen kann mehr habe ich nicht getan.

      Und halt ein Tipp gegeben wie das gehen könnte.

      Zu dein 2 Punkt:

      Ich habe dich lediglich gefragt wie ich das raus nehmen kann das er die exe nicht startet,

      da ich das schon mehrmals versucht hatte.

      Du hast dann mit dein wissen denn Code von dieser Seite weiter ausgebaut:

      vbarchiv.net/tipps/tipp_1794.html

      Mein Vorschlag war in mein Post eigentlich nur, das man es damit doch besser realisieren könnte.

      Ich habe damit auch schon angefangen, aber leider bisher ohne Erfolg.

      Also, ich finde so eine Art von Diskusion hier sinnlos,

      da es ein unterForum von Sourcecode Austausch ist.
      Es ist zwar nicht das beste aber es Funktioniert:

      Hier ist mein Code:

      VB.NET-Quellcode

      1. Public Class Form1
      2. Private Declare Function SetParent Lib "user32" (ByVal hWndChild As Integer, ByVal hWndNewParent As Integer) As Integer
      3. Private Declare Function FindWindow Lib "user32.dll" Alias "FindWindowA" (ByVal lpClassName As Integer, ByVal lpWindowName As String) As Integer
      4. Private Declare Function ShowWindow Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal flag As Integer) As IntPtr
      5. Private Const SW_MAXIMIZE As Integer = 3
      6. Private Const SW_NORMAL As Integer = 1
      7. Dim window As String
      8. Dim hwnd As Integer
      9. Private lhwnd As IntPtr
      10. Private Sub ReleaseApplicationAsChild()
      11. SetParent(lhwnd, Nothing)
      12. ShowWindow(lhwnd, SW_NORMAL)
      13. End Sub
      14. Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
      15. ReleaseApplicationAsChild()
      16. End Sub
      17. Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
      18. SetApplicationAsChild(Me)
      19. End Sub
      20. Private Sub SetApplicationAsChild(ByVal p As System.Windows.Forms.Form)
      21. window = "Unbenannt - Editor"
      22. lhwnd = FindWindow(0, window)
      23. If lhwnd <> 0 Then
      24. SetParent(lhwnd, p.Handle)
      25. 'MsgBox("Fenster Gefunden")
      26. ShowWindow(lhwnd, SW_MAXIMIZE)
      27. Else
      28. MsgBox("Kein Gültieges Fenster Gefunden")
      29. End If
      30. End Sub
      31. End Class


      Abgeleitet ist der code von hier:

      activevb.de/tipps/vb6tipps/tipp0489.html



      Edit:

      Aufgrund der Unlesbarkeit.

      @mike,

      vb 2008 meckert nicht rum bzw. gibt mir keine Fehler aus.

      Daher kann ich von meiner seite davon ausgehen das alles in ordnung ist.

      Ich habe noch nicht so viel plan davon, daher sage ich dies einfach mal.

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „dreamboy5883“ ()

      VB.NET-Quellcode

      1. ''' <summary>Einbetten der Anwendung in die eigene Form.</summary>
      2. ''' <param name="CallingApplication">Die einzubettende Anwendung.</param>
      3. ''' <param name="p">Panel, in das die Anwendung eingebettet werden soll.</param>


      Da muss ich das Progamm einbetten??

      Wie mach ich das?

      VB.NET-Quellcode

      1. ''' <summary>Einbetten der Anwendung in die eigene Form. ??? ?( </summary>
      2. ''' <param name="CallingApplication">test.exe</param>
      3. ''' <param name="p">Panel, in das die Anwendung eingebettet werden soll. HÄÄ?? ?( </param>
      Ich hab das jetzt mal versucht zu kompilieren(@mike) aber an folgernder stelle:

      Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
      'wenn ein eintrag aus der listbox ausgewählt wurde,
      'kann dieser prozess auch aufgerufen und eingebettet werden
      If Me.ListBox1.SelectedItem IsNot Nothing Then
      SetApplicationAsChild(Me.ListBox1.SelectedItem, Me.Panel1)

      End If
      End Sub

      sagt es mir, dass "panel1 kein member von windowsapplication1.form1" ist..
      @mikeb:

      Hab nen BUG gefunden:

      Wenn man den letzten eintrag wählt, und man auf einbetten geht, verschwindet ja der eintrag in der liste. dann gibt es keinen eintrag an dieser stelle und es kommt zu ner exception

      EDIT: Hab ihn behoben:

      VB.NET-Quellcode

      1. Private Sub t_Tick(ByVal sender As Object, ByVal e As System.EventArgs) Handles t.Tick
      2. 'prozessliste aktualisieren - um alle geöffneten fenster erfassen zu können
      3. t.Stop()
      4. Dim index As Integer = Me.ListBox1.SelectedIndex
      5. 'alle prozesse die einen fenstertitel haben in die listbox eintragen
      6. Me.ListBox1.Items.Clear()
      7. For Each p As Process In Process.GetProcesses
      8. If p.MainWindowTitle <> "" Then
      9. Me.ListBox1.Items.Add(p.ProcessName)
      10. End If
      11. Next
      12. Me.ListBox1.Items.Add("")
      13. Me.ListBox1.SelectedIndex = index
      14. t.Start()
      15. End Sub


      grüße serials
      | Keine Fragen per PN oder Skype.
      Vielen Dank!!!!
      Es funktioniert theoretisch. Leider wird die App unsichtbar. Bzw. wird sie scheinbar als Hintergrundprozess weitergeführt.
      Ein Tipp warum das passiert?

      Quellcode

      1. Private Declare Function SetParent Lib "user32.dll" (ByVal hWndChild As IntPtr, ByVal hWndNewParent As IntPtr) As IntPtr
      2. ....
      3. MyProcess = Process.Start(pinfo)
      4. MyProcess.WaitForInputIdle()
      5. AppWin = MyProcess.MainWindowHandle
      6. SetParent(AppWin, myPanel.Handle)
      7. ....
      8. <WindowsFormsHost >
      9. <WindowsForms:Panel x:Name="myPanel" />
      10. </WindowsFormsHost>

      Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „sodah“ ()

      Das hast du auch gemacht?

      C#-Quellcode

      1. // Show window before set style and resize
      2. NativeMethods.ShowWindow(AppWin, NativeMethods.WindowShowStyle.Maximize);


      und der resize

      C#-Quellcode

      1. NativeMethods.SetWindowPos(PuTTYProcess.MainWindowHandle, IntPtr.Zero, 0, 0, puTTYHost.ClientSize.Width, puTTYHost.ClientSize.Height, NativeMethods.SWP_NOZORDER | NativeMethods.SWP_NOACTIVATE);


      Hier die NativeMethods


      Eventuell solltest du einen eigenen Thread aufmachen.?

      Edit: Beim Windows 10 Taskmanager wird der Prozess als Subprozess deiner Anwendung angezeigt.
      NETworkManager - A powerful tool for managing networks and troubleshoot network problems!