愚者の経験

「また今度」はほとんどこない

Windows10にてmshtml.dllが更新される[VBA]

Windows10のアップデート(5/10前後)でに上記のdllが更新されました。
おそらくそれが原因で下記のコードが動かなくなりました。

Option Compare Database
Option Explicit

' 擬似非同期処理クラス
' 指定したオブジェクトのパプリックプロシージャを非同期実行

Private html As Object
Private Method As String
Private Arguments As Variant
Public Target As Object

Private Sub Class_Initialize()
    Set html = CreateObject("htmlfile")
    Set html.parentWindow.onhelp = Me
End Sub

Private Sub Class_Terminate()
    Set html.parentWindow.onhelp = Nothing
    Set html = Nothing
End Sub

Public Sub AsyncCall(MethodName As String, TimeLag As Long, ParamArray Args() As Variant)
    If (Target Is Nothing) Then
        Set Target = CodeContextObject
    End If
    
    Method = MethodName
    Arguments = Args
    
    html.parentWindow.setTimeout "onhelp.CallMethod", TimeLag, "VBScript"
End Sub

' 非同期実行プロシージャ
Public Sub CallMethod()
    CallByName Target, Method, VbMethod, Arguments
End Sub

フォームのPublicのプロシージャを非同期もどきで処理していたんですがなぜか動かなくなりました。エラーが出ることもないです。

上記のプログラムをざっくり説明すると
「webページのオブジェクト作って、setTimeout関数で画面の処理(フォームのPublicプロシージャ)を呼ぼう」ってプログラムです。
本来は不可能なMsgBoxを同時に2つ出したりできます。

Private Sub Class_Initialize()
    Set html = CreateObject("htmlfile")
    Set html.parentWindow.onhelp = Me
End Sub

CreateObject(“htmlfile”)でhtmlドキュメントを作成し
parentWindowの適当なプロパティ(この場合はonhelp)にMe(このクラスオブジェクト)を代入し

    html.parentWindow.setTimeout "onhelp.CallMethod", TimeLag, "VBScript"

setTimeout関数でこのクラス(onhelpに代入されている)のメソッド呼びましょうねって感じです。

動かなくなったので代替コードが下記

Option Compare Database
Option Explicit

' 擬似非同期処理クラス
' 指定したオブジェクトのパプリックプロシージャを非同期実行

Private html As Object
Private Method As String
Private Arguments As Variant
Public Target As Object

' Set html.parentWindow.onhelp = Me
' html.parentWindow.setTimeout ~~
' 上記コードは動かなくなった(Windows10のアップデートでmshtml.dllが更新されたのが原因?)
' ので代替コードで修正

Private Sub Class_Initialize()
    Set html = CreateObject("htmlfile")
    
    Const EXEC_SCRIPT = _
            "this.async=" & _
                "function(obj,lag){" & _
                    "setTimeout(function() {obj.CallMethod()},lag)}"
    
    Call html.parentWindow.execScript(EXEC_SCRIPT)
End Sub

Private Sub Class_Terminate()
'    Set html.parentWindow.onhelp = Nothing
    Set html = Nothing
End Sub

Public Sub AsyncCall(MethodName As String, TimeLag As Long, ParamArray Args() As Variant)
    If (Target Is Nothing) Then
        Set Target = CodeContextObject
    End If
    
    Method = MethodName
    Arguments = Args
    
    'html.parentWindow.setTimeout "async.CallMethod", TimeLag, "VBScript"
    Call html.parentWindow.async(Me, TimeLag)
End Sub

' 非同期実行プロシージャ
Public Sub CallMethod()
On Error Resume Next
    CallByName Target, Method, VbMethod, Arguments
End Sub

parentWindow.execScriptでfunctionを登録して
引数でMeを指定しfunction内のsetTimeoutで指定秒数後callします。
なぜこれなら動くのか全く不明だがとりあえず動く。

広告

コメントを残す

以下に詳細を記入するか、アイコンをクリックしてログインしてください。

WordPress.com ロゴ

WordPress.com アカウントを使ってコメントしています。 ログアウト /  変更 )

Google フォト

Google アカウントを使ってコメントしています。 ログアウト /  変更 )

Twitter 画像

Twitter アカウントを使ってコメントしています。 ログアウト /  変更 )

Facebook の写真

Facebook アカウントを使ってコメントしています。 ログアウト /  変更 )

%s と連携中

%d人のブロガーが「いいね」をつけました。