3

コンテキスト:Framework v3.5を対象として、VB(.NET)で記述された、VisualStudio2012で現在開発/保守されているプログラム。ほとんどのお客様はオランダ語のWindowsをインストールしており、またほとんどのお客様の地域設定はオランダ語(nl-NL)に設定されています。これは、を意味します。(ピリオド)グループ化および、(コンマ)を小数点記号として使用します。

ほぼ10,000人の顧客のうち、問題が発生したのは1つだけでした。その原因は、ファイルの(小さな)アイコンを取得するためのSHGetFileInfoの呼び出しに起因するものであると特定されました。コード内の関連するステートメント:

  Private Declare Unicode Function SHGetFileInfo Lib "Shell32.dll" Alias "SHGetFileInfoW" (pszPath As String, dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, cbSizeFileInfo As UInteger, uFlags As UInteger) As IntPtr

Dim result As IntPtr = SHGetFileInfo(pszPath, dwFileAttributes, psfi, cbSizeFileInfo, uFlags)

この顧客の特定のPCで、SHGetFileInfoへの(最初の)呼び出しの前にSystem.Globalization.CultureInfo.CurrentCultureが(nl-NL)であったと評価しましたが、呼び出しの直後にCurrentCultureが(en -米国)、これは明らかに他の場所で問題を引き起こしました。

その時点でコードを一時停止し、構成パネルを調べても、地域設定はまだオランダ語(nl-NL)でした。また、SystemEvents.UserPreferenceChanged(または-Changing)イベントはコードでキャッチされませんでした。プログラムを停止して再起動した後、プログラム内のCurrentCultureは、最初のSHGetFileInfo呼び出しまで、再びオランダ語(nl-NL)でした。

実用的な意味では、必要に応じてCurrentCultureをリセットすることで問題を解決しました。

  Private Declare Unicode Function SHGetFileInfo0 Lib "Shell32.dll" Alias "SHGetFileInfoW" (pszPath As String, dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, cbSizeFileInfo As UInteger, uFlags As UInteger) As IntPtr


  Private Shared Function SHGetFileInfo(pszPath As String, dwFileAttributes As UInteger, ByRef psfi As SHFILEINFO, cbSizeFileInfo As UInteger, uFlags As UInteger) As IntPtr

    Dim ciBefore As System.Globalization.CultureInfo = Application.CurrentCulture

    Dim result As IntPtr = SHGetFileInfo0(pszPath, dwFileAttributes, psfi, cbSizeFileInfo, uFlags)

    Dim ciAfter As System.Globalization.CultureInfo = Application.CurrentCulture
    If (ciAfter.Name <> ciAfter.Name) OrElse (ciBefore IsNot ciAfter) Then
      Application.CurrentCulture = ciBefore
    End If

    Return result
  End Function

問題はその特定の顧客であるPCにのみ現れたので、私は彼のPCで問題を分析する必要があり、チェックする時間を制限しました。それで、彼のために実際的な意味で問題を解決した後、私はこれがどのように起こり得るのかわからないという不快な事実を残しました、そしてそれ故に、私の質問は:誰かがこの暗闇の中で光を当てることができますか?

追加情報:お客様は1か月前までこの問題を抱えていませんでした。最近、彼はDropBoxとBoxSyncを使い始めました(そしておそらくインストールされました)。私はこれらの内部動作については知りませんが、それらも「ファイルを使用」しており、それらのインストールは表示される問題とほぼ一致しているため、接続があるのではないかと疑っています。

問題を十分に述べたことを願っていますが、さらに情報が必要な場合は、喜んでこれを提供していきます。どんな助けでも大歓迎です。提案を事前に感謝します。

4

1 に答える 1

2

スレッドのCurrentCultureプロパティは、内部で管理されていないプロパティです。ネイティブコードは、SetThreadLocale()を呼び出して変更できます。したがって、管理されていない関数をピンボークすると、文化が変化する理由はまったく不思議ではありません。

さらに、SHGetFileInfo()のようなシェル関数は、シェル拡張の動作の影響を受けます。それらは野生にたくさんあり、このような問題を頻繁に引き起こすことはありません。SetThreadLocale()を呼び出すことは、フォーマットの問題を修正するための便利な方法です。ロケールを復元しないことは、他のプロセスのコンテキストで実行されるため、特にシェル拡張では重大なバグです。

コードを変更してこの問題を修正するのではなく、お客様にマシンを修正するように伝えてください。そのための最良の方法は、SysInternalsのAutoRunsユーティリティを実行することです。[エクスプローラー]タブには、インストールされているすべてのシェル拡張機能のリストが表示されます。[発行元]列に「Microsoft」が含まれていないものはすべて無効にします。ログアウト+ログインして効果を上げましょう。これらの拡張機能のいくつかがないと生きていけない場合は、それらを1つずつ再度有効にして、トラブルメーカーを見つけることができます。

于 2012-10-20T11:52:44.803 に答える