Vista, conime.exe, 消せないフォルダ

(2010年1月24日追記)『KB97509: Windows Server 2008 および Windows Vista でコンソール アプリケーションを起動すると、コンソール アプリケーションが配置してあるフォルダーが削除できない』もご覧下さい(追記終わり)
昨日のカレントディレクトリの話 (id:NyaRuRu:20070808:p2) ですが,あれから少し調べてみると,Windows Vista で conime.exe の挙動が変わったらしいという話を見つけました.日付は今年の 3 月です.気づいている人は気づいていたという感じですねぇ.

http://pc11.2ch.net/test/read.cgi/tech/1171721448/503-573
Win32API質問箱 Build50

503 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/05(月) 23:00:39
    >>495
    APIの質問ではなくスレ違いで申し訳ないんですが、お教えください。
    残っているスレッドをどのようにして知ることができるのでしょうか?
    
    現在、以下のようなトラブルで悩んでおります。
    発生条件がまだ絞り込めてないのですが、Vistaでexplorerからディレクトリを削除するときに
    「他のプロセスで使用中のため削除できません」(みたいな意味の)エラーで削除できない場合が
    あります。そのディレクトリは自分のプログラムでOpenFileDialogでファイルを開いたディレクトリ
    なのですが、タスクマネージャのプロセスタブで見る限りプログラムは終了しています。
    スレッドだけが(問題のディレクトリをカレントにして)いつまでも残っているなんてことがあるのか
    疑問なんですが、残っているスレッドが確認できればこれが確認できるかと。
    
    よろしくお願いいたします。

505 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/05(月) 23:10:31
    >>503
    API的な回答じゃなくていいのならProcessExplorerでさっくり見れる
    
    >スレッド
    vistaは判らないけど、それ以前のOSのことを考えれば
    スレッドは所詮プロセスの枠の中の存在だから独立することはない

507 名前: 503 [sage] 投稿日: 2007/03/05(月) 23:14:36
    >>505
    ありがとうございます。
    
    >スレッドは所詮プロセスの枠の中の存在だから独立することはない
    のはずですよね・・・・・・・

508 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/05(月) 23:20:13
    >>507
    UnLockerで、捕まえてるプロセス名を調べてみ?
    http://ccollomb.free.fr/unlocker/

509 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/05(月) 23:23:07
    >>503
    OpenFileDialogでファイル名を取ってきたあと、
    何もしない場合でもその症状?
    
    それとも、特定の処理(ファイル読み込みなど)後で、
    その症状?
    
    切り離して考えてみ?


538 名前: 503 [sage] 投稿日: 2007/03/06(火) 17:24:28
    >>505 >>508 >>509
    おかげさまで原因が特定できました。>>509の書かれたとおりOpenFileDialog
    が原因ではなく、その後の処理に起因するものでした。
    
    結論だけ書くと・・・
    消せないディレクトリをカレントにしてconime.exeが動きっぱなしになっているようです。
    
    詳細に書くと・・・・
    今回問題となっているプログラム(Prog1.exeとする)は、OpenFileDialogでユ
    ーザーが指定したファイルを処理するために、指定したファイルのあるディレ
    クトリをカレントにしてProg2.exeをCreateProcessします。Prog2.exeはコン
    ソールプログラム(SW_HIDEでDOS窓は表示されず、STARTF_USESTDHANDLESで出
    力をパイプ経由でProg1が受け取るのでユーザーに目には触れない)のため、こ
    れが起動されたとき、conime.exeが(まだ起動してなければ)起動されます。そ
    して、Prog2.exe/Prog1.exe終了後もconime.exeは終了せずに残り、以降に起
    動されたコンソールプログラムで使いまわされるようです。
    つまり、
    (1) ログイン後初めて実行されるコンソールプログラムを親としてconime.exeが起動する。
    (2) (1)の親プログラム終了後もconime.exeは終了しない。
    (3) 2つめ以降のコンソールプログラムはこのcomime.exeを使用する。
    という動作をし、これはXPでもVistaでも同じようです。
    Vistaだけで問題が起きたのは、
    XP:conime.exeは親に関係なくC:\Windows\System32をカレントにして起動される
    Vista:comime.exeは(1)の親のカレントをカレントとして起動され、その後移動しない
    の違いがあるためです。
    Vista環境でProg1->Prog2が最初のコンソールプログラムの場合、ユーザーの
    指定したファイルのディレクトリにconimeが居座るためこのディレクトリが削
    除できなくなっているわけです。
    
    「Vistaの問題だ!」と言いたいところだが、さてどう対策したものか・・・・・・
    Prog1起動時に、C:\でもカレントにしてダミーのコンソールプログラムを動かしとくかなあ(涙)

539 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 17:42:11
    >>538
    私見だけど;
    GUIアプリではカレントディレクトリを常に当たり障りのないトコに設定しとくべき。
    OpenFileDialog 等、カレントディレクトリが移動されそうな処理の後には再設定も行う。
    
    これを怠ると「なぜこのフォルダが消せない!」ということが頻発するから。

540 名前: 503 [sage] 投稿日: 2007/03/06(火) 18:01:19
    >>539
    コメントありがとうございます。
    Prog2がコンソール(CUI)アプリといところが味噌でして・・・・
    
    (これを書くと関係者が見てたら身元がバレそうだが)
    実は上記のProg2は(組み込みマイコン用のクロス)コンパイラであり、処理するファイルは
    ソースファイルなんです。
    #include 等を適切に処理するために、カレントをそれなりの場所にして起動する必要があります。

541 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 18:24:15
    なるほど。
    ダミーで cmd /c exitとか動かしておくしか手が無さそうですね。
    
    KBの↓なんかもひどい解決方法・・・
    http://support.microsoft.com/kb/903204/en-us

542 名前: 503 [sage] 投稿日: 2007/03/06(火) 18:33:45
    >>541
    >http://support.microsoft.com/kb/903204/en-us
    思わず爆笑。

543 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 18:59:41
    なんだかよくわからないけど
    Prog2のカレントディレクトリをC:\とかにして起動して
    起動後にカレントディレクトリ変えるんじゃだめなのか?
    全然見当違いなこと言ってたらすまん

544 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 19:03:00
    なるほど。
    バッチファイルを挟むという手はあるな。
    
    ・・・俺は馬鹿か

545 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 19:20:27
    試してないけど、conime.exeを先に起動しとくとかは?

546 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 19:46:01
    それが541の解決法

547 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 19:51:42
    >>540
    CreateProcessって子プロセスのカレントディレクトリをパラメータで指定できたから
    親のカレントディレクトリを移動する必要はないんじゃない?
    >>545
    それが>>541

548 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 20:01:24 ?2BP(222)
    >>545
    それが
    >http://support.microsoft.com/kb/903204/en-us
    だろ。
    
    日本語版見たらもっとひでーw
    http://support.microsoft.com/kb/899153/ja

549 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 20:10:34
    >>503
    CreateProcessでProg2を起動しているんだったら
    CREATE_NO_WINDOWフラグを入れるのは?
    
    あとは、終了時にWM_CLOSEをconime.exeに投げたり
    conime.exeをkillする手もある。

550 名前: 503 [sage] 投稿日: 2007/03/06(火) 20:45:07
    >>543-549
    コメントありがとうございます。
    (直接APIの事でないのに、こんなに盛り上がっていいのか・・・・)
    
    Prog2は他社製のため手を入れられませんが、>>544の書かれているように
    間にバッチなりコンソールアプリなりを挟んでそこでC:\→目的のディレクトリ
    を行うのはいい方法ですね。
    >>538の最後に書いたのも、>>541も>>544もconime.exeを予め問題の無いディレクトリで
    起動しとくという点では同じ考えで、あとはどれが一番美しいかですね。検討してみます。
    
    >>547
    CreateProcessでの子プロセスのカレント指定は既に使用しています。
    (conime.exeが影響されるのは子プロセスのカレント)
    親のカレントもファイルを選択した時点で同じディレクトリに移動させていますが、
    逆に親が動いている間はそのディレクトリを消されたくないので、(消極的な方法ではあり
    ますが)そのようにしています。
    
    >>548
    >http://support.microsoft.com/kb/899153/ja
    もっと大爆笑!
    
    >>549
    >CREATE_NO_WINDOWフラグを入れるのは?
    で、conime.exeが起動されなければ一番よさそうですね。試してみます。
    
    >あとは、終了時にWM_CLOSEをconime.exeに投げたり
    >conime.exeをkillする手もある。
    実際にProcessExplorerからconime.exeをKillしてみると(当然のことながら)ディレクトリ
    を削除できるようになりました。ただ前にも書いたように一つのconime.exeが全ての
    コンソールアプリで使いまわされているようなので、この時に他のコンソールアプリが
    動いている可能性を考えると、この手は使えません。
    
551 名前: 503 [sage] 投稿日: 2007/03/06(火) 21:44:28
    >>549
    >>CREATE_NO_WINDOWフラグを入れるのは?
    >で、conime.exeが起動されなければ一番よさそうですね。試してみます。
    
    とりあえずXP環境で確認したところ、CREATE_NO_WINDOWでconime.exeは起動されなくなるようです。
    Vistaは明日確認。これでOKなら万事解決!感謝!
    
    このスレに最もふさわしい解決方法ですね。
    (言い訳しとくと、このプログラムの初版は1998年。当時CREATE_NO_WINDOWなんて無かった・・・)

552 名前: 503 [sage] 投稿日: 2007/03/06(火) 22:27:06
    余談だが、VisualStudio6のIDEでビルドを行った時もconime.exeが起動され、IDE終了後も残る。
    VistaにVS6入れる人なんてほとんどいないと思うが、プロジェクトのディレクトリが
    削除できなくなるんだろうなあ。

553 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 22:32:35
    DETACHED_PROCESSでもコンソールウィンドウは表示されなくなるが、
    CREATE_NO_WINDOWとは何が違うのだろう。(conimeについては未確認。)

554 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/06(火) 23:15:11
    Vista に 6.0 入れてるよ俺…
    明日試してみるか orz

555 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/07(水) 04:58:35
    デュアルブートしてるXPにインストールしたVC6のコンパイラだけ借りてる

556 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/07(水) 09:10:10
    コンパイラを使っている方のOSは何

557 名前: 503 [sage] 投稿日: 2007/03/07(水) 13:36:06
    Vista環境で、CREATE_NO_WINDOWによりconime.exeが起動されなくなり、ディレクトリが消せなく
    なる問題が解決することを確認できました。
    また、>>538の状況やCREATE_NO_WINDOWでの対策が有効なことは、Vista-x64のWOW64
    環境下でも同じであることを確認しました。
    万事解決。皆様に感謝。

    >>552がデマだったらまずいんで自分でも確認してみたら、やはりVista環境でログイン後の最初に
    VS6-IDEからビルドを行ったプロジェクトのディレクトリは削除できなくなりました。

565 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:13:13
    CreateProcessのCREATE_NO_WINDOWフラグって
    VC7でないと使えない?
    MSDNの2000年版にすらそのフラグは存在してないんだが。

566 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:14:42
    自分で定義すりゃ何ででも使える

567 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:15:18
    以前は非公開だったってだけだな

568 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:15:31
    そっか
    逆にOSは2000以上限定ですかね?

569 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:29:18
    9xだって動くんだい

570 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:34:34
    >>565
    なるべく新しいPlatform SDKを入れてみろ

571 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 00:41:56
    VC6なら、ほどほどに新しいもの(2003febだったか)を
    入手する必要があるぞ(w

572 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 07:21:54
    >>565
    VC6 SP6でもちゃんとwinbase.hで定義されてるし、VC6用最終のMSDN Oct.2001には載ってる。
    Win9xも対象にしたいならDETACHED_PROCESSでも使え。
    (CREATE_NO_WINDOWと何が違うのかは知らんが。)

573 名前: デフォルトの名無しさん [sage] 投稿日: 2007/03/08(木) 08:11:37
    リダイレクタ作った時、CREATE_NO_WINDOWを指定したら、
    コンソール窓が開かなくなったが・・
    
    憶測だけど。

カヤック星人様にまとめてもらうとこんな感じ.

Windows XP 時代までの conime.exe の挙動


(Windows XP で c:\users は嘘っぽいけど修正面倒なのでこのまま!)

Windows Vista での conime.exe の挙動

Unlocker 1.8.5 はディレクトリのロックを検出できない

上のスレッドで紹介されている Unlocker ですが,バージョン 1.8.5 と Windows Server 2008 June CTP の組み合わせで試してみたところ,この conime.exe のロックは検出できないようでした.
多分そういうことかと.

http://pc11.2ch.net/test/read.cgi/win/1185679484/974-976
□■ Windows Vista 98 ■□

974 名前: 名無し~3.EXE [sage] 投稿日: 2007/08/09(木) 21:02:10 ID:7e6Pu3+e
    >>971 
    三日に1回のペースであるよ 
    最近はなぜかなくなってきた 
    >>973 
    ファイルコピーがたまに途中でとまるよ 
    しかも再起動するまでゴミ箱に捨てられないファイルもあるし 
    unlockerで調べてもどこにも使用されてないのにさ
    
    でもいいOSだと思うよ

975 名前: 名無し~3.EXE [sage] 投稿日: 2007/08/09(木) 21:04:34 ID:8ts0r/mJ
    最近のunlockerってバグないか?
    XPでもロックされているのに使用してるのが見つからないことがある。
    この場合でもロックを解除するとちゃんと解除されるんだよな。

976 名前: 名無し~3.EXE [sage] 投稿日: 2007/08/09(木) 21:13:06 ID:7e6Pu3+e
    >>975 
    俺はXPの時は問題なかったよ
    でも、削除出来ないいじょうどこかでlockされてるんだよな絶対に。
    vistaが糞じゃなければさw

その他の報告例と Windows Server 2008 June CTP 日本語版での状況

本家の MSDN Forums でも,同様の指摘が今年 3 月に行われているのを見つけました.ただ,このスレッドでは無事に解決したように終わっているのですが,これまで見てきたようにこの問題,ぜんぜん解決していないんじゃないかと.

困ったことに Windows Server 2008 June CTP 日本語版でも同じ症状が見られたので,今回はそちらにフィードバックを入れておきました.

Windows Server 2008 と OpenFileDialog とカレントディレクトリの変更

ついでに発見したのですが,Windows Server 2008 June CTP のコモンダイアログの挙動もなんか変わっているような気がします.
WinForms に System.Windows.Forms.OpenFileDialog を貼り付けて,「ファイルを開くダイアログ」でファイルを選択するという簡単なアプリケーションで実験してみたのですが,以下のような違いが見られました.

  • Windows Vista → カレントディレクトリが変わる
  • Windows Server 2008 June CTP → カレントディレクトリが変わらない

うーん,こういうところの挙動を変えて大丈夫なんでしょうか……
(2008年10月23日追記)
この挙動ですが,Windows Vista / Windows Server 2008 以降と .NET Framework 2.0 SP1/3.0 SP1/3.5 SP1 の組み合わせで,従来とは異なる方法でファイル選択ダイアログが表示されるために発生するようです.GetOpenFileName や,GetSaveFileName といった Win32 API の動作に変更はありません.
具体的な原因ですが,まず .NET Framework 2.0 SP1/3.0 SP1/3.5 SP1 で,WinForms の FileDialog クラスに AutoUpgradeEnabled というプロパティが追加されました.このプロパティが true のとき,Windows Vista / Windows Server 2008 で導入された IFileDialog ベースのダイアログ の使用が試みられます (非対応環境では従来通り GetOpenFileName/GetSaveFileName を使用).
このプロパティは規定で true となります.そして,カレントディレクトリが変わらないという現象は,この IFileDialog ベースのダイアログ使用時に発生するようです.
これらの実装詳細については,公開されている .NET Framework のソースコードで確認することができます.確認方法については『.NET Framework の基本クラスに対してソースレベルデバッグを行う方法 (オフライン編) - NyaRuRuの日記』を参考にしてください.(残念ながら,この方法は Visual C# 2008 Express Edition では使えません)