Externes Programm korrekt schließen

  • VB.NET

Es gibt 27 Antworten in diesem Thema. Der letzte Beitrag () ist von dumpfi.

    Externes Programm korrekt schließen

    Hallo,

    also ich bin eindeutig ein Anfänger was Programierung betrifft, und ich habe mir ein kleines Programm geschrieben welches am Abend meinen Rechner mit einem Klick beenden soll.

    Soweit funktioniert eigentlich alles, das Problem ist nur folgendes, ich habe eine Applikation welche auf einen externen Server zugreift, und diese muss Ordnungsgemäß beendet werden da es ansonsten beim Neustart zu Problemen kommen kann.

    Ich habe schon folgende Dinge versucht.

    Quellcode

    1. process.Closemainwindow
    2. process.Kill


    Natürlich noch entsprechend mit Prozess Aufruf aufgeführt. Das ganze funktioniert auch prima. Jedoch ist es bei besagtem Programm so das wenn man das Hauptfenster schließt das Programm im Hintergrund weiterläuft. Also es ist noch ala Sounds, oder Antivirus in der Taskleiste geöffnet. Mit Prozess Kill fährt das Programm nicht korrekt herunter also auch nicht zu brauchen für mich.

    Daher wie gehe ich am besten vor wenn ich will das in diesem Programm die Schaltfläche Beenden zum schließen des Programms verwendet wird?

    Ich hoffe das ist jetzt nicht zu verwirrend geschrieben leider weis ich nicht wie ich es besser schreiben könnte ?(

    Danke schon mal für eure Tipps.

    Ach ja ich habe eine Windows Forms anwendung mit VisualBasic erstellt
    Sowas wird nie stabil laufen, es sei denn, dass annere Proggi hat extra was für vorgesehen, dasses so ferngesteuert werden kann.

    Also instabil wäre, dass du die Anwendung in den Vordergrund holst - vlt. gibts dafür eine AppActivate - Api, und dann kann man Tastendrücke senden, die hoffentlich als erstes das Menü öffnen, und dann Datei-schließen anwählen.
    oft muss nach einer Zeit noch {Enter} hinterher geschickt werden, nämlich, wenn die Anwendung noch Änderungen hat, und fragt, ob die gespeichert wern sollen.

    Aber ich empfehle dir: Lasses - du kriegst solche Krücken nicht stabil.
    Okay, habe ich also schon richtig vermutet das es schwirig wird.

    Also ich habe gerade gesehen das man in dem Programm das Menü wie bei Office bedienen kann. Also alt Taste und dann über die Buchstaben welche neben den Schaltflächen erscheinen die Funktionen aufrufen.

    Daher meine Idee.

    Sobald man die Abschaltfunktion startet, Maus und Tastatur sperren so das ein Fremdeinwirken durch den Benutzer verhindert wird. SendKey Funktion verwenden mit Pausen von 100 millisekunden, sollte reichen damit die Tastenbefehle ordnungsgemäß ausgeführt werden.

    Sobald das Programm ja dann geschlossen ist könnte man ja die Tastatur wieder freigeben. Müsste ja dann soweit eigentlich stabil laufen hätte ich mal gesagt.

    Einen Versuch wäre es zumindest wert oder spricht hier schon vorab etwas gegen diese Lösung?
    wenn im Proggi iein modaler Dialog geöffnet ist, dann erreichst du das Menü nicht mehr.
    Auch weiß ich nicht, wie man Tastatur und Maus systemweit sperrt.
    Wie gesagt: Stabil kriegst du das nicht.

    Und als Moderator füge ich hinzu: Falls jmd weiß, wie Tastatur und Maus zu sperren wären, so soll er es hier nicht posten, denn mit diesem KnowHow kann jedes Script-Kiddies dann auch üble Malware coden

    Danke, sorry das mit der Tastatur sollte eig. keine Frage sein, hier weis ich selbst wie ich das umsetzten kann.

    Das zu schließende Programm ist zum Glück sehr einfach gestrickt, sprich es gibt beim Beenden usw. keine Sicherheitsabfragen. Und das mit den offenen Dialogen bekomme ich auch hin. Denke ich.

    Ich hab soweit meine Lösung schon im Kopf und würde versuchen das zu Programmieren. Mir ist schon klar das es nicht das gelbe vom Ei ist, aber naja hilft ja nicht. Unterm strich ist das ganze Projekt für mich dazu gedacht meine Fähigkeiten zu verbessern und so ganz nebenbei hat es auch noch einen kleinen Nutzen für mich.

    Jedenfalls fürs erste schon einmal herzlichen Dank für deine Hilfe, vielleicht muss ich ja noch einmal was fragen ;)

    dumpfi schrieb:

    ich habe eine Applikation welche auf einen externen Server zugreift, und diese muss Ordnungsgemäß beendet werden da es ansonsten beim Neustart zu Problemen kommen kann.
    Das lässt mich tief schlucken.
    Wer zum Teufel schreibt solche fehlerintoleranten Anwendungen?

    Es gibt tausend Möglichkeiten, dass die Verbindung zwischen Client und Server unterbrochen wird.
    Was dann?
    --
    If Not Program.isWorking Then Code.Debug Else Code.DoNotTouch
    --
    Diese Klasse hab ich - Derfur zu verdanken , die dürfte deine Bedürfnisse abdecken ;)

    Spoiler anzeigen

    VB.NET-Quellcode

    1. Imports System
    2. Imports System.Text
    3. Imports System.Diagnostics
    4. Imports System.Runtime.InteropServices
    5. Module Windows_Controller
    6. Public Class WindowsController
    7. Public Enum Options
    8. LogOff = 0
    9. PowerOff = 8
    10. Reboot = 2
    11. ShutDown = 1
    12. Suspend = -1
    13. Hibernate = -2
    14. End Enum
    15. Public Structure LUID
    16. Dim LowPart As Integer
    17. Dim HighPart As Integer
    18. End Structure
    19. Public Structure LUID_AND_ATTRIBUTES
    20. Dim pLuid As LUID
    21. Dim Attributes As Integer
    22. End Structure
    23. Public Structure TOKEN_PRIVILEGES
    24. Dim PrivilegeCount As Integer
    25. Dim Privileges As LUID_AND_ATTRIBUTES
    26. End Structure
    27. Private Const TOKEN_ADJUST_PRIVILEGES = &H20
    28. Private Const TOKEN_QUERY = &H8
    29. Private Const SE_PRIVILEGE_ENABLED = &H2
    30. Private Const FORMAT_MESSAGE_FROM_SYSTEM = &H1000
    31. Private Const EWX_FORCE = 4
    32. Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA" (ByVal lpLibFileName As String) As IntPtr
    33. Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As IntPtr) As Integer
    34. Declare Function GetProcAddress Lib "kernel32" (ByVal hModule As IntPtr, ByVal lpProcName As String) As IntPtr
    35. Declare Function SetSuspendState Lib "Powrprof" (ByVal Hibernate As Integer, ByVal ForceCritical As Integer, ByVal DisableWakeEvent As Integer) As Integer
    36. Declare Function OpenProcessToken Lib "advapi32.dll" (ByVal ProcessHandle As IntPtr, ByVal DesiredAccess As Integer, ByRef TokenHandle As IntPtr) As Integer
    37. Declare Function LookupPrivilegeValue Lib "advapi32.dll" Alias "LookupPrivilegeValueA" (ByVal lpSystemName As String, ByVal lpName As String, ByRef lpLuid As LUID) As Integer
    38. Declare Function AdjustTokenPrivileges Lib "advapi32.dll" (ByVal TokenHandle As IntPtr, ByVal DisableAllPrivileges As Integer, ByRef NewState As TOKEN_PRIVILEGES, ByVal BufferLength As Integer, ByRef PreviousState As TOKEN_PRIVILEGES, ByRef ReturnLength As Integer) As Integer
    39. Declare Function ExitWindowsEx Lib "user32" (ByVal uFlags As Integer, ByVal dwReserved As Integer) As Integer
    40. Declare Function FormatMessage Lib "kernel32" Alias "FormatMessageA" (ByVal dwFlags As Integer, ByVal lpSource As IntPtr, ByVal dwMessageId As Integer, ByVal dwLanguageId As Integer, ByVal lpBuffer As StringBuilder, ByVal nSize As Integer, ByVal Arguments As Integer) As Integer
    41. Public Sub ExitWindows(ByVal how As Options, ByVal force As Boolean)
    42. Select Case how
    43. Case Options.Suspend
    44. SuspendSystem(False, force)
    45. Case Options.Hibernate
    46. SuspendSystem(True, force)
    47. Case Else
    48. ExitWindows(Convert.ToInt32(how), force)
    49. End Select
    50. End Sub
    51. Protected Sub ExitWindows(ByVal how As Integer, ByVal force As Boolean)
    52. EnableToken("SeShutdownPrivilege")
    53. If force Then how = how Or EWX_FORCE
    54. If (ExitWindowsEx(how, 0) = 0) Then Throw New PrivilegeException(FormatError(Marshal.GetLastWin32Error()))
    55. End Sub
    56. Protected Sub EnableToken(ByVal privilege As String)
    57. If Not CheckEntryPoint("advapi32.dll", "AdjustTokenPrivileges") Then Return
    58. Dim tokenHandle As IntPtr = IntPtr.Zero
    59. Dim privilegeLUID = New LUID
    60. Dim newPrivileges = New TOKEN_PRIVILEGES
    61. Dim tokenPrivileges As TOKEN_PRIVILEGES
    62. If (OpenProcessToken(Process.GetCurrentProcess().Handle, TOKEN_ADJUST_PRIVILEGES Or TOKEN_QUERY, tokenHandle)) = 0 Then Throw New PrivilegeException(FormatError(Marshal.GetLastWin32Error()))
    63. If (LookupPrivilegeValue("", privilege, privilegeLUID)) = 0 Then Throw New PrivilegeException(FormatError(Marshal.GetLastWin32Error()))
    64. tokenPrivileges.PrivilegeCount = 1
    65. tokenPrivileges.Privileges.Attributes = SE_PRIVILEGE_ENABLED
    66. tokenPrivileges.Privileges.pLuid = privilegeLUID
    67. Dim Size As Integer = 4
    68. If (AdjustTokenPrivileges(tokenHandle, 0, tokenPrivileges, 4 + (12 * tokenPrivileges.PrivilegeCount), newPrivileges, Size)) = 0 Then Throw New PrivilegeException(FormatError(Marshal.GetLastWin32Error()))
    69. End Sub
    70. Protected Sub SuspendSystem(ByVal hibernate As Boolean, ByVal force As Boolean)
    71. If Not CheckEntryPoint("powrprof.dll", "SetSuspendState") Then Throw New PlatformNotSupportedException("The SetSuspendState method is not supported on this system!")
    72. SetSuspendState(Convert.ToInt32(IIf(hibernate, 1, 0)), Convert.ToInt32(IIf(force, 1, 0)), 0)
    73. End Sub
    74. Protected Function CheckEntryPoint(ByVal library As String, ByVal method As String) As Boolean
    75. Dim libPtr As IntPtr = LoadLibrary(library)
    76. If Not libPtr.Equals(IntPtr.Zero) Then
    77. If Not GetProcAddress(libPtr, method).Equals(IntPtr.Zero) Then
    78. FreeLibrary(libPtr)
    79. Return True
    80. End If
    81. FreeLibrary(libPtr)
    82. End If
    83. Return False
    84. End Function
    85. Protected Function FormatError(ByVal number As Integer) As String
    86. Dim Buffer = New StringBuilder(255)
    87. FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, IntPtr.Zero, number, 0, Buffer, Buffer.Capacity, 0)
    88. Return Buffer.ToString()
    89. End Function
    90. End Class
    91. Public Class PrivilegeException
    92. Inherits Exception
    93. Public Sub New()
    94. MyBase.New()
    95. End Sub
    96. Public Sub New(ByVal message As String)
    97. MyBase.New(message)
    98. End Sub
    99. End Class
    100. End Module


    Tut perfeckt das was sie soll - beendet die Programme richtig vorm ShutDown ;)

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

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim ProcessName As String = "Notepad"
    3. Dim myProcesses() As Process = Process.GetProcesses
    4. For Each proc As Process In myProcesses
    5. If InStr(proc.ProcessName.ToLower, ProcessName.ToLower) Then
    6. ' If Not proc.CloseMainWindow() Then proc.Kill()
    7. proc.CloseMainWindow()
    8. End If
    9. Next
    10. End Sub
    @TVX Wann endlich verinnerlichst Du die Buchstabenfolge Option Strict On :?:
    Warum nicht

    VB.NET-Quellcode

    1. Dim myProcesses() As Process = Process.GetProcessesByName("Notepad")
    Die Kill-Variante sollte schon in Betracht gezogen werden, weil ein ungesichertes Dokument erst gespeichert werden will und dann der Save-(As-)Dialog aufgeht.

    VB.NET-Quellcode

    1. If Not proc.CloseMainWindow() Then
    2. proc.Kill()
    3. End If
    Bilder
    • Strict.png

      4,44 kB, 513×59, 124 mal angesehen
    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!
    vergessen - hab das nicht standardmäßig eingestellt ||

    VB.NET-Quellcode

    1. Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    2. Dim myProcesses() As Process = Process.GetProcessesByName("Notepad")
    3. For Each proc As Process In myProcesses
    4. If Not proc.CloseMainWindow() Then
    5. proc.Kill()
    6. End If
    7. Next
    8. End Sub​

    RodFromGermany schrieb:

    Die Kill-Variante sollte schon in Betracht gezogen werden, weil ein ungesichertes Dokument erst gespeichert werden will und dann der Save-(As-)Dialog aufgeht.

    Genau deswegen hätte ich nicht Kill genommen. Auf die Closemessage ist Notepad vorbereitet und zeigt den Save-Dialog an. So beugt man Datenverlust vor. Bei Kill wäre sofort alles weg und der Nutzer müsste seinen ungespeicherten 400 Seiten langen Aufsatz neu machen.

    Gonger96 schrieb:

    Genau deswegen hätte ich nicht Kill genommen.
    Jou.
    Genau das liegt im Ermessen des Schließenden, beide Lösungen stehen da.
    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!
    Und der Vorschlag von - Murdock Post 8 - sollte dann ungefähr so aussehen .

    VB.NET-Quellcode

    1. Option Strict On
    2. Public Class Form1
    3. Private Declare Function FindWindow Lib "user32" Alias "FindWindowA" (ByVal lpClassName As String, ByVal lpWindowName As String) As Integer
    4. Private Declare Function PostMessage Lib "user32" Alias "PostMessageA" (ByVal hwnd As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    5. Private Declare Function SendMessage Lib "user32" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal uMsg As Integer, ByVal wParam As Integer, ByVal lParam As Integer) As Integer
    6. Private Const WM_Quit = &H12
    7. Private Const WM_Close = &H10
    8. Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
    9. Dim lhwnd As Integer = FindWindow(vbNullString, "Unbenannt - Editor")
    10. SendMessage(lhwnd, WM_Close, 0, 0)
    11. 'PostMessage(lhwnd, WM_Quit, 0, 0)
    12. End Sub
    13. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    14. Process.Start("C:\windows\notepad.exe") 'Test Fenster
    15. End Sub
    16. End Class​
    Hallo!

    VB.NET-Quellcode

    1. Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
    2. Process.Start("C:\windows\notepad.exe") 'Test Fenster
    3. End Sub


    Ich empfehle es so zu machen:

    VB.NET-Quellcode

    1. Process.Start("notepad.exe")

    Weil nicht jeder das System-Windows auf C:\ hat!
    Visual Basic.NET 8o
    MS-SQL
    8o

    TVX schrieb:

    sollte dann ungefähr so aussehen
    Was soll der Quatsch? Denk doch mal nach, bevor Du postest, da waren doch schon beliebig viele bessere Lösungen da.
    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!