Ansteuern eines externen Programms

  • VB.NET
  • .NET (FX) 4.5–4.8

Es gibt 25 Antworten in diesem Thema. Der letzte Beitrag () ist von Hourmin.

    Ansteuern eines externen Programms

    Guten Morgen,

    Schreibe zurzeit für ein CAD Programm
    ein Plugin. Ich habe über Umwege auf einen Befehl zugegriffen, der über die API nicht ansteuerbar ist.

    Nun habe ich bei dem Befehl die Möglichkeit eine Datei auszuwählen. Danach kommt ein Fenster wo ein Dropdown Feld betätigt werden muss und Zeichnungen ausgewählt werden müssen.

    Ist dies über reine Windows Programmierung möglich? Das Windows erkennt wo was eingetragen werden kann?

    Danke im Voraus

    *Topic verschoben*

    Dieser Beitrag wurde bereits 1 mal editiert, zuletzt von „Marcus Gräfe“ ()

    @Hourmin Ich hab nicht ganz genau verstanden, was Du willst, aber schau mal hier rein: Andere Programme fernsteuern
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Ich habe bei einem externen Programm einen Befehl angesteuert, der mir ermöglicht eineDatei auszuwählen. Danach listet er mir
    Zeichnungen von dieser Datei auf. Diese
    Muss ich über ein Dropdown Menü filtern und anschließend per CheckBox auswählen.

    Allerdings läuft das halt alles extern von dem Programm aus und ich frage mich wie ichZugriff bekomme, da die API mir dort nichtweiterhilft (glaube ich)
    Ich verstehe auch nicht was Du meinst. Nicht im Ansatz.

    Versuche es praktisch zu erklären und sag um welche Software es sich handelt und was genau Du machen möchtest.
    Da es sich scheinbar um eine Grafiksoftware handelt, mache Screenshots und visualisiere Deine Frage.
    Dann können wir Dir sicher mit Tips weiterhelfen - aber zuerst müssen wir verstehen was Du wissen möchtest ;)
    Liebe Grüße
    Roland Berghöfer

    Meine aktuellen und kostenlos verwendbaren Tools (mit VB.NET erstellt): freeremarkabletools.com | priconman.com | SimpleCalendar | AudibleTouch | BOComponent.com | bonit.at
    @Hourmin Du kannst dem externen Programm gezielt Texte in String-Controls reinschreiben und Du kannst Buttons /CheckBoxes klicken.
    Was genau bietet denn deren API?
    Gibt es da enen Link zu?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Es geht um Autodesk Revit.

    1. Folgenden Button Click konnte ich per Command Simulieren.
    picload.org/view/dlwlwwpa/schritt1.png.html

    2. Dann erscheint folgendes Fenster:
    picload.org/view/dlwlwwpl/schritt2.png.html

    3. Nachdem man eine Datei ausgewählt hat ist folgendes auszuwählen.
    picload.org/view/dlwlwwpi/schritt3.png.html

    Und an Schritt 2 und 3 breche ich mir zurzeit einen ab.
    Folgende API gibt es im Internet: revitapidocs.com/
    @Hourmin Ich habe das Gefühl, dass Dein Programm (noch) nicht bereit ist, dieses Autodesk anzusteuern.
    Über welche Programmiererfahrung verfügst Du?
    Was genau macht Dein Programm?
    Was genau soll Dein Programm machen?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Bin Anfänger. Von der Logik klappt alles super nur
    wenn ich neue Dinge mache, wie externe Programme ansteuern, dann
    hab ich da tatsächlich ein Problem mit.
    Grundsätzlich ist es ja echt nicht schwer was jetzt noch fehlt.

    Es soll eine Excel-Tabelle auslesen und die dort hingeschriebenen
    Zeichnungen importieren. Mir geht's jetzt aber nur darum, dass es irgendwas
    importiert.

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

    Hourmin schrieb:

    Zeichnungen importieren
    OHa.
    Kannst Du das mit reinen AutoDesk-Mitteln bereits tun?
    Kannst Du das Format lesen?
    Was soll mit den Daten passieren?
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    Einen Guten Abend,

    @RodFromGermany
    Habe deine Anleitung befolgt und es funktioniert anhand deiner Testapplikation alles wunderbar.
    Egal ob es um das Klicken eines Buttons oder das Ändern eines Textfelds geht.

    Habe ergänzt, dass das Programm das WindowHandle anhand des Namens findet.
    Trotzdem funktioniert es mit dem Notepad zum Test leider nicht.
    Vielleicht hat einer eine Idee woran es liegen könne - danke im vorraus!!

    Entscheidend wird es erst ab Zeile 61. Habe den Code
    nochmal ein Wenig abgeändert.
    Sobald ich das Handle des "Öffnen" Fensters vom Editor bekommen möchte,
    kann ich leider nicht automatisch eine Datei auswählen lassen.
    Das normale MainWindow erkennt er und ich kann dort reinschreiben, was ich möchte.

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Text
    3. Imports System.Collections.Generic
    4. Imports System.Runtime.InteropServices
    5. Public Class Form1
    6. Dim _Process As Process
    7. Dim prAll() As Process
    8. Dim _MainWnd As IntPtr
    9. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles StarteProgramm.Click
    10. _Process = New Process()
    11. _Process.StartInfo.FileName = "C:\Users\Matthias\Desktop\FernsteuerungTestGui.exe"
    12. _Process.Start()
    13. _Process.WaitForInputIdle()
    14. '_MainWnd = NativeMethods.FindWindowHandle("FernsteuerungTestGui")
    15. If _MainWnd <> 0 Then
    16. ' Fenster aktivieren und in den Vordergrund holen
    17. NativeMethods.SetForegroundWindow(_MainWnd)
    18. End If
    19. End Sub
    20. Public Sub Button1_Click(sender As Object, e As EventArgs) Handles AenderealleBeschriftungen.Click
    21. Dim i As Integer
    22. Dim childs As List(Of IntPtr) = NativeMethods.GetChildWindows(_MainWnd)
    23. Do While (i < childs.Count)
    24. NativeMethods.SendMessage(childs(i), NativeMethods.WM_SETTEXT, IntPtr.Zero, i.ToString())
    25. i += 1
    26. Loop
    27. End Sub
    28. Private Sub AendereButtonundLabel_Click(sender As Object, e As EventArgs) Handles AendereButtonundLabel.Click
    29. Dim btn As IntPtr = NativeMethods.FindWindowEx(_MainWnd, IntPtr.Zero, "Button", "Button1")
    30. NativeMethods.SendMessage(btn, NativeMethods.WM_SETTEXT, IntPtr.Zero, "Button 2")
    31. Dim nechst As IntPtr = IntPtr.Zero
    32. Dim i As Integer = 0
    33. While (True)
    34. Dim btn2 As IntPtr = NativeMethods.FindWindowEx(_MainWnd, nechst, "Button", Nothing)
    35. If btn2 = IntPtr.Zero Then
    36. Exit While
    37. End If
    38. NativeMethods.SendMessage(btn2, NativeMethods.WM_SETTEXT, IntPtr.Zero, "bla")
    39. i += 1
    40. nechst = btn2
    41. End While
    42. End Sub
    43. Private Sub KlickeButton_Click(sender As Object, e As EventArgs) Handles KlickeButton.Click
    44. Dim hwnd As IntPtr = NativeMethods.FindWindowEx(_MainWnd, IntPtr.Zero, "Button", "Button1")
    45. ClickButton(hwnd)
    46. End Sub
    47. Private Sub AendereCheckBox_Click(sender As Object, e As EventArgs) Handles AendereCheckBox.Click
    48. Dim check As IntPtr = NativeMethods.FindWindowEx(_MainWnd, IntPtr.Zero, "Button", "Check1")
    49. NativeMethods.SendMessageInt(check, NativeMethods.BM_SETCHECK, 0, 0)
    50. ClickButton(check)
    51. End Sub
    52. Public Sub ClickButton(ByVal hwnd As IntPtr)
    53. NativeMethods.PostMessage(hwnd, NativeMethods.BM_Click, IntPtr.Zero, Nothing)
    54. End Sub
    55. Private Sub FindWindow_Click(sender As Object, e As EventArgs) Handles FindWindow.Click
    56. Dim hwnd As IntPtr = NativeMethods.FindWindowEx(_MainWnd, IntPtr.Zero, "Edit", "")
    57. NativeMethods.SendMessage(hwnd, NativeMethods.WM_SETTEXT, IntPtr.Zero, "Test")
    58. End Sub
    59. '////////////////////////////////////////Test mit Notepad
    60. Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Revitstart.Click
    61. _Process = New Process()
    62. _Process.StartInfo.FileName = "Notepad.exe"
    63. _Process.Start()
    64. _Process.WaitForInputIdle()
    65. _MainWnd = _Process.MainWindowHandle
    66. End Sub
    67. Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles Button2.Click
    68. Dim _chldWnd As IntPtr = NativeMethods.FindWindowHandle(_MainWnd, "Öffnen")
    69. Dim btn As IntPtr = NativeMethods.FindWindowEx(_MainWnd, IntPtr.Zero, "Edit", "")
    70. NativeMethods.SendMessage(btn, NativeMethods.WM_SETTEXT, IntPtr.Zero, "Test")
    71. End Sub
    72. End Class
    73. Public Class NativeMethods
    74. Public Const BM_SETCHECK As Int32 = &HF1
    75. Public Const BM_Click As Int32 = &HF5
    76. Public Const WM_SETTEXT As Int32 = &HC
    77. Public Const WM_GETTEXT As Int32 = &HD
    78. Public Const GW_HWNDFIRST = 0
    79. Public Const GW_HWNDNEXT = 2
    80. Friend Delegate Function EnumWindowProc(ByVal hWnd As IntPtr, ByVal Parameter As IntPtr) As Boolean
    81. <DllImport("user32.dll", SetLastError:=True)>
    82. Friend Shared Function EnumChildWindows(ByVal window As IntPtr, ByVal callback As EnumWindowProc, ByVal listHandle As IntPtr) _
    83. As <MarshalAs(UnmanagedType.Bool)> Boolean
    84. End Function
    85. Public Shared Function GetChildWindows(ByVal parent As IntPtr) As List(Of IntPtr)
    86. Dim result As List(Of IntPtr) = New List(Of IntPtr)
    87. Dim listHandle As GCHandle = GCHandle.Alloc(result)
    88. Try
    89. Dim childProc As EnumWindowProc = New EnumWindowProc(AddressOf EnumWindow)
    90. EnumChildWindows(parent, childProc, GCHandle.ToIntPtr(listHandle))
    91. Finally
    92. If listHandle.IsAllocated Then
    93. listHandle.Free()
    94. End If
    95. End Try
    96. Return result
    97. End Function
    98. Private Shared Function EnumWindow(ByVal handle As IntPtr, pointer As IntPtr) As Boolean
    99. Dim gch As GCHandle = GCHandle.FromIntPtr(pointer)
    100. Dim list As List(Of IntPtr) = CType(gch.Target, List(Of IntPtr))
    101. If list Is Nothing Then
    102. Throw New InvalidCastException("GCHandle Target could not be cast as List IntPtr")
    103. End If
    104. list.Add(handle)
    105. Return True
    106. End Function
    107. Public Shared Function FindWindowHandle(ByVal _MainWnd As IntPtr, ByVal title As String) As IntPtr
    108. Dim hWndNext As IntPtr = NativeMethods.GetWindow(NativeMethods.FindWindow(IntPtr.Zero, IntPtr.Zero), CType(NativeMethods.GW_HWNDFIRST, IntPtr))
    109. Dim space As StringBuilder = New StringBuilder(512)
    110. While (hWndNext <> IntPtr.Zero)
    111. If ((NativeMethods.GetWindowText(hWndNext, space, space.Capacity) > 0) _
    112. AndAlso (space.ToString.StartsWith(title) _
    113. AndAlso (NativeMethods.GetParent(hWndNext) = _MainWnd))) Then
    114. Return hWndNext
    115. End If
    116. hWndNext = NativeMethods.GetWindow(hWndNext, CType(NativeMethods.GW_HWNDNEXT, IntPtr))
    117. End While
    118. Return IntPtr.Zero
    119. End Function
    120. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    121. Public Shared Function SendMessage(ByVal hwnd As IntPtr, ByVal wsg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
    122. End Function
    123. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    124. Public Shared Function PostMessage(ByVal hwnd As IntPtr, ByVal wsg As Integer, ByVal wParam As IntPtr, ByVal lParam As String) As IntPtr
    125. End Function
    126. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    127. Public Shared Function FindWindowEx(ByVal parentHandle As IntPtr, ByVal childAfter As IntPtr, ByVal className As String, ByVal windowTitle As String) As IntPtr
    128. End Function
    129. <DllImport("user32.dll", EntryPoint:="SendMessageA", CharSet:=CharSet.Ansi, SetLastError:=True, ExactSpelling:=True)>
    130. Public Shared Function SendMessageInt(ByVal hwnd As IntPtr, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As IntPtr
    131. End Function
    132. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    133. Public Shared Function GetClassName(ByVal hwnd As IntPtr, ByVal lpClassName As String, ByVal nMaxCount As IntPtr) As IntPtr
    134. End Function
    135. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    136. Public Shared Function GetWindow(ByVal hwnd As IntPtr, ByVal nID As IntPtr) As IntPtr
    137. End Function
    138. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    139. Public Shared Function GetWindowTextLength(ByVal hwnd As IntPtr) As IntPtr
    140. End Function
    141. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    142. Public Shared Function SetForegroundWindow(ByVal hwnd As IntPtr) As IntPtr
    143. End Function
    144. Public Declare Function GetWindowText Lib "user32.dll" (ByVal hWnd As IntPtr, ByVal returnedString As System.Text.StringBuilder, ByVal nMaxCount As Integer) As Integer
    145. <DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)>
    146. Public Shared Function FindWindow(
    147. ByVal lpClassName As String,
    148. ByVal lpWindowName As String) As IntPtr
    149. End Function
    150. <DllImport("user32.dll", CharSet:=CharSet.Unicode)>
    151. Public Shared Function GetParent(ByVal hwnd As IntPtr) As IntPtr
    152. End Function
    153. End Class

    Dieser Beitrag wurde bereits 5 mal editiert, zuletzt von „Hourmin“ ()

    Hourmin schrieb:

    VB.NET-Quellcode

    1. _Process.WaitForInputIdle()
    Nimm da mal die Überladung mit der Wartezeit und lass ihn explizit 500 bis 1000 Millisekunden warten.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    VB.NET-Quellcode

    1. '////////////////////////////////////////Test mit Notepad
    2. Private Sub Button1_Click_1(sender As Object, e As EventArgs) Handles Revitstart.Click
    3. _Process = New Process()
    4. _Process.StartInfo.FileName = "Notepad.exe"
    5. _Process.Start()
    6. _Process.WaitForInputIdle(1000)
    7. _MainWnd = _Process.MainWindowHandle
    8. End Sub
    9. Private Sub Button2_Click_1(sender As Object, e As EventArgs) Handles Button2.Click
    10. _Process.WaitForInputIdle(1000)
    11. Dim _chldWnd As IntPtr = NativeMethods.FindWindowHandle(_MainWnd, "Öffnen")
    12. Dim btn As IntPtr = NativeMethods.FindWindowEx(_chldWnd, IntPtr.Zero, "Edit", "")
    13. NativeMethods.SendMessage(btn, NativeMethods.WM_SETTEXT, IntPtr.Zero, "Test")
    14. End Sub


    Tut sich leider nichts.

    Hourmin schrieb:

    kann ich leider nicht automatisch eine Datei auswählen lassen.
    Die Datei gibst Du dem Notepad als Parameter mit:

    VB.NET-Quellcode

    1. _Process.StartInfo.Arguments = "c:\Temp\Test.txt"
    Die Sub-Fenster, die Du suchst, gibt es zu diesem Zeitpunkt nicht, die werden erst mit dem Öffnen des Menüs aktiviert.
    Solch habe ich nicht untersucht.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!
    @Hourmin Das kommt doch in meinem Tut vor, da musst Du über alle diese Fenster iterieren und es dann anhand seiner "laufenden Nummer" erkennen.
    Dabei werden bei mir die Texte durch Nummern ersetzt.
    Ein Fenster, das nicht da ist (ein Item in einem PullDown-Menü) kann so nicht gefunden werden.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!

    Hourmin schrieb:

    manuell von mir geöffneten „öffnen“ Fenster
    Wie machst Du denn das?
    Wenn ein anderes Programm den Fokus bekommt, geht das Menü zu und das Fenster ist wieder weg.
    Falls Du diesen Code kopierst, achte auf die C&P-Bremse.
    Jede einzelne Zeile Deines Programms, die Du nicht explizit getestet hast, ist falsch :!:
    Ein guter .NET-Snippetkonverter (der ist verfügbar).
    Programmierfragen über PN / Konversation werden ignoriert!