「応答なし」の正体 ── Windowsがアプリを「固まった」と判定する仕組みと、固まらない設計

· · Windows, Windows開発, 不具合調査, マルチスレッド, WinForms, WPF, Win32 API, UI設計

「処理中にアプリが白くなって(応答なし)と出る」「たまに固まるという問い合わせが来るが、開発機では再現しない」── Windowsの業務アプリで最も多い苦情のひとつが、この「応答なし」です。そして意外に知られていないのが、「応答なし」という表示を出しているのは固まったアプリ自身ではなく、OSであることです。

Windowsは、アプリが「固まった」ことをどうやって知るのか。白くかすんだあのウィンドウは何者なのか。この記事では、Windowsで業務アプリを作る開発者と、固まるアプリの問い合わせを受ける情シス担当者を対象に、「応答なし」判定の仕組みをメッセージループの基礎から解き明かし、固まる定番原因、固まらない設計、そして固まった瞬間の調査手順までを一次情報にもとづいて整理します。

1. まず結論

  • 「応答なし」はOSの判定です。入力を待たず、起動処理中でもなく、5秒間メッセージの取り出し(PeekMessage)を行っていないウィンドウ(とその所有GUIスレッド)を、OSは応答なしとみなします。判定はプロセス単位ではありません。1
  • 白くなったウィンドウは「ゴーストウィンドウ」です。OSが元のウィンドウを隠し、同じ位置・サイズ・外観の偽物に差し替えています。できるのは移動・最小化・閉じるだけで、中身は動いていません。デバッガー接続中はゴーストウィンドウは生成されません。2
  • 固まる原因はほぼ1つに帰着します。メッセージループを回すべきUIスレッドが、重い処理や待機で塞がっていることです。同期I/O・ネットワーク呼び出し・ロック待ち・スレッド間の SendMessage が定番です。3
  • 対策の原則は「UIスレッドで待たない・計算しない」です。重い処理はワーカースレッド(C#なら async/await + Task.Run)に移し、UIスレッドは描画・進捗・キャンセル受付に専念させます。4
  • DoEvents やメッセージポンプの手動駆動は再入バグの温床です。応答なし表示は消えますが、処理の途中に任意のイベントが割り込む構造になります。回避ではなく分離が正攻法です。
  • 調査は「固まっている瞬間」の状態確保が第一です。ダンプを取ってUIスレッドのスタックを見れば、何を待って止まっているかはほぼ特定できます。

2. 前提: Windowsアプリはメッセージで動いている

「応答なし」を理解するには、まずWindowsのGUIアプリがイベント駆動であることを押さえる必要があります。GUIアプリは自分から入力を取りに行くのではなく、OSが届けるメッセージ(マウス、キーボード、再描画要求、タイマーなど)を受け取って動きます。3

ウィンドウを作った各スレッドはメッセージキューを持ち、次のようなメッセージループを回します。

MSG msg;
while (GetMessage(&msg, NULL, 0, 0) > 0) {
    TranslateMessage(&msg);
    DispatchMessage(&msg);   // ウィンドウプロシージャが呼ばれる
}

GetMessage でキューからメッセージを取り出し、DispatchMessage がそのウィンドウのウィンドウプロシージャ(メッセージ処理関数)を呼ぶ。ボタンのクリック処理も、再描画も、WinFormsやWPFのイベントハンドラーも、突き詰めればすべてこのループの1回転の中で実行されています。5

メッセージループの基本構造OSがマウスやキーボードなどの入力をスレッドのメッセージキューに入れ、UIスレッドのループがGetMessageで取り出してDispatchMessageでウィンドウプロシージャを呼び、処理が終わるとループの先頭に戻るOS(入力・再描画要求・タイマー)スレッドのメッセージキューGetMessageで取り出すDispatchMessageウィンドウプロシージャで処理

図1: GUIアプリの心臓部はメッセージループで、イベント処理はすべてこのループの1回転として実行される。

この構造の重要な帰結がひとつあります。ウィンドウプロシージャ(イベントハンドラー)の中で時間のかかる処理をすると、その間ループは次のメッセージを取り出せないということです。クリックにも再描画要求にも反応できなくなる ── これが「固まる」の正体です。

メッセージの届き方には2経路あることも押さえておきます。PostMessageキューに積んですぐ戻り、ループが順に取り出して処理します。一方 SendMessage はウィンドウプロシージャを直接呼び出し、処理が完了するまで呼び出し元に戻りません36 この違いは4章のデッドロックの話にそのまま効いてきます。

メッセージの2つの配送経路PostMessageはキューに積んですぐ戻り、メッセージループが順に取り出して処理する。SendMessageはウィンドウプロシージャを直接呼び出し、処理が完了するまで呼び出し元に戻らないPostMessageキューに積む(すぐ戻る)ループが順に取り出して処理SendMessageプロシージャを直接呼ぶ処理完了まで戻らない

図2: 同じ「メッセージを送る」でも、キュー経由のPostと完了を待つSendでは性質がまったく違う。

3. 「応答なし」判定の仕組み ── 5秒ルールとゴーストウィンドウ

では、OSはどうやって「このアプリは固まった」と知るのでしょうか。判定基準は公式に文書化されています。入力を待っておらず、起動処理中でもなく、5秒間 PeekMessage(メッセージの取り出し)を呼んでいないウィンドウを、OSは応答なしとみなします。1 つまりOSは「メッセージループがちゃんと回転しているか」を脈拍のように見ていて、5秒間脈がなければ応答なしと判定するわけです(この5秒という値は将来変わりうると明記されています)。判定の単位はウィンドウとその所有GUIスレッドで、複数のUIスレッドを持つアプリでは、1つが固まっても別スレッドのウィンドウは生きていることがあります。ダンプで見るべきは固まったウィンドウの所有スレッドです。

判定されたトップレベルウィンドウに起きることも文書化されています。OSは元のウィンドウを非表示にし、同じZオーダー・位置・サイズ・外観を持つ「ゴーストウィンドウ(ghost window)」に差し替えます。ユーザーがそれに対してできるのは移動・サイズ変更・(強制)クローズだけです。中身のアプリは実際には応答していないので、それ以外の操作はできません。2

応答なし判定とゴーストウィンドウ差し替えの流れUIスレッドが重い処理で塞がりメッセージの取り出しが5秒止まると、OSが応答なしと判定して元のウィンドウを隠し、同じ見た目のゴーストウィンドウに差し替え、ユーザーには移動・最小化・閉じる操作だけを提供するいいえはいUIスレッドが重い処理で塞がるメッセージ取り出しが止まる5秒経過?ゴーストウィンドウに差し替えタイトルに(応答なし)表示白くかすむ・移動と閉じるのみ可

図3: 「応答なし」の表示も白い画面も、固まったアプリではなくOSが差し替えたゴーストウィンドウのもの。

タイトルバーに付く「(応答なし)」の文字列も、Aeroテーマで白くかすむ見た目も、すべてこのゴーストウィンドウのものです。ここから2つの実務的な帰結が導けます。

  • 「応答なし」と表示された時点で、そのウィンドウの所有スレッドは少なくとも5秒間メッセージを処理していません。「表示が出るのが早すぎる」のではなく、UIスレッドが確実に塞がっています。
  • デバッガーを接続しているとゴーストウィンドウは生成されません。2 「デバッグ実行だと応答なしにならないのに、リリースだと出る」ように見える場合、固まり方は同じで表示だけが違う、ということがあります。

なお、プロセス単位でこの差し替えを無効化する DisableProcessWindowsGhosting というAPIも存在します。7 キオスク端末など「OSに勝手にウィンドウを操作可能に見せてほしくない」特殊な場面のためのもので、呼べば「応答なし」表示は出なくなりますが、固まっている事実は変わりません。一般のアプリが応答なし対策として使うものではない、と理解してください。

4. なぜ固まるのか ── UIスレッドを塞ぐ定番パターン

原因は突き詰めれば「UIスレッドがメッセージループに戻ってこない」の一点ですが、実務で出会う形はいくつかの定番に分類できます。

UIスレッドを塞ぐ定番原因の分類同期I/Oとネットワーク呼び出し、ロック待ち、スレッド間SendMessage、COMのSTA絡みという4系統の定番原因は、いずれもUIスレッドがメッセージループに戻れないという同じ一点に帰着する同期I/O・ネットワーク呼び出しUIスレッドがループに戻れないロック待ちスレッド間SendMessageCOMのSTA絡み応答なし判定へ

図4: 見た目の症状は同じでも、塞いでいる犯人は4系統に分類でき、それぞれ対策が異なる。

同期I/Oとネットワーク呼び出し。最多はこれです。ボタンのクリックハンドラーの中で、大きなファイルの読み書き、データベースクエリ、Web APIの呼び出し、ネットワークドライブ上のファイルアクセスを同期で行うパターン。開発機ではコンマ数秒で終わるため気づかず、本番のネットワーク遅延やファイルサーバーの不調で数十秒待ちになり、「たまに固まる」という問い合わせになります。ネットワークドライブは接続断時のタイムアウトが長く、症状を劇的に悪化させます。

ロック待ち。UIスレッドがワーカースレッドと共有するデータのロックを取ろうとして、そのロックを長時間握るワーカーを待ってしまうパターン。ロックの規律についてはマルチスレッド実務シリーズで詳しく扱っています。

スレッド間の SendMessageSendMessage は、宛先ウィンドウのプロシージャが処理を終えるまで戻りません6 別スレッドのウィンドウに送った場合、そのスレッドがメッセージを処理できる状態になるまで送信側は待たされます。ここで宛先スレッドも何かを待っていると、互いに待ち合うメッセージデッドロックが成立します。3 特に HWND_BROADCAST への送信は、応答しないウィンドウが1枚あるだけで巻き込まれます。待てない場面では SendMessageTimeout や、応答を待たない PostMessage を検討します。8

スレッド間SendMessageによるデッドロックUIスレッドがワーカースレッドの結果待ちでブロックしているところに、ワーカースレッドがUIスレッドのウィンドウへSendMessageを送ると、互いに相手の完了を待ち合ってデッドロックになるワーカースレッドUIスレッドワーカースレッドUIスレッドメッセージを処理できない(待機中)SendMessageから戻れない互いに待ち合いデッドロックワーカーの完了を待機(ブロック)SendMessage(処理完了まで戻らない)

図5: 「UIスレッドがワーカーを待ち、ワーカーがSendMessageでUIスレッドを待つ」は定番のデッドロック。

COMのアパートメント絡み。STAオブジェクトへの呼び出しはウィンドウメッセージとして配送されるため、UIスレッド(STA)が塞がると、他スレッドからのCOM呼び出しも巻き添えでブロックします。この構造はCOM STA/MTAの記事で解説しています。

「一瞬だから」の積み重ね。1回50msの同期処理でも、ループで100回呼べば5秒です。応答なしの閾値は5秒ですが、体感の「もっさり」は100ms程度から始まります。設計の目安は「UIスレッドを塞いでよいのはミリ秒単位まで」です。

5. 固まらない設計 ── 重い処理をUIスレッドから追い出す

対策の原則はひとつ、時間のかかる仕事をUIスレッドから追い出すことです。C#(WinForms/WPF)なら async/await が最短の正攻法です。

private async void RunButton_Click(object sender, EventArgs e)
{
    runButton.Enabled = false;
    try
    {
        // CPU負荷の高い処理・同期しかないAPIはTask.Runでワーカーへ
        var result = await Task.Run(() => HeavyCalculation(input));

        // I/OはネイティブにasyncなAPIを使う(スレッドも消費しない)
        var data = await httpClient.GetStringAsync(url);

        // awaitの後はUIスレッドに戻っているので、コントロールを直接触れる
        resultLabel.Text = result + data.Length.ToString();
    }
    catch (Exception ex)
    {
        // async voidハンドラーから例外を漏らすとアプリが落ちる。ここで受け止める
        MessageBox.Show($"処理に失敗しました: {ex.Message}");
    }
    finally
    {
        runButton.Enabled = true;
    }
}

ポイントは3つあります。第一に、await の待機中、UIスレッドはメッセージループに戻っているので応答なしになりません。第二に、await の継続はUIスレッドに戻ってくるため、後続でコントロールを普通に触れます(ワーカースレッドからコントロールを直接触るのは禁止で、必要なら Control.Invoke / Dispatcher.InvokeAsync を使います)。4 第三に、実行中はボタンを無効化するなどして再入を設計で殺すことです。

Win32ネイティブの場合も構図は同じで、ワーカースレッドに仕事を渡し、完了を PostMessage で自作メッセージとしてUIスレッドに通知し、ウィンドウプロシージャで画面を更新します。PostMessage はキューに積むだけですぐ戻るため、ワーカー側がブロックすることもありません。6 ワーカースレッドの待ち合わせ自体は、条件変数の記事で扱った規律で書きます。

固まらないアプリの役割分担UIスレッドは入力受付・進捗表示・キャンセル受付だけを担当し、重い処理はワーカースレッドが実行して、完了をPostMessageやawaitの継続でUIスレッドに返す仕事を渡すPostMessage / awaitの継続UIスレッド:入力・進捗・キャンセルワーカースレッド:重い処理UIスレッドでの同期I/O・長い計算は禁止

図6: UIスレッドは「受付係」に徹し、重い仕事は必ずワーカーに渡して完了通知だけ受け取る。

避けたいのが、重い処理の合間に Application.DoEvents()PeekMessage ループを差し込んで表示だけ生かす手法です。応答なしは回避できますが、処理の途中で任意のイベントハンドラーが再入します。ボタンの二度押し、処理中のフォームクローズ、タイマーの発火 ── どれも処理中のデータを壊しうるうえ、タイミング依存で再現しにくいバグになります。メッセージポンプを手で回すのは、モーダルな進捗ダイアログのような限定された構造の中だけにとどめ、原則は分離で解決してください。

DoEventsによる再入バグの時系列重い処理の途中でDoEventsを呼ぶと溜まっていたクリックのイベントハンドラーが割り込んで実行され、処理中のデータを書き換えてから元の処理が再開するため、タイミング依存のデータ破壊が起きるUIスレッドUIスレッドボタン再クリックのハンドラーが割り込む重い処理を開始(データ加工中)DoEvents(溜まったメッセージを処理)割り込み処理がデータを書き換え元の処理が再開(データは既に不整合)

図7: DoEventsは「応答なし」を消す代わりに、処理の真ん中へ任意のイベントを招き入れる。

長時間処理には進捗表示とキャンセルも設計に含めます。IProgress<T> で進捗をUIに送り、CancellationToken で中断を伝える形にしておくと、ユーザーは「動いている」ことが分かり、強制終了(それはしばしばデータ破損の原因になります)に手を伸ばさなくなります。

長時間処理の進捗とキャンセルの流れワーカースレッドはIProgress経由で進捗をUIスレッドに送り、UIのキャンセル操作はCancellationTokenを通じてワーカーに伝わり、ワーカーは区切りのよい箇所で中断して後始末するIProgressで進捗CancellationTokenワーカー:長時間処理UI:進捗表示と中止ボタン区切りで中断して後始末

図8: 進捗は「ワーカー→UI」、キャンセルは「UI→ワーカー」。双方向の細い連絡路を最初から設計に含める。

6. 固まった瞬間の調べ方

「たまに固まる」の調査で最も価値があるのは、固まっているまさにその瞬間のスレッド状態です。再起動してしまうと証拠は消えます。

ダンプを取る。タスクマネージャーの詳細タブで対象プロセスを右クリック→「ダンプ ファイルの作成」。これだけで全スレッドのスタックが入った完全ダンプが取れます。問い合わせを受ける情シス側に「固まったら閉じずにこれを取ってほしい」と伝えておくだけで、調査の成功率は大きく変わります。取得の仕組みづくりはクラッシュダンプ収集の記事を参照してください。

UIスレッドのスタックを見る。WinDbgでダンプを開き、メッセージループを回しているスレッド(通常はスレッド0)のスタックを見ます。同期I/Oなら ReadFile やネットワークAPI、ロック待ちなら WaitFor… 系、スレッド間 SendMessage なら SendMessage の内部で待つ姿が、そのまま写っています。読み方はWinDbg入門記事で解説しています。

生きたまま見る。Process Explorerならスレッド一覧とスタックをその場で確認できます。定常的にもっさりする場合は、WPRでトレースを取ってUIスレッドの待ちを時系列で分析します(WPR/WPA実践)。

応答なし調査の基本手順固まっている瞬間にダンプを取り、UIスレッドのスタックを見て、同期I/O・ロック待ち・スレッド間SendMessageのどれで止まっているかを特定し、該当する設計修正につなげる固まっている瞬間ダンプを取る(閉じる前に)UIスレッドのスタックを見る同期I/O・ネットワーク待ちロック待ちスレッド間SendMessage該当箇所をワーカーへ分離

図9: 調査の主役は「固まっている瞬間のダンプ」で、UIスレッドのスタックがそのまま原因の分類になる。

症状からの当たりの付け方も定番化できます。特定操作で必ず固まるなら、そのハンドラー内の同期I/Oをまず疑う。まれに固まり操作と相関がないなら、ロック順序やスレッド間 SendMessage のデッドロックを疑い、ダンプで両スレッドの待ち先を突き合わせる。特定環境でだけ固まるなら、ネットワークドライブ・プロキシ・ウイルス対策ソフトなど環境要因のタイムアウトを疑う、という流れです。

7. まとめ

  • 「応答なし」は、5秒間メッセージを取り出さないアプリをOSが判定し、ゴーストウィンドウに差し替える仕組み。表示を出しているのはアプリではなくOS。
  • 固まる原因は「UIスレッドがメッセージループに戻れない」の一点。同期I/O・ネットワーク・ロック待ち・スレッド間SendMessageが定番。
  • 対策はUIスレッドから重い処理を追い出すこと。C#なら async/await + Task.Run、Win32ならワーカースレッド+ PostMessage。実行中の再入はボタン無効化などの設計で防ぐ。
  • DoEvents による回避は再入バグと引き換え。DisableProcessWindowsGhosting は表示を消すだけ。どちらも根本対策ではない。
  • 調査は「固まっている瞬間」のダンプが最重要。UIスレッドのスタックに原因はほぼそのまま写っている。

「応答なし」は、ユーザーから見れば「壊れた」ですが、仕組みを知っていれば「UIスレッドが5秒戻ってこなかった」という正確な一文に翻訳できます。その一文から逆算すれば、原因の候補も、直し方も、調査の手順も自然に決まります。

関連記事

関連する相談領域

合同会社小村ソフトでは、「たまに固まる」「応答なしになる」業務アプリの原因調査(ダンプ解析・トレース分析)、同期処理だらけのレガシーUIコードのasync/await化・ワーカースレッド分離の改修、フリーズしないUI設計のレビューを扱っています。再現手順が不明な段階からでも、証拠の取り方の設計からお手伝いできます。

参考リンク

  1. Microsoft Learn, IsHungAppWindow function (winuser.h). アプリが「入力を待っておらず、起動処理中でもなく、内部タイムアウトである5秒の間PeekMessageを呼んでいない」場合に応答なしとみなされるという判定基準、この5秒という基準は変更されうること、ゴーストウィンドウに対しては常にTRUEが返ることについて。  2

  2. Microsoft Learn, GetMessage function (winuser.h). トップレベルウィンドウが数秒間メッセージに応答しなくなると、システムがそのウィンドウを応答なしとみなし、同じZオーダー・位置・サイズ・外観を持つゴーストウィンドウに差し替えること、ユーザーは移動・サイズ変更・クローズだけができること、デバッガー接続中はゴーストウィンドウが生成されないことについて。  2 3

  3. Microsoft Learn, About Messages and Message Queues. Windowsアプリがイベント駆動であり、ウィンドウプロシージャがメッセージを処理する構造、キュー経由のメッセージと直接送信されるメッセージの区別、応答なしウィンドウのゴーストウィンドウへの差し替え、スレッド間でメッセージを送り合うことによるデッドロックの節について。  2 3 4

  4. Microsoft Learn, How to make thread-safe calls to controls (Windows Forms). WinFormsのコントロールが作成されたスレッド以外から安全に触れないこと、他スレッドからの更新にはInvoke/BeginInvokeを使うこと、async/awaitやBackgroundWorkerを使った安全な非同期パターンについて。  2

  5. Microsoft Learn, Using Messages and Message Queues. GetMessage・TranslateMessage・DispatchMessageによる標準的なメッセージループの実装例と、メッセージキューの調査方法について。 

  6. Microsoft Learn, SendMessage function (winuser.h). SendMessageが指定ウィンドウのウィンドウプロシージャを呼び出し、処理が完了するまで戻らないこと、別スレッドのウィンドウへの送信では相手スレッドがメッセージを処理するまで待たされること、応答を待たずキューに積むPostMessageとの違いについて。  2 3

  7. Microsoft Learn, DisableProcessWindowsGhosting function (winuser.h). 呼び出したGUIプロセスについて、応答なしウィンドウを最小化・移動・クローズ可能にするゴーストウィンドウ機能を無効化できること、無効化はプロセスの生存期間中続くことについて。 

  8. Microsoft Learn, SendMessageTimeout function (winuser.h). タイムアウト付きでメッセージを送信できること、応答しないウィンドウ(ハング判定されたウィンドウ)に対して待たずに戻るフラグ(SMTO_ABORTIFHUNG)が用意されていることについて。 

同じタグを共有する最新の記事です。さらに近い話題で知識を深められます。

このテーマと近いトピックページです。記事を起点に、関連するサービスや他の記事へ進めます。

この記事は次のサービスページにつながります。近い入口からご覧ください。

よくある質問

この記事のテーマについて、相談時によくある質問をまとめています。

「応答なし」はどういう条件で表示されるのですか?
OSは、ウィンドウを持つアプリが「入力を待っておらず、起動処理中でもなく、5秒間メッセージの取り出し(PeekMessage)を行っていない」とき、そのウィンドウを応答なしと判定します。判定されたトップレベルウィンドウは非表示にされ、同じ位置・サイズ・外観の「ゴーストウィンドウ」に差し替えられます。タイトルバーの「(応答なし)」表示や白くかすむ見た目はこのゴーストウィンドウのもので、移動・最小化・閉じる操作だけができます。つまり「応答なし」はアプリ自身の表示ではなく、OSが肩代わりして出している画面です。
処理中に「応答なし」と表示されないようにする設定はありますか?
DisableProcessWindowsGhostingを呼ぶと、そのプロセスに対するゴーストウィンドウへの差し替えを無効化できます。ただしこれは「固まっていることをユーザーから見えにくくする」だけで、ウィンドウが操作に反応しない事実は変わらず、ユーザーには移動も閉じることもできない完全な固まり方として見えます。根本対策は表示の抑止ではなく、UIスレッドを5秒どころか0.1秒単位でも塞がないよう、重い処理をワーカースレッドに移すことです。なおデバッガー接続中はOSがゴーストウィンドウを生成しないため、「デバッグ中は応答なしにならない」ように見える点にも注意してください。
DoEvents(メッセージポンプの手動駆動)で応答なしを回避してもよいですか?
推奨しません。重い処理の途中でDoEventsやPeekMessageループを回すと、応答なし判定は回避できますが、処理の途中でボタンの再クリック・ウィンドウを閉じる操作・タイマーなど任意のイベントハンドラーが再入してきます。処理中のデータを別のハンドラーが書き換える、閉じたはずのフォームに触って例外になる、といった再入バグはタイミング依存で再現しにくく、応答なしより厄介です。正攻法は処理そのものをTask.Runなどでワーカースレッドに移し、UIスレッドは進捗表示とキャンセル受付だけを担当する形にすることです。
ワーカースレッドから画面(コントロール)を更新するにはどうすればよいですか?
WinFormsのコントロールやWPFの要素は、作成したスレッド(通常はUIスレッド)からしか触れません。ワーカースレッドから直接触ると例外や不定動作になります。C#ならasync/awaitを使うのが最も簡単で、awaitの継続は呼び出し元のUIスレッドに戻ってくるため、awaitの後で普通にコントロールを更新できます。明示的に切り替える場合はWinFormsではControl.Invoke/BeginInvoke、WPFではDispatcher.InvokeAsyncを使います。Win32ネイティブでは、ワーカースレッドからPostMessageで自作の完了メッセージをUIスレッドに送り、ウィンドウプロシージャ側で画面を更新するのが定石です。
「応答なし」になっているアプリの原因はどう調べればよいですか?
固まっている「その瞬間」に状態を取るのが重要です。まずタスクマネージャーの詳細タブから「ダンプファイルの作成」で完全ダンプを取り、WinDbgでUIスレッド(メッセージループを回しているスレッド)のスタックを見ます。同期I/O・ネットワーク待ち・ロック待ち・SendMessageによる他スレッド待ちのどれで止まっているかはスタックにそのまま現れます。生きた状態で見るならProcess Explorerのスレッド一覧とスタック表示、時系列で追うならWPRでのトレース採取が有効です。当サイトのWinDbg入門・Process Explorer実践・WPR/WPA実践の各記事も参考にしてください。

著者プロフィール

記事の著者プロフィールページです。

小村 豪

合同会社小村ソフト 代表

Windows ソフト開発、技術相談、不具合調査を中心に、既存資産が残る案件や原因が見えにくい障害調査に強みがあります。

ブログ一覧に戻る