golang
部分主要是用来启动和结束 webman
进程的,其他所有业务流程和前端部分都是由 webman
响应的。
有兴趣可以下载安装体验一下,只支持 Windows
,安装包大小:12.7MB
。
下载地址 密码:webman
。
网盘里面有一个 Windows
系统版本的 micro.sfx
文件,只打包了小部分扩展,没有带 MySQL
,只有sqlite3
。
// app.go
// App struct
type App struct {
ctx context.Context
phpCmd *exec.Cmd
}
// NewApp creates a new App application struct
func NewApp() *App {
return &App{}
}
// startup is called when the app starts. The context is saved
// so we can call the runtime methods
func (a *App) startup(ctx context.Context) {
a.ctx = ctx
a.startPHPProcess()
go a.monitorPHPProcess()
}
func (a *App) startPHPProcess() {
exePath, _ := os.Executable()
installDir := filepath.Dir(exePath)
phpWebmanExePath := filepath.Join(installDir, "myapp.exe")
fmt.Println(phpWebmanExePath)
cmd := exec.Command(phpWebmanExePath)
cmd.SysProcAttr = &syscall.SysProcAttr{
HideWindow: true,
CreationFlags: 0x08000000, // CREATE_NO_WINDOW
}
err := cmd.Start()
if err != nil {
// 使用 Wails 弹窗提示用户
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
Type: runtime.ErrorDialog,
Title: "Error",
Message: "Failed to start PHP process. Please restart the application.",
})
return
}
time.Sleep(2 * time.Second)
a.phpCmd = cmd
}
func (a *App) shutdown(ctx context.Context) {
fmt.Println(a.phpCmd)
if a.phpCmd != nil && a.phpCmd.Process != nil {
a.phpCmd.Process.Kill()
}
}
func (a *App) monitorPHPProcess() {
if a.phpCmd == nil {
return
}
for {
// 等待进程完成
err := a.phpCmd.Wait()
if err != nil {
// 进程已退出
runtime.MessageDialog(a.ctx, runtime.MessageDialogOptions{
Type: runtime.WarningDialog,
Title: "PHP Process Stopped",
Message: "The PHP process has stopped. Please restart the application.",
})
break
}
// 每隔10秒检查一次
time.Sleep(10 * time.Second)
}
}
理论上如果用 libphp(embed)+go+wails 可以实现不依赖 micro.sfx 来编写桌面程序,就像 frankenPHP 一样,且可以实现可替换的代码。有人有兴趣可以研究一下。
之前在 frankenPHP 的 discussions 上看到大佬你好像说过一次这种思路,后续有空我研究一下。
同道中人,你的这个和我的webview-jacketing原理差不多,不过我没把
micro.sfx
加入进来,我用vlang
来编译个外壳哈哈,webview 套壳能用就行