Estimado Carlos,
Lo tienes localizado: nunca liberas el WebView al cerrar la ventana, y la clase no lo hace por ti. Te detallo la cadena completa, verificada en el fuente:
Qué pasa
- oWeb:End() no se llama nunca. Tu oWeb es STATIC y el ACTIVATE WINDOW no tiene cláusula VALID. Al cerrar la ventana muere el HWND padre, pero el controller COM (ICoreWebView2Controller) sigue vivo: lo único que lo destruye es TWebView2:End() → webview2_end() → delete (source/classes/twebview2.prg:51, source/internal/twebview/cwebview.cpp:734).
- El destructor además fuga por diseño: TWebView() quita los handlers y libera los settings, pero no llama a pController->Close() ni hace Release() del controller/core. Cada visita deja un browser Edge huérfano y un proceso rondando.
- El objeto Harbour queda eternamente referenciado: New() hace AAdd( aWebViews, Self ) y nada lo quita jamás.
- Al reentrar se crea un segundo controller sobre la misma user-data-folder por defecto (%APPDATA%\<tuExe>), con el primero fugado aún vivo. Y aquà está el bloqueo: Initialize(), Navigate() y SetHtml() esperan la creación async con while( bBusy ) SysRefresh();. Si la creación no completa, ese bucle no sale nunca → la app se queda totalmente bloqueada bombeando mensajes. Por eso te pasa igual en 32 y 64 bits: es lógica, no arquitectura.
- Agravante: WebView2_OnBind() resuelve con aWebViews[ AScan(...) ] sin comprobar si es 0 (los otros dos callbacks sà lo comprueban), asà que mensajes JS del controller fugado pueden caer en el objeto muerto, cuya ventana ya no existe.
La prueba de que End() es obligatorio la da el propio framework: FW_WebView() (mismo twebview2.prg, lÃneas 251-264) engancha oWnd:bValid := { || oWeb:End(), .t. }, y el sample samples/ai/opencode2.prg:2021 limpia con oWeb:End() + oWeb := nil en su Cleanup().
La corrección (lado app)
STATIC oWeb := nil
FUNCTION VentanWeb()
...
ACTIVATE WINDOW oWnd ;
ON INIT WebVie2Init( oWnd ) ;
VALID WebVie2End() ;
ON RESIZE ( oWeb:SetSize( oWnd:nWidth, oWnd:nHeight ) )
return nil
STATIC FUNCTION WebVie2End()
if oWeb != nil
oWeb:End()
oWeb := nil
endif
return .t.
Dos detalles más en tu código: en ON RESIZE WndResize( nWidth, nHeight ), nWidth/nHeight no existen en ese ámbito — usa oWnd:nWidth/oWnd:nHeight (o bResized, que sà recibe {|nType,nWidth,nHeight|}); y blinda WndResize()/VentanaBind() con if oWeb == nil ... return, porque pueden llegar callbacks con la ventana a medio cerrar.
Lado framework (pendiente, si quieres)
TWebView2:Destroy() hoy es VIRTUAL vacÃo; puedo implementarlo para que llame a End() y saque el objeto de aWebViews, blindar GetWebView() contra AScan()==0, y añadir pController->Close() + Release() en TWebView(). Eso exige reconstruir la lib C — dime y lo hago con su entrada en whatsnew.txt.