none
Windows 10 Fall Creators Update (バージョン1709) にアップグレード後、MFC リボンを使用したアプリケーションの動作が遅くなる

    質問

  • Windows 10 Fall Creators Update (バージョン1709) にアップグレードすると、MFC リボンを使ったアプリケーションの動作が遅くなります。

    具体的には、次の現象が発生します。

    ・リボンのタブを切り替えるときに2~3秒ほど時間がかかります。

    ・右クリックでポップアップメニューを表示するときも同様に2~3秒ほど時間がかかります。

    ・どちらの操作も初回表示のみ遅く、2回目からは素早く表示されます。

    Windows 10 Creators Update (バージョン1703) では、どちらの操作も0.5秒ほどで問題なく表示されます。

    MFCリボンアプリケーションは、Visual Studio 2010 で作成しています。

    ただし、最新のVisual Studio 2017でも発生するようです。

    https://developercommunity.visualstudio.com/content/problem/136952/mfc-ribbon-slow-on-first-loadshow.html

    動作が遅くなってしまい非常に困っています。

    ソースコードを修正する方法だけでなく、Windows10の設定変更などで回避する方法があれば教えていただきたく存じます。(1703に戻す方法以外で)

    よろしくお願いします。

    2017年10月31日 10:23

すべての返信

  • いろいろ試してみて、分かったことをご報告します。

    Windows 10 (Ver 1709) でGetPixel()/SetPixel() の呼び出しが10倍以上遅くなっているのが原因であると思われます。
    特に、リボンのアイコン数が多いと、目に見えて遅くなります。
    Visual Studio 2017 でビルドしても発生します。
    詳しくは以下の通りです。

    【再現手順】
     a. MFCリボンアプリケーションを新規作成。
     b. リソースエディタを開く。
     c. ビットマップリソースを2種類(2048px×16px, 2048px×32px)追加。
     d. リボンリソースを開き、カテゴリを追加。
     e. dで追加したカテゴリに対し、Small Images, Large Images としてbで追加したビットマップリソースのIDを指定。
     f. 作成したアプリケーションをビルド。
     g. Windows 10 (Ver 1709) でアプリケーションを起動し、カテゴリを切り替えると、切り替えが完了するまで1秒以上かかる。


    【原因】
     MFCリボンのタブ(カテゴリ)を切り替えたとき、カテゴリのSmallImages, Large Images に対して、SetTransparentColor() が呼び出される。
     この関数からUpdateInternalImage() を経由し、最終的にGetPixel()/SetPixel() が実行されるが、Windows 10 (Ver 1709) では、Ver 1703 と比較して、GetPixel()/SetPixel() の呼び出しに10倍以上時間がかかるようになってしまった。

    【回避策】
     CMainFrame::OnCreate() でリボンを生成した直後に、全カテゴリのSmallImages, Large Images に対して、
     SetTransparentColor(GetGlobalData()->clrBtnFace) を呼び出す。
     (VS 2010 の場合は、SetTransparentColor(afxGlobalData.clrBtnFace))
     重たい処理を事前に行っておくことで、リボンのタブ(カテゴリ)を切り替えが素早く行われる。 

     ただし、この回避策では、起動するまで時間が遅くなるため、抜本的な対処ではない。
     OS側で GetPixel()/SetPixel() の高速化が対策されない場合、
     抜本的に対処するには、GetPixel()/SetPixel() を使わないよう、CMFCToolBarImages クラスの処理を修正する必要がある。


    この問題を早急にマイクロソフト社が修正しない限り、アプリ側で何らかの対処をせざるを得ないと思います。
    そもそも、GetPixel()/SetPixel() を多用していること自体がよくないのですが、自前でコーディングしていた部分であればともかく、ライブラリ側の問題でユーザーが修正を迫られるのはいかがなものなのでしょうか?

    最近のマイクロソフト社の動きを見ていると、従来型のWindowsデスクトップアプリにはあまり関心がない気がしてなりません。
    Windows離れがより一層進むことを危惧します。

    2017年11月4日 20:43
  • 詳細な検証情報の共有、ありがとうございます。

    一点、共有しておきたいことがあるとすれば、「この場はユーザー同士の情報交換フォーラムであり、Microsoft の開発メンバーに声を届ける場ではない」ということです。
    調査いただいた内容から、Windows の不具合であろうことは見えていますので、フィードバック Hub にダメ押しで挙げてください。

    2017年11月4日 22:53
    モデレータ
  • Azulean 様

    ご連絡ありがとうございます。

    ここは、開発者間の情報交換の場であることは承知しております。

    フィードバックHub にも投稿していますが、まだレスがついていないようですので、そちらにもコメントを追記しています。

    2017年11月5日 3:19
  • フォーラムの性質は理解されていると言うことなので、その上で1つ書かせてください。

    Windows は年2回大規模なアップデートを配信するというリリース体制に移行しました。
    新機能の追加・仕様変更などが従来よりも頻繁に発生するため、結果的に、何らかの不具合が埋め込まれるリスクが高まりました。
    Creators Update でも「DateTimePicker コントロールの表示や入力が正しく機能しない場合がある」という問題がありましたので、今後も続くと予想されます。
    (もっとも、古いコモンコントロールを利用するアプリケーションとなると、割合は低くなりますが)

    Microsoft は内部でのリングのほか、Insider Preview としてテストする人々を募っています。
    これは Microsoft 自身で見つけきれなかった不具合を見つけてもらう性質もあると思っています。
    自己防衛も兼ねて、Insider Preview の終盤には自分たちのアプリケーションの動作確認を通じて Windows の不具合を見つけていくのも必要かもしれませんね。
    (正式リリース前に見つければ修正が早まるかもしれない。正式リリース後だと定例リリースと一緒にリリースなど、スピード感が落ちる)

    2017年11月5日 7:03
    モデレータ
  • Azulean 様

    自己防衛のために、Insider Preview でテストしておくというのは、おっしゃる通りだと思います。

    ただ、そうであれば、マイクロソフト社は、Windows 10のアップグレードにおいて、「不具合が出る可能性があるので、Insider Preview でテストすべき」 ということを、もっと開発者にアピールすべきでしょう。 

    最近、Windows デスクトップアプリ開発者向けのサポートが手薄になってきていると感じます。 早くUWPへの移行を進めたいめのでしょうね。

    (Azulean 様に言ってもどうしようもないのですが、お許しください。)

    2017年11月6日 20:50
  • ただ、そうであれば、マイクロソフト社は、Windows 10のアップグレードにおいて、「不具合が出る可能性があるので、Insider Preview でテストすべき」 ということを、もっと開発者にアピールすべきでしょう。 

    具体的にどういった策を採っていたら良かったとお考えですか?
    仮に Web サイトやエバンジェリストのブログに載っていたとして、「アピールされていた」とみなせますか?
    良い案があれば、それもフィードバックとして出しておくことをお勧めします。
    (愚痴や批判だけだと何も変わらないので建設的な方向で考えるという視点からです)

    どちらかと言えば、我々日本人が思い込みがちな、「品質が高くて当然」という意識から抜け出すことが、Developer に求められているかと思います。
    こういった話は Microsoft に限らず、欧米系のベンダーではよくある話でしょうから。
    こういった見方もあるという紹介まで

    最近、Windows デスクトップアプリ開発者向けのサポートが手薄になってきていると感じます。 早くUWPへの移行を進めたいめのでしょうね。

    どうしても、リソースは限られている以上、優先度はあるでしょうね。
    .NET Framework の Windows Forms は高 DPI 対応で地道に手を入れている現状はあるので、デスクトップアプリ全体ではないと思いますけれども。

    2017年11月6日 22:09
    モデレータ
  • Windows Defender の制御フローガードをオフにすることでとりあえずは回避できましたが、セキュリティ緩くすることになるのであまりいい状態ではないですね。

    2017年11月9日 0:54
  • gizmolabs 様

    ご連絡ありがとうございます。

    こちらでも試してみましたが、Windows Defender の制御フローガードをオフにしても依然として遅いままです。

    ちなみに、developpercommunity の方では、制御フローガードをオフにすると改善したという報告があるようです。

    Windows Defender 以外のセキュリティソフトを入れていない状態で確認していますが、gizmolabs 様の環境にはセキュリティソフトをインストールされていますでしょうか?

    2017年11月9日 20:27
  • Azulean 様

    ご連絡ありがとうございます。

    ご質問の件について回答します。

    Windows 7や8の頃は、アプリケーションを最新OSに対応させるための注意点について、マイクロソフトからセミナーが開催され、私も参加させていただきました。

    しかし、Windows 10発売後のアップデートについて、マイクロソフトより、新機能などの案内はあったと思いますが、「アップデートによりこれまで動いていたアプリが正常に動かなくなる可能性がある」という案内はなかったのではないかと思います。

    Azulean 様のようにWindowsを熟知している方であれば、「OSのアップデートで不具合が出る」ことは常識だと思いますが、一般の開発者までこの常識が通じているかといえばそうではないと思います。

    アップデートでトラブルが発生しないのであれば現在のように自動的にアップデートしても構いませんが、それができないのであれば、

    マイクロソフト自ら、開発者および一般ユーザーにOSアップデートの危険性を積極的に通知すべきだと思います。

    (ただし、戦略上絶対にこんなことはできないでしょう。)

    ちなみに、マイクロソフトの姿勢をかなり批判していますが、これは「マイクロソフト自身で発見・修正できる不具合がある」から批判するのであって、自作アプリの不具合について、すべてマイクロソフトのせいにするわけではありません。

    自作アプリの処理が分からないことには対処できない不具合もありますので、そのような不具合については当然開発者の責任で修正する必要があります。

    あと、「品質が高くて当然」 というのは、Windows が有償であり、マイクロソフト以外改変できないことから、高品質を要求することは当然のことだと思います。

    要望の実現にお金を払うのは構いませんが、不具合修正についてお金を払うのは到底受け入れられません。

    (オープンソースであれば、気に入らない部分は自分で修正すればよいのでそこまで高品質を求めません。)

    「過剰に高品質を求めることが悪い」と言われれば、「顧客が求めているので、対応するのが当然」ということになります。

    Windows デスクトップ開発へのサポートが最近手薄な件については、すでにあきらめています。

    既にマルチプラットフォーム対応が求められる時代なので、早く Xamarin や Cordova に移行すべきなのでしょう。

    おそらく、これ以上話をしても平行線になると思いますので、返信は不要です。

    いろいろとご意見いただきありがとうございました。

    2017年11月9日 22:03
  • 私の1意見ですので、議論に値しないとお考えであれば読み捨ててください。

    Windows 7や8の頃は、アプリケーションを最新OSに対応させるための注意点について、マイクロソフトからセミナーが開催され、私も参加させていただきました。

    私の「どのような手段であればアピールされていたとみなせますか?」に対するお答えはこの部分ですかね…?
    セミナーの参加枠は有限なので、すべての開発者にリーチできる手段ではなさそうですが…。

    しかし、Windows 10発売後のアップデートについて、マイクロソフトより、新機能などの案内はあったと思いますが、「アップデートによりこれまで動いていたアプリが正常に動かなくなる可能性がある」という案内はなかったのではないかと思います。

    不具合を前面に出した内容はないでしょうけれども、Insider Preview で互換性評価を行って問題を検証する、リリースされたら評価するといった話は出ていますね。
    https://blogs.windows.com/japan/2017/08/04/waas-simplified-and-aligned/

    Azulean 様のようにWindowsを熟知している方であれば、「OSのアップデートで不具合が出る」ことは常識だと思いますが、一般の開発者までこの常識が通じているかといえばそうではないと思います。

    受動的な立場でいると今後も難しいでしょう。
    これを契機に情報収集する、積極的に試す側に動いて事前に予防するか、Microsoft の有償サポートで「不具合である」というエビデンス(証拠)を引き出して、顧客に説明する運用を取っていくか。

    ちなみに、マイクロソフトの姿勢をかなり批判していますが、これは「マイクロソフト自身で発見・修正できる不具合がある」から批判する

    これはユーザー、開発者サイドから断言できるものではないと思います。

    「すべてのアプリケーション、すべてのデバイスをテストしていれば、発見できる」であるならば、スピード感や費用対効果の観点から無理でしょう。
    実際、我々アプリケーション開発者も、すべてのデバイスではテストしていないのですから、要求されても困る立場ですし…。

    また、Insider Preview を通しても発見されなかったか、発見されたが修正されなかったかのいずれかなので、人数比からすると、Microsoft 内で発見できないレベルだったと言えるかもしれません。

    あと、「品質が高くて当然」 というのは、Windows が有償であり、マイクロソフト以外改変できないことから、高品質を要求することは当然のことだと思います。

    「(前述のような判定基準で)MS が見つけられるはずの不具合は 0 にしろ」というお考えであれば、1開発者として、費用対効果に合っていないと思いますけれども…。

    要望の実現にお金を払うのは構いませんが、不具合修正についてお金を払うのは到底受け入れられません。

    この話を考えの根底に置くなら、Windows は使えないことになります。
    昔からですが、Windows の不具合修正は保証されていませんし、リクエストするためには有償のプレミアサポートの契約レベルが必要であるため。

    ライセンス条項に付属する、品質保証規定でも、Microsoft の裁量により修正か、返金かを選ぶとされています。

    「過剰に高品質を求めることが悪い」と言われれば、「顧客が求めているので、対応するのが当然」ということになります。

    たぶん、この考えで行くと、日本国内でも揉める気がします。
    「過剰」なのですよね…?

    そして、そのスタンスは自分たちアプリケーション開発者の首を絞めることにつながりますが…。

    なお、Microsoft に対する同情的な内容になっていますが、私自身も何度か苦しめられています。幸い、プレミアサポートを使える職場なので、ある程度は追い込んでから、Microsoft に回避策を出してくれとか、社内の人的リソースを浪費しないようにはできていますので何とかなっている範囲ですね...。
    2017年11月9日 22:40
    モデレータ
  • 私の環境も Windows Defender 以外のセキュリティソフトは入っていない状態です。

    yoshinor さんの質問時のデベロッパーコミュニティのコメントにもありましたが、最初は改善されたのですがその後再び遅くなったので制御フローガードの設定は解除しています。

    設定は、全体ではなく特定のプログラムに対して実行していました。

    2017年11月30日 2:51
  • gizmolabs さん、ご連絡ありがとうございます。

    カスペルスキーが入っているPCでも発生したので、おそらくセキュリティソフトは無関係と思われます。

    デベロッパーコミュニティのコメントを見ると、11/30 にWindows Update で配信された KB4051963 を適用すると
    改善されたとの報告があがっています。
    私の環境では、KB4051963 適用後も依然として改善されませんが、gizmolabs さんの環境ではいかがでしょうか?

    2017年12月1日 13:50
  • 1カ月経ってもマイクロソフトが一向に対処しようとしないため、自力で修正する方法を調べました。
    調べた結果、分かったことをご報告します。

    CMFCToolBarImages::UpdateInternalImage() で m_hbmImageShadow を生成する処理に非常に長い時間がかかることが原因ですが、そもそも32ビットBMP または PNGのときは、表示処理に m_hbmImageShadow を全く使っていないことが判明しました。
    そこで、m_hbmImageShadow を生成しないようにするため、以下の対処を行うことで、リボン切り替え時間およびアプリ起動時間を短縮することができました。

    1. CMFCToolBarImages をa)~f) の手順で必要な数だけあらかじめ生成しておく。

     a) LoadStr()でリソースから画像を読み込む。
     b) SetImageSize() でイメージの大きさを指定。
     c) afxGlobalData.m_nBitsPerPixel を一時的に0に変更。
     d) 画面DPIが100%以外のときは、SmoothResize()で画像を拡大。(拡大率はafxGlobalData.GetRibbonImageScale()で取得)
     e) SetTransparentColor(afxGlobalData.clrBtnFace) を呼び出す。
     f) afxGlobalData.m_nBitsPerPixel の値を元に戻す。


    2. CMFCRibbonCategory や CMFCRibbonGallery を生成するとき、リソース画像のIDを指定せず、その代わりに1で生成した CMFCToolBarImagesをコピーして使うようにする。


    グローバル変数の値を強引にかえるためあまりよくない対処法ですが、m_hbmImageShadowを全く生成せずに済むため、リボン切り替え時間だけでなく、アプリ起動時間も短縮することが可能です。

    なお、この方法はリボンをソースコードに記述する場合の対処法になります。

    リソース上でリボンを記述する場合は、リソース上で画像のIDを指定せず、LoadResource() 実行後に1.の方法で生成したCMFCToolBarImagesを追加する必要があります。

    ただし、アプリ起動中に afxGlobalData.clrBtnFace が変わる場合は、リボン切り替え時に m_hbmImageShadow が生成されてしまうため、切り替えに時間がかかってしまいます。

    ※ VS2017 をお使いの場合、afxGlobalData に直接アクセスせず、GetGlobalData() 経由でのアクセスを推奨します。

    この方法はあくまでもアプリを使っている顧客からの苦情に対応するための緊急避難的な方法です。
    マイクロソフトにはこの不具合に対する迅速かつ抜本的対処を強く求めます。
    (ちなみに フィードバックHub にも投稿しましたが、残念ながら全く対処する兆しがありません。)

    2017年12月1日 15:08
  • ようやく、マイクロソフトが「Windows 10 Fall Creators Update 環境で GetPixel および SetPixel 関数の処理速度が、Windows 10 Creators Update 以前の Windows 10 の処理速度と比較し、遅くなる」 ことを認めました。
    詳しくは、以下の記事をご覧ください。
    https://blogs.msdn.microsoft.com/japan_platform_sdkwindows_sdk_support_team_blog/2017/12/08/fcu_getpixel/
    マイクロソフトには、迅速かつ抜本的な対処をお願いします。
    2017年12月8日 10:49
  • ブログへの掲載は、どなたかが有償サポートなどで問い合わせた結果でしょうね。

    不具合修正に際しては、ビジネスインパクト(それが修正されないことによる被害)とサイドエフェクト(修正することによる影響)を勘案して Microsoft の裁量で決めるわけです。
    ここで、「迅速かつ抜本的な対処をお願いします」と書いても、それらのパラメーターに影響を与えないので、残念ながら効果はありません。

    参考: Hotfixリクエストが承認される基準

    営利活動をされている中で、本気で動かしたい思っているなら有償サポートを使うことです。

    -----
    セキュリティ強化か何か、Windows の改良として必要だったのであれば、その狙いと互換性の両立させるための策を探すために時間はかかるでしょうね。

    2017年12月8日 13:58
    モデレータ
  • Azulean さん、コメントありがとうございます。

    個人的には、以前投稿したとおり、ある程度自力で回避することができたので、今回の不具合については、急いで対処してもらわなくても問題ありません。ただ、Developer Community でもかなり票数が集まってきているので、マイクロソフトもさすがに無視するわけにはいかないと判断されたのではないでしょうか。多くのユーザーが困っているので、マイクロソフトにはこの不具合を放置せず対処されることを期待します。

    ブログの記事によると、GetPixel()/SetPixel() が数倍~十数倍遅くなるということなので、「セキュリティ強化で遅くなった」としても理由として正当化できないと思います。1.5倍~2倍程度遅くなるのであれば、ある程度仕方ありませんが、急に十数倍も遅くなったらセキュリティ強化が理由だとしてもほとんどのユーザーは納得しないでしょう。アプリの起動に今まで10秒かかっていたとして、急に100秒かかるようになったら、アプリの不具合を疑うのではないでしょうか。

    なお、「有償サポート」 の件について、マイクロソフトのサポート体制がそのようになっているということは承知しますが、「不具合を直して欲しかったら金を払え」 というのには全く同意できないので、個人的には今後も使わないでしょう。

    もちろん、マイクロソフトのリソースにも限りがあるので、不具合をすべて対処できるわけがないことは理解しています。マイクロソフトが不具合を認めた上で、「対処しない」と明言してもらえるのであれば、それで構いません。お金を払うことで、優先して不具合を対処してもらうというのであれば、それはありだと思います。 (誤解があると困るので補足しておくと、あくまでもマイクロソフトが原因の不具合の話です。 当然のことながら、アプリのソースコードに問題がある場合は開発者の責任です。)

    この点については、いくら議論しても私の考えは変わらないと思います。

    2017年12月9日 2:03
  • 「Microsoft をどうにも制御できない」という前提に立ったときに、ビジネスとしての開発に携わる者としての1意見です。
    不具合がないことがベストであり、速やかに修正されることがベターであることは否定しません。
    ただ、それは、近年のラピッドリリース体制ではなしえない幻に過ぎないと捉えてはいます、個人的には。

    アプリの起動に今まで10秒かかっていたとして、急に100秒かかるようになったら、アプリの不具合を疑うのではないでしょうか。

    そうでしょうね。
    なので、かのブログ記事のように Microsoft のエビデンス(証拠)を出してもらって、それを元に、自分たちも被害者であることを伝えつつ、顧客からの信用毀損などのダメージを減らそうと考えているところはあると思います。
    いくら、自分たちの調査の結果、Windows の不具合だとわかっても、エビデンスがないと弱いですからね。

    なお、「有償サポート」 の件について、マイクロソフトのサポート体制がそのようになっているということは承知しますが、「不具合を直して欲しかったら金を払え」 というのには全く同意できないので、個人的には今後も使わないでしょう。

    別にそれはあなた方のビジネス判断なので、その決断を変えさせようという意図はありません。
    以下はその判断根拠に関して気にかかったというレベルのコメントなので、判断基準を見直す必要はないとお考えであれば、特に返信されなくて結構です。

    判断根拠が感情論や、契約・法務上保証されていない事柄(不具合を出さないべきだとか、迅速な修正があるべきだとか)であるならば、ビジネスとして危ういと思えます。
    なぜなら、それらでは Microsoft の開発プロセスを変えることがないからです。

    また、こういったものは不確実な事象=リスクとして捉えて、事前に軽減策を採るか、発生時の対策を想定しておくべき事例だと考えています。
    軽減策としては前述したように Insider Preview で触っていくこと、発生時の対策としては有償サポートでエビデンスを出させつつ、プレミアサポートが許されるなら回避策の提案も受けることで、Microsoft に責任を分散して自分たち(ベンダー)の信用度を下げないようにしつつ、裏付けのある対策を取りたいところです。

    もっとも、これも私個人のリスクマネジメント的な考えに過ぎませんので、あなた方のビジネス判断に影響を与えうるものではありません。
    ビジネスの判断に何を使うのはそれぞれの自由ですし、その結果、信頼度の低下や修正工数といった人件費などのコストがかかった、次の製品の開発スケジュールに影響を与えたとしても、その判断の結果の範囲内と言えます。

    2017年12月9日 8:37
    モデレータ
  • 弊社も、会社として問い合わせをいたしましたので、おそらく同様に問い合わせをした方は多かったと推測します。

    次のWindowsUpdateで対応予定との内容も早くから回答を獲ましたが、社として独自に対応も必要と思っていたため別途対処の実現方法を模索しました。

    弊社の場合は、結果として社内対応とマイクロソフト社の対応が同時期であったため事なきを得ましたが、yoshinorさんのおっしゃる不具合の内容は、そもそもこちらで問い合わせる内容ではないかと。ここはユーザー同士の議論の場所です。そこにマイクロソフトが関知することはないと思います。モデレーターの方がいらっしゃるのも、あくまでも、フォーラム運営をサポートするためです。

    やり場の無い怒り、という点ではご心労に配慮いたしますが、同様にマイクロソフト側も対応に苦慮した点があるのであろうことをご理解いただければと思います。

    2018年3月16日 5:03