deadman icon indicating copy to clipboard operation
deadman copied to clipboard

Integrate with windows better to protect the app from easy closing

Open flowchartsman opened this issue 9 years ago • 8 comments

Windows 7/8 do not send SIGINT to console apps when the window is closed. This needs to be detected and handled as a reboot scenario, or, if it cannot be handled, the app will need to be compiled with -ldflags -H=windowsgui and rewritten to be GUI-centric.

flowchartsman avatar May 06 '15 03:05 flowchartsman

It appears we need to detect CTRL_CLOSE_EVENT, which is not currently captured by the Go runtime. The changes necessary are in the following patch, which proposes sending os.Terminate in its place, and tracked as issue #7479 in the golang repository.

flowchartsman avatar May 06 '15 03:05 flowchartsman

Alternatively, we can build it as a "GUI" app, which requires special flags and, of course, a special way to close the app (especially if we implement issue #6), because it will no longer have a windowed command line presence. A related issue on the Go project is being tracked as issue 2565 which, when fixed, will make special build flags unnecessary.

flowchartsman avatar May 06 '15 04:05 flowchartsman

The current consideration is having the windows version of the app open a port bound to localhost and then adding a /k flag which will have the app attempt to connect to this port and tell the process to terminate nicely. Combining this with issue #6 would probably involve having the sending process sending an "expect password" message which will cause the listening process start a timer and reboot if it does not get a response in the allotted time period.

flowchartsman avatar May 07 '15 18:05 flowchartsman

For better integration with windows, use the following code:

import (
        "fmt"
        "syscall"
        "unsafe"
)

var (
        kernel32, _        = syscall.LoadLibrary("kernel32.dll")
        getModuleHandle, _ = syscall.GetProcAddress(kernel32, "GetModuleHandleW")

        user32, _     = syscall.LoadLibrary("user32.dll")
        messageBox, _ = syscall.GetProcAddress(user32, "MessageBoxW")
)

These functions have been called as an example, You can call functions like FreeConsole() and SetConsoleTitle() You can find the whole code here: https://github.com/golang/go/wiki/WindowsDLLs MSDN will tell you which function is in which library.

omern1 avatar May 08 '15 05:05 omern1

Way ahead of you, buddy. It's a lot more complicated than that, though.

flowchartsman avatar May 08 '15 08:05 flowchartsman

I'm sure. I was just giving an example. I don't know much about the language, I'm still learning it.

omern1 avatar May 08 '15 09:05 omern1

I think I read somewhere that you can call C++ code from Go. If that is true, I can write the code in C++ for windows and you can call it from Go. I'm learning the language but I am not as comfortable with it as I am with java or C++.

omern1 avatar May 12 '15 16:05 omern1

I'm trying to avoid using cgo so that the build process stays simple and cross-platform and doesn't become a mess. This means limiting it to syscall only (no import "C") (at least on Windows) If this becomes unavoidable, I'll consider it, but I'd like to research the syscall route for now, even if the code is somewhat more complex. At the moment, I can build the binary for any target platform anywhere (currently I'm using OSX and Linux), and I'd like to keep it that way and play to Go's strengths.

flowchartsman avatar May 12 '15 16:05 flowchartsman