※ お知らせ ※

スクリプトを利用して本エントリーの内容を半自動化する方法を別エントリーで紹介していますので、そちらもご一読ください。

Windows 7: C:\Program Files フォルダーを別ドライブに移動 (x64 対応半自動化版)

Windows 7 のシステム要件によると、インストール先ディスクの空き容量は 32ビット版で 16GB 以上、64ビット版で 20GB 以上とされている。Windows 7 Ultimate (32ビット版) をクリーン・インストールした直後の C: ドライブのディスク消費量は 7GB 程度 (ページファイルを除く) だが、このシステム要件は、様々なプログラムをインストールしたり、「ドキュメント」 以下にファイルを溜め込んで行く使い方を想定してのこと。大容量化が進んだ最近の HDD なら 「1.5TB の C: ドライブ一発」 と言うこともできるので、旧型 PC にインストールする場合以外では、ディスク容量が問題になることは少なそうだ。ただし 「1.5TB 一発」 は男らしさのアピールにはいいとして、ディスク障害発生時のリスク、OS の再インストール、デフラグ時のコスト等を考えると、あまり効率的とは言えない。

一方、ディスクを適切なサイズにパーティショニングしたり別ディスクを用意するなどして、システム以外のソフトウェアを別ドライブにインストールする方法は、Windows のパフォーマンス向上、と言うより低下防止やリスク軽減策としてよく見られる。しかし各プログラムのインストール時に毎回別ドライブの任意の場所を指定していては、うっかり C: ドライブにインストールしてしまうこともあるし、プログラム本体は別ドライブにインストールできても、付属品が C: ドライブ (Program Files\Common Files 等) に入ってしまうこともある。こうした事態を防ぐには、Windows がデフォルトのインストール先として認識している、環境変数 ProgramFiles で定義されたフォルダー (以下 「ProgramFiles フォルダー」) を移動させてしまえばいい。

※ 注意 ※

以下の作業で操作を誤ると、OS に回復不能な損傷を与えて Windows の再インストールが必要になる他、データを失う等の副次的被害が発生する可能性があります。本ページの内容を参考に行った作業によって何らかの損害を被った場合も、筆者は一切の責任を負いません。お試しになる場合は、くれぐれも自己責任でお願いします。

僕は Windows 9x 時代から XP まで (Vista は見送り)、自分で好きにいじれる PC は必ず OS インストール直後に ProgramFiles フォルダー別ドライブに移動させることにしている。そこで今後少しずつ進める予定の Windows XP → Windows 7 の段階的なリプレイスに備えて検証してみると、Windows 7 でも XP とほぼ同様の操作で、ProgramFiles フォルダーの移動ができることがわかった。しかし Vista 以降の Windows ならではの部分があるので、手順をまとめておく。

 作業の流れは以下の通り。Windows 7 は Ultimate (32ビット版) で、インストール直後のデフォルト・ユーザー名を test、ProgramFiles フォルダー移動前のパスを C:\Program Files、移動先を D:\Program Files と仮定している。表示フォントによっては、パス区切り記号の "¥" がバックスラッシュ (半角\) になるので、"/" と間違えないように注意。

  1. ローカル Administrator の有効化、及びパスワード設定。
  2. ProgramFiles フォルダーをコピー。
  3. レジストリの書き換え。
  4. 旧 ProgramFiles フォルダーを削除。
  5. 移動先のアプリケーションの動作確認。

作業は Windows 7 のクリーン・インストール直後、できれば上記作業に必須ではないドライバー類もインストールしない状態の方が、手間とリスクを最小限にできる。

1. ローカル Administrator の有効化、及びパスワード設定

最強のユーザーであるローカル Administrator は、Windows 7 のデフォルト状態では無効になっている。まずデフォルト・ユーザー test でログオン後、スタート メニューの 「全てのプログラム」 → 「アクセサリ」 → 「コマンド プロンプト」 を右クリック → 「管理者として実行」 を選択し、コマンド プロンプトを管理者権限で起動する。コマンド プロンプトでは次の操作を行う。

> net user Administrator /active:yes ← Administrator を有効化

> net user Administrator <PASSWORD> ← パスワードを設定

> set ProgramFiles ← 環境変数を確認
ProgramFiles=C:\Program Files ← この段階では C: ドライブ

> set CommonProgramFiles
CommonProgramFiles=C:\Program Files\Common Files ← こちらも同様

※ 64ビット環境では上記変数名に "(x86)" を付加した環境変数も存在し、それぞれ " (x86)" を付加した値が設定されている。

コマンド プロンプトを管理者権限で実行していないと、「システム エラー 5」 「アクセスが拒否されました」 等のメッセージが表示される。最後の set コマンドは、この段階で Windows が ProgramFiles フォルダーとして認識している場所を確認している。

Administrator を有効化できたら test はログオフし、Administrator でログオンし直す。

2. ProgramFiles フォルダーをコピー

Windows 7 のデフォルト状態では、拡張子や隠しファイルが表示されていない。「フォルダーと検索のオプション」 の「表示」 タブの 「詳細設定」 で、次の設定を変更する。

  • 隠しファイル、隠しフォルダー、および隠しドライブを表示する → 選択
  • 登録されている拡張子は表示しない → OFF
  • 保護されたオペレーティング システム ファイルを表示しない (推奨) → OFF

※ 03/01 修正
以前はエクスプローラー上でフォルダーをコピーする方法を記載していたが、アクセス許可設定や属性等が再現できない問題があるので、xcopy コマンドを用いる方法に変更。

フォルダのコピーは、管理者権限のコマンド プロンプトを開き、以下のように xcopy コマンドで行う。

> xcopy /e /h /k /o /x /b /y "C:\Program Files" "D:\Program Files\"

> xcopy /e /h /k /o /x /b /y "C:\Program Files (x86)" "D:\Program Files (x86)\" ← 64ビット環境の場合

上記オプションは、空フォルダーを含むサブ・フォルダー (/e)、隠しファイル及びシステム・ファイル (/h)、属性 (/k)、所有権及び ACL 情報 (/o)、監査設定 (/x)、リンク自体をコピー (/b)、上書き時の問い合わせなし (/y) を指定している。

※ 03/05 追記
ジャンクション "Program Files\Windows NT\アクセサリ" の扱いが不完全であることが判明したので、「x64 対応半自動化版」 で修正。上記コマンドを既に実施してしまった場合は、手動修正も可能。

コピーが完了したら、エクスプローラーでコピー元とコピー先の各フォルダーのプロパティを開き、ファイルやフォルダーの数、アクセス許可設定等が正しくコピーできているか確認する。

3. レジストリの書き換え

このフェイズでは、レジストリ中に存在する "C:\Program Files" と言う文字列を移動先のパス、今回の例では D:\Program Files に置換する。単純だが記述箇所が大量にあるため、一つ一つ探し出して編集するのは現実的でない。

そこで利用するのが、レジストリ中の任意の文字列を検索・置換する RegGrep。Windows 9x 時代からお世話になっている便利なツールで、Windows 7 でも動く。(02/28 追記: RegGrep は 32ビット環境限定。64ビット環境では、Registry Toolkit の 64ビット版で意図通りの置換ができた。同ツールは 32ビット版もあり)

RegGrep を管理者権限で起動したら (UAC を無効化していなければ右クリック → 「管理者権限で実行」)、次のように設定して 「置換」 ボタンをクリックする。

  • 検索文字列に "C:\Program Files"、置換文字列に移動先のパス、今回の例では "D:\Program Files" とそれぞれ入力 ("" は不要)。
  • 「対象ルートキー」 で HKEY_DYN_DATA キー (Windows XP 以降では存在しない) 以外を ON。
  • 「オプション」 で 「大文字と小文字を区別する」 を ON。

最初にヒットした文字列のダイアログで 「すべて置換」 ボタンをクリックすると、以後発見される文字列が全て置換される。

※ 02/28 追記
前述の Registry Toolkit を使用する場合は、ツリー構造の "My Registry" を選択した状態でメニューの 「Registry」 → 「Search of Replace in Registry」 ダイアログを表示させ、"Settings" の "Match Case"、"Search/Replace In" の "Data" と "Value" のチェックを ON にして、「Replace」 ボタンをクリックする (各項目の名前にピンと来なければ、こちらのサイトが参考になる)。"Start In:" が "My Registry" 以外になっている場合はレジストリの全域をスキャンできないので、忘れずに確認する。ヒットした文字列を全て置換するには、最初に表示されるダイアログで 「Replace Rest」 ボタンをクリック。

20100228a_1.jpg
Registry Toolkit での置換

尚、Windows XP では 8.3形式の短いファイル名が使われているので、この後 C:\PROGRA~1 を D:\PROGRA~1 に置換する。クリーン・インストール直後の Windows 7 では 8.3形式での記述は見つからなかったが、念のため検索しておいた方がいいかもしれない。僕の環境では存在しなかったが、もし C:\PROGRA~2 と言う記述が見つかっても、これは C:\ProgramData の 8.3形式表記なので、そうと知らずに書き換えてしまうと危ない。

さらに、アプリケーション単位の INI ファイル等で旧 Program Files フォルダーがフルパスで指定されている場合も不具合が予想されるので、移動先 Program Files フォルダー内で文字列 "C:\Program Files" を検索する。その際 「フォルダー オプション」 の 「検索」 タブにある 「検索項目」 で、「ファイル名と内容を常に検索する」 を選択しておかないと、INI ファイルの内容を検索できない。

ちなみにクリーン・インストール直後の僕の環境では、8.3形式の ProgramFiles フォルダーのパスや、修正が必要な INI ファイルは見つからなかった。

ProgramFiles フォルダーを指す全ての文字列置換が完了後、Windows 7 を再起動する。

4. 旧 ProgramFiles フォルダーを削除

これまでの作業でスタート メニュー中にあるショートカットのリンク先も、移動先の ProgramFiles フォルダーに追従しているはずなので、不要になったはずの旧 ProgramFiles フォルダー (と 64ビット環境では ProgramFiles(x86) フォルダー) を削除する。Windows XP ではいきなり Administrator で削除できたが、セキュリティが強化された Windows 7 では (恐らく Vista も同様)、事前にひと手間必要になる。

旧 ProgramFiles フォルダーを削除するには、Windows 7 上で直接行う他に、C: ドライブがある HDD を別のマシンに接続したり、KNOPPIX (5.x で NTFS パーティションの操作が可能) 等の CD 起動 Linux を使う等、いくつか方法がある。ひとまず Windows 7 上で直接削除するには、以下の手順で行う。

まず Administrator でログオン後、コマンド プロンプトで次のコマンドを入力し、Windows の該当環境変数の値が移動先の ProgramFiles フォルダーに変わっていることを確認する。

> set ProgramFiles
ProgramFiles=D:\Program Files ← 値が移動先 ProgramFiles フォルダーに変更されている

> set CommonProgramFiles
CommonProgramFiles=D:\Program Files\Common Files ← こちらも変更されている

環境変数 ProgramFiles 及び CommonProgramFiles の値が移動先 ProgramFiles フォルダー以下に変更されている、即ち Windows が C:\Program Files の存在を忘れてしまっていることが確認できたら、以下の操作で所有権を奪う。旧 ProgramFiles フォルダーのプロパティを開き、「セキュリティ」 タブの 「詳細設定」 ボタンで、「セキュリティの詳細設定」 ウィンドウを開く。「所有者」 タブで 「現在の所有者」 が TrustedInstaller になっていることを確認して 「編集」 ボタンをクリック。「所有者の変更」 欄から Administrator を選択して 「サブコンテナーとオブジェクトの所有者を置き換える」 を ON にし、「OK」 ボタンをクリック。

次にアクセス権限を変更する。同じ 「セキュリティの詳細設定」 ウィンドウで 「アクセス許可」 タブに移動し、「アクセス許可の変更」 ボタンをクリック。「アクセス許可エントリ」 欄の Administrators を選択した状態で 「編集」 ボタンをクリックし、「適用先」 を 「このフォルダー、サブフォルダーおよびファイル」、「アクセス許可」 欄の 「フル コントロール」 を ON にして閉じる。「セキュリティの詳細設定」 ウィンドウに戻るので、「子オブジェクトのアクセス許可すべてを、このオブジェクトからの継承可能なアクセス許可で置き換える」 を ON にして、開いている全てのウィンドウを 「OK」 ボタンで閉じる。

これでようやく、旧 ProgramFiles フォルダー以下を好きに料理できるようになる。フォルダー削除時に 「IP Helper が使用中で sqmapi.dll が削除できない」 旨のメッセージが表示される場合は、タスク マネージャーの「サービス」 タブで iphlpsvc を探し、右クリック → 「サービスの停止」 で一時的に IP Helper を止めて、残ったフォルダーを削除する。削除後、改めて iphlpsvc を右クリックメニューで起動し直しておく。

参考までに、KNOPPIX を使う場合の手順を以下で説明する。

KNOPPIX で起動後、まずデスクトップに表示される HDD のアイコンをダブル・クリックして中身を確認する。旧 ProgramFiles フォルダーがあるデバイスを特定できたら、root 権限のシェルを起動 (メニューの 「KNOPPIX」 → 「Root Shell」)。HDD アイコンをダブル・クリックした時点で、該当デバイス・ファイルが読み取り専用でマウントされているので、次の手順で削除する。(C: ドライブが /dev/sda2 と認識されていると仮定)

# umount /media/sda2 ← Program Files フォルダーがあるディレクトリをアンマウント (読み取り専用)

# mount /dev/sda2 /media/sda2 ← 再度マウント

# cd /media/sda2/

# rm -rf "Program Files" ← 丸ごと削除

僕が KNOPPIX 5.3.1 でテストした際は、Program Files/Windows NT/アクセサリ の削除に失敗したが、Windows 7 に Administrator でログオン後、前述のアクセス権限云々の操作をせずに、いきなり削除できた。

尚、本エントリーの公開後、実はデスクトップの右クリック → 「ガジェット」
のアイコンが表示されず、機能しないことに気がついた。改めてレジストリを検索してみると、"HKEY_CLASSES_ROOT\DesktopBackground\Shell\Gadgets\command"
等、管理者であっても編集できない部分に旧 ProgramFiles フォルダーのパスが残っている。旧 ProgramFiles フォルダーは既に削除してしまって存在しないので、機能しないと言うわけだ。

この不具合の解消のため、管理者権限でコマンド プロンプトを起動し、次のように C: ドライブ直下にシンボリック リンクを作成する。

C:\Users\Administrator> cd ..\..\ ← C: ドライブ直下に移動

C:\> mklink /d "Program Files" "D:\Program Files" ← /d オプションでフォルダーへのシンボリック リンクを作成

C:\> dir ← 確認
 :
2010/02/19  21:31    <SYMLINKD>     Program Files [D:\Program Files]
 :

※ 64ビット環境では、同じ場所で "Program Files (x86)" → "D:\Program Files (x86)"
のシンボリック・リンクも作成する。

UNIX 系 OS で多用するシンボリック・リンクだが、Windows でも作ることができ、同名で呼ばれているとは知らなかった。この mklink コマンドが導入されたのは Vista からで、XP でもリソース・キットに含まれる linkd コマンドで実現できるらしい。ひょっとするとレジストリを無理やり置換する必要はなかったんじゃないか、と一瞬考えたが、旧 ProgramFiles フォルダーを削除する前の段階で Windows 7 が移動先 ProgramFiles フォルダーを環境変数 ProgramFiles として認識していなければいけないので、やはり置換は必要だ。

5. 移動先のアプリケーションの動作確認

移動させたドライブのアプリケーションをスタート メニュー等から起動し、正常に動作することを確認して作業完了。

僕の環境では、上記作業で ProgramFiles フォルダーを移動させることができた。ただこれは Windows 7 をクリーン・インストールした直後の状態なので、既に各種アプリケーションがインストールされている状態では同じように行くとは限らないし、アプリケーションによっては、移動はできても正常動作しない可能性がある点には、ご注意いただきたい。

ProgramFiles フォルダーが移動できれば、あとはページファイルを専用パーティションに移動させたり、「ドキュメント」 等の 「個人用フォルダー」 以下にある任意のフォルダーを別ドライブに移動させる等して、極力 C: ドライブを 「軽く」 する。「個人用フォルダー」 以下のフォルダーは、右クリック → プロパティの 「場所」 タブで任意の場所を指定できるので楽だ。

6 Responses to this entry.

  • Natz:

    「ガジェット」 機能等で一部不完全な部分があったため、回避策を追記。

  • Natz:

    64ビット環境におけるレジストリ置換作業を加筆。

  • Natz:

    ProgramFiles フォルダーのコピー方法を変更。

  • Natz:

    「x64 対応半自動化版」 として改訂。
    http://www.natzworks.com/digital/entries/2010/000263.html

  • t:

    ・ローカル Administrator の有効化とパスワード設定
    ・レジストリの書き換え

    を実施せずに Program Files が移動できました。

    作業した環境は、Windows 7 SP1 32bitです。
    参考までにその手順を紹介させて頂きます。

    以下、コマンドプロンプトは管理者として実行。別ドライブは、D としています。
    1. xcopy で ドライブ D に Program Files フォルダをコピー
    2. D:\Program Files\Windows NT\アクセサリを削除(不要にコピーされた実体を削除)
    3. mklink /J "D:\Program Files\Windows NT\アクセサリ" "D:\Program Files\Windows NT\Accessories" でジャンクションを作成
    4. C:\Program Files\Windows NT\アクセサリ を削除
    5. KNOPPIX で Cドライブの Program Files を削除
    6. Windows セーフモード で起動
    7. mklink /J "C:\Program Files" "D:\Program Files" でジャンクション作成

    KNOPPIX による削除は、自分では思いつくことができなかったので、
    とても参考になりました。ありがとうございました。

  • Natz:

    > t さん
    遅くなってしまいましたが、コメントありがとうございます。
    このカスタマイズは(個人的には)既に確立した方法だったため、他の方法は試していませんでした。
    今度仮想環境などで実験してみます。