wailsapp / wails

Create beautiful applications using Go
https://wails.io
MIT License
23.25k stars 1.1k forks source link

wails2.8 window11 上打开对话框选择确认或则取消都会crash #3535

Open daimall opened 2 weeks ago

daimall commented 2 weeks ago

Description

基于最简单的样例,只要打开对话框,无论选择确认还是取消都会crash package main

import ( "context"

"github.com/wailsapp/wails/v2/pkg/runtime"

)

// App struct type App struct { ctx context.Context }

// 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 }

// Greet returns a greeting for the given name func (a App) Greet(name string) string { filePath, err := runtime.SaveFileDialog(a.ctx, runtime.SaveDialogOptions{ Filters: []runtime.FileFilter{{Pattern: ".*"}}, DefaultFilename: "myproject", Title: "Save", }) if err != nil { return err.Error() }

return filePath

} 上面就是最简单的代码,错误提示如下 To develop in the browser and call your bound Go methods from Javascript, navigate to: http://localhost:34115 2024/06/12 09:44:06 The parameter is incorrect. [0612/094406.974:ERROR:window_impl.cc(121)] Failed to unregister class Chrome_WidgetWin_0. Error = 0

该问题不必现,出现后重启电脑大概率能消失,过一段时间又出现了

To Reproduce

1、运行上面最简单的demo 2、Click Greet image 3、click 取消 image 4、crash 2024/06/12 09:53:12 The parameter is incorrect. [0612/095312.565:ERROR:window_impl.cc(121)] Failed to unregister class Chrome_WidgetWin_0. Error = 0

Expected behaviour

正常运行

Screenshots

image image image

Attempted Fixes

重启电脑,大概率能恢复

System Details

> wails docker
Wails CLI v2.8.2

Available commands:

   build      Builds the application
   dev        Runs the application in development mode
   doctor     Diagnose your environment
   init       Initialises a new Wails project
   update     Update the Wails CLI
   show       Shows various information
   generate   Code Generation Tools
   version    The Wails CLI version

Flags:

  -help
        Get help on the 'wails' command.

 ♥   If Wails is useful to you or your company, please consider sponsoring the project:
https://github.com/sponsors/leaanthony

webview 版本:
EdgeWebView\Application\125.0.2535.92

windows 版本:
OS 名称:          Microsoft Windows 11 企业版
OS 版本:          10.0.22631 暂缺 Build 22631
OS 制造商:        Microsoft Corporation
OS 配置:          成员工作站
OS 构建类型:      Multiprocessor Free

Additional context

跟踪代码发现是 v2\internal\go-common-file-dialog\cfd\vtblCommonFunc.go 中的 iModalWindowVtbl.show 方法crash的 func (vtbl *iModalWindowVtbl) show(objPtr unsafe.Pointer, hwnd uintptr) error { fmt.Println("iModalWindowVtbl>>>>>>>>>>>>>111111", vtbl.Show, objPtr, hwnd) fmt.Printf("Function address: %x\n", vtbl.Show) fmt.Println("iModalWindowVtbl>>>>>>>>>>>>>111111") ret, , := syscall.Syscall(vtbl.Show, 1, uintptr(objPtr), hwnd, 0) fmt.Println("iModalWindowVtbl>>>>>>>>>>>>>22222") return hresultToError(ret) }

输出的结果如下:

iModalWindowVtbl>>>>>>>>>>>>>111111 140703621641488 0x2016af66958 3346448 Function address: 7ff81d62f510 iModalWindowVtbl>>>>>>>>>>>>>111111 2024/06/12 11:45:27 The parameter is incorrect. [0612/114527.816:ERROR:window_impl.cc(121)] Failed to unregister class Chrome_WidgetWin_0. Error = 0

daimall commented 2 weeks ago

3.0 依然有此问题 image

下面代码改成直接调用 windows api 就没有问题 package main

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

// App struct type App struct { ctx context.Context }

var ( modComdlg32 = syscall.NewLazyDLL("comdlg32.dll") procGetSaveFileName = modComdlg32.NewProc("GetSaveFileNameW")

modKernel32      = syscall.NewLazyDLL("kernel32.dll")
procGetLastError = modKernel32.NewProc("GetLastError")

)

const ( OFN_FILEMUSTEXIST = 0x00001000 OFN_PATHMUSTEXIST = 0x00000800 OFN_OVERWRITEPROMPT = 0x00000002 )

type OPENFILENAME struct { lStructSize uint32 hwndOwner uintptr hInstance uintptr lpstrFilter uint16 lpstrCustomFilter uint16 nMaxCustFilter uint32 nFilterIndex uint32 lpstrFile uint16 nMaxFile uint32 lpstrFileTitle uint16 nMaxFileTitle uint32 lpstrInitialDir uint16 lpstrTitle uint16 Flags uint32 nFileOffset uint16 nFileExtension uint16 lpstrDefExt uint16 lCustData uintptr lpfnHook uintptr lpTemplateName uint16 pvReserved uintptr dwReserved uint32 FlagsEx uint32 }

// 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 }

// Greet returns a greeting for the given name func (a *App) Greet(name string) string { var ofn OPENFILENAME file := make([]uint16, 260) ofn.lStructSize = uint32(unsafe.Sizeof(ofn)) ofn.lpstrFile = &file[0] ofn.nMaxFile = uint32(len(file)) ofn.Flags = OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST | OFN_OVERWRITEPROMPT

ret, _, err := procGetSaveFileName.Call(uintptr(unsafe.Pointer(&ofn)))
if ret == 0 {
    fmt.Printf("Error: %v\n", err)
    errorCode, _, _ := procGetLastError.Call()
    fmt.Printf("CommDlgExtendedError: %d\n", errorCode)
} else {
    fmt.Printf("Selected file: %s\n", syscall.UTF16ToString(file))
}

return syscall.UTF16ToString(file)

}