アプリ版:「スタンプのみでお礼する」機能のリリースについて

●質問内容
システム環境変数を変更する場合(WindowsXP時)、
「スタート」⇒「設定」⇒「コントロールパネル」⇒「システム」の
「システムのプロパティ」画面の「詳細設定」タグ内の「環境変数」ボタンを
押下して「環境変数」画面にて新規/編集/削除を実施すると思います。

システム環境変数の削除を行うにあたり上記一連操作をバッチファイル
等の単純操作にて実施したいと考えているのですがどのようにすれば実現できるでしょうか?
条件は以下の通りです。
・OSはWindowsXPもしくはWindows2000。
・削除するシステム環境変数名は決まっている。
・ログオン/ログインや再起動は行わずに削除情報を反映させたい。

●質問内容補足
自分で調べた範囲ではシステム環境変数の新規/編集であれば
Windows2000のリソースキット中のsetx.exeというプログラムを
利用すれば可能だということが分かりました。
このHPで言っているように削除もバッチ処理で行いたいのです。
参考HP<<http://chinpindo.blog11.fc2.com/blog-entry-61.ht …

お手数ですがご回答頂けると幸いです。
よろしくお願いいたします。

A 回答 (8件)

この回答への補足

早急なご回答ありがとうございます。
残念ながらこちらのHPでは実施したい内容と条件が異なります。

このページは質問する前に既に参照して実行していたのですが、
システム環境変数名が削除されるのではなく、
システム環境変数値が空になるだけで
システム環境変数名自体は残ってしまいます。
つまりシステム環境変数値が空のシステム環境変数が存在する事になります。

実施したい内容としては、
あるシステム環境変数自体を削除したいということです。

●追加質問
レジストリ操作によってシステム環境変数を削除する方法は分かりました。
但しレジストリを変更後、再起動せずに変更を有効にする方法が分かりません。
こちらも知ってる方がいらっしゃったら合わせてアドバイスを頂けると
幸いです。

補足日時:2006/12/21 16:58
    • good
    • 0

★再起動せずに変更を有効にする方法


・システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします。
・レジストリ操作によってシステム環境変数を操作する方法を知っているのなら出来ますね。
・なお、環境変数の文字列操作は経験的に面倒ですよ。→検索、追加、挿入、削除といろいろね。
・短いですがアドバイスはこれで終わりです。
・下に『参考URL』を載せておきます。→『詳細』部分に『再起動せずに変更を有効にする方法』があるよ。

参考URL:http://support.microsoft.com/kb/104011/ja

この回答への補足

ご回答ありがとうございます。
同HPも質問前に検索して既に見つけていたのですが、
再起動せずに変更を有効にする方法が分かりません。

>・システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします。
参考URLに記述されていた以下の本文内容
「関連するアプリケーション (エクスプローラ、プログラム マネージャ、タスク マネージャ、コントロール パネルなど) が更新を行えるように、システム内のすべてのウィンドウに WM_SETTINGCHANGE メッセージをブロードキャストします」
の中で、
・システム内のすべてのウィンドウ
・WM_SETTINGCHANGE メッセージをブロードキャストします
という文章の意味がいまいち分かりません。
「システム内のすべてのウィンドウ」とは環境変数変更後に使用するアプリケーションを示すのでしょうか?
またWM_SETTINGCHANGEメッセージを具体的にどのようにブロードキャストしたらよいかその方法が分かりません。
(教えていただいた参考URLに以下の例が書かれていましたが、
どの記述が何の意味を示すのか分からず困っています。)
SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE, 0,
(LPARAM) "Environment", SMTO_ABORTIFHUNG,
5000, &dwReturnValue);
ちなみにシステム環境変数の削除には以下の記述を行った.reg拡張子ファイルを作成し
同ファイルををダブルクリックして削除しました。
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Session Manager\Environment]
"AAA"=-

>・レジストリ操作によってシステム環境変数を操作する方法を知っているのなら出来ますね。
すいません。下記URLを参考に環境変数の追加、変更、削除までは
できる様になったのですが、再起動せず変更を有効にする方法は
分かりません。
参考URL:http://www.higaitaisaku.com/patchfile.html

>・なお、環境変数の文字列操作は経験的に面倒ですよ。→検索、追加、挿入、削除といろいろね。
少々実施した私でも面倒だと感じました。
なので長くやられているとより一層そう感じますよね、きっと。

追加質問となってしまい申し訳ありません。
ご回答の程、よろしくお願いいたします。

補足日時:2006/12/22 09:12
    • good
    • 0

VBScript使っていいなら以下のような感じでできると思います。


Option Explicit

Set objShell = WScript.CreateObject("WScript.Shell")
Set sysEnv = objShell.Environment("System")
sysEnv.Remove("削除する環境変数名")
Set sysEnv = Nothing
Set objShell = Nothing

参考URL:http://www.atmarkit.co.jp/fwin2k/operation/wsh06 …
    • good
    • 0
この回答へのお礼

ご回答ありがとうございました。

今回VBScriptは用いずに実施させたいので利用できませんが、
別方法でも実現可能だと勉強になりました。

お礼日時:2006/12/22 13:29

★簡単な解説


・まず、Win32 API『SendMessageTimeout』関数で複数のウィンドウへメッセージを送信します。
・また、『WM_SETTINGCHANGE』メッセージは、システム全体の設定を変更したときに、再起動など
 しないで設定内容を反映したい場合に送ります。つまり、再起動などしないですべてのトップ
 ウインドウに『更新したよ』というメッセージを送るのです。なお、昔は『WM_WININICHANGE』
 で『WIN.ini』ファイルを更新するメッセージがありました。これの、レジストリ版って事だ。

★『WM_SETTINGCHANGE』メッセージ
●WPARAM
・アプリケーションが発行するときは 0 を指定
●LPARAM
・更新する部分のレジストリ名(WIN.iniのセクション名)の文字列を指定

★『SendMessageTimeout』関数
LRESULT SendMessageTimeout(
 HWND hWnd, // ウィンドウのハンドル
 UINT Msg, // メッセージ
 WPARAM wParam, // メッセージの最初のパラメータ
 LPARAM lParam, // メッセージの2番目のパラメータ
 UINT fuFlags, // 送信オプション
 UINT uTimeout, // タイムアウト期間(ms)
 PDWORD_PTR lpdwResult // 同期呼び出しの戻り値
);

●参考URLの説明
・『hWnd』に『HWND_BROADCAST』を指定すると、システム内の全てのトップ・ウィンドウに送信
・『Msg』に『WM_SETTINGCHANGE』を指定。 ←システムの更新を反映させるため
・『wParam』に 0 を指定。 ←アプリケーションが発行するから
・『lParam』に "Environment" の文字列を指定。 ←環境変数を更新するから
・『fuFlags』に『SMTO_ABORTIFHUNG』を指定。 ←ハングアップ状態のとき、即、制御を戻す
・『uTimeout』に『5000ms』を指定。 ←ハングアップと判断するまでの時間
・『lpdwResult』に『dwReturnValue』を指定。 ←メッセージの処理結果を格納
・以上。おわり。

参考URL:http://msdn.microsoft.com/library/ja/jpwinui/htm …

この回答への補足

ご丁寧に解説して頂きありがとうございました。

早速、システム環境変数を削除する「○○○.rsg」を
以下のように内容を変更して同ファイルをダブルクリックしたところ、「レジストリに正しく入力されました」とメッセージが出るものの、
環境変数削除が反映されていないように思えます。
何が悪いのか分からない為、ご指摘頂けると幸いです。
(Win32 API『SendMessageTimeout』関数はレジストリ操作ファイルと
一緒に書かず、別に作成するものなのでしょうか?)

●○○○.rsgファイルの内容
1. Windows Registry Editor Version 5.00
2. [HKEY_CURRENT_USER\Environment]
3. "AAA"=-
4.
5. Windows Registry Editor Version 5.00
6. SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
7. 0, "Environment", SMTO_ABORTIFHUNG, 5000, &dwReturnValue);
(※左側数字(Ex 1.)は行番号。)

●システム環境削除が反映されたかの確認方法
上記○○○.rsgファイルダブルクリック後、
コマンドプロンプトを開いて「set AAA」と打ち込んだところ、
削除前の値である「AAA=aaa」が表示されてしまいました。
(※試しにAAAという環境変数を操作しています。)

補足日時:2006/12/22 13:29
    • good
    • 0

> (Win32 API『SendMessageTimeout』関数はレジストリ操作ファイルと


> 一緒に書かず、別に作成するものなのでしょうか?)

レジストリ操作ファイルにAPIを書いても無視されるかエラーになるだけだと思います。
Windows上で動くプログラムは通常はウィンドウメッセージというもののやり取りをしていて、
SendMessageTimeOutというのは任意のウィンドウにウィンドウメッセージを投げるものです。
ですから、このメッセージを投げるプログラムが何らかの形で必要になります。

バッチとかwshではできないような気がします。
CなりVisual Basic、はたまたDelphiなどで(ほかにもできるものはありますが)
ウィンドウメッセージを投げるプログラムを作らなければならないのではないでしょうか?

あと、このメッセージを投げたとしてもメッセージを受ける側のプログラムのつくりによっては
環境変数が書き換えられたとしてもそれを認識しない可能性があります。
    • good
    • 0
この回答へのお礼

ご回答ありがとうございます。

『SendMessageTimeout』関数はWin32API関数だったんですね。
そのままレジストリ操作ファイルに書くような書式ではないと
薄々気付いてはいたのですが…調査不足ですいませんでした。

この回答見てからプログラムを組んでEXEファイルを
作成したらシステム環境変数を反映させる事が出来ました。
ありがとうございます。

お礼日時:2006/12/22 16:06

★バッチファイル等の単純操作だけでは実現不可能。


・まず、『SendMessageTimeout』関数は、????.reg ファイルに記述する命令ではありません。
・回答者 No.5 番さんの『アドバイス』通りです。
・よって、バッチファイルで実行を反映させるには簡単なアプリケーションを作成して
 それを実行させます。下にそのCサンプルを紹介。→テスト済み(正常に動作した)

Cサンプル:
#include <stdio.h>
#include <windows.h>

int main( VOID )
{
 DWORD dwReturnValue;
 LRESULT Ret;
 
 printf( "★レジストリ内容を反映させています...\n" );
 
 Ret = SendMessageTimeout( HWND_BROADCAST, WM_SETTINGCHANGE, 0,
  (LPARAM)TEXT("Environment"), SMTO_ABORTIFHUNG,
  5000, &dwReturnValue );
 
 if ( Ret == 0 ){
  printf( "\n×正常にレジストリ内容を反映できませんでした。\n" );
 }
 else{
  printf( "\n★正常にレジストリ内容を反映しました。\n" );
 }
 return( 0 );
}

方法:
・回答 No.4 の補足にある ????.reg ファイルの内容は3行で良い。
・上記のCサンプルを元に『コンソール・アプリケーション』を作る。→コマンド名(RegRefreshなど)
・バッチファイルで、????.reg と RegRefresh を記述すれば実現可能です。
・ただし、現在開いている『コマンド・プロンプト』には反映しませんので、『コマンド・プロンプト』を
 起動し直す必要があります。→システムの環境変数は反映します。
・また、ソフトによっては『WM_SETTINGCHANGE』メッセージを受け取らない仕組みならば、上記方法では
 反映されることはありません。→この場合は再起動などが必要です。

まとめ:
・レジストリ操作ファイルと一緒に書かずに、別にコマンドを作成します。
・以上。おわり。→サンプルは、C言語ソースです。

この回答への補足

ご丁寧なご回答ありがとうございます。

ANo.5の回答を見た後、
私がプログラムを組んだものとご明示頂いたサンプルソースが
ほぼ同じ内容だった為、自分が合っていると確認できました。
また『コンソール・アプリケーション』を作る等、
補足情報が詳細で良く理解することが出来ました。

最後に二点だけ質問させて下さい。
(1)
サンプルソース内に『(LPARAM)TEXT("Environment")』という
記述がありましたが、このTEXTというのは何を表しているのでしょうか?
(以前教えて頂いた参考HPのサンプルにはTEXTの記述はありませんでした。)
(2)
上記サンプルソースをコンパイルして作成したEXEをダブルクリックしたところ、
処理が終了した時点でコマンドプロンプトが閉じてしまい、
printf文で表示している内容が『"★レジストリ内容を反映させています』しか確認できませんでした。
サンプルソースのreturn(0)の前に『fflush(stdin); 』という
Enterキーを押さないとコマンドプロンプトが次行の処理に
移らない記述を書いても効果がありませんでした。
EXEを直接実行(ダブルクリック)した後、printf文を確認できるように
処理を止めるにはどうしたらよいでしょうか?

何度も伺ってしまい申し訳ありません。

補足日時:2006/12/22 16:19
    • good
    • 0

★最後の質問について


・『TEXT』はマクロ関数です。
・これは、ビルド(コンパイル)時に UNICODE が定義されていれば、文字列定数に『L』を追加して
 UNICODE の定数に解釈します。また、UNICODE が定義されていないと『シフトJISコード』で解釈
 します。つまり、ビルド(コンパイル)時に UNICODE が定義されているかどうかで簡単に Unicode
 への対応ができるためのマクロです。『TEXT』マクロを使うと後で国際向けのプログラムに簡単に
 変身できます。(参考: http://wisdom.sakura.ne.jp/system/winapi/win32/w … )
・バッチファイルの中で一時停止したいのならば『pause』という命令を1行記述します。
 これで、一時停止しますので『★正常にレジストリ内容を反映しました。』という文字列を確認
 できるようになります。何かキーを押すと続きの処理を行います。→最後だと、画面が閉じます。

●バッチ内容
????.reg
RegRefresh.exe
pause
※上記の3行で最後に一時停止しますので、確認メッセージを表示できます。

余談:
・API関数の『SetWindowText』には、『SetWindowTextA』と『SetWindowTextW』の2つがあります。
・『SetWindowTextA』は『シフトJISコード』対応の文字列を引数に取ります。
・『SetWindowTextW』は『Unicodeコード』対応の文字列を引数に取ります。
・よって、SetWindowText 関数を使うと、定数 UNICODE の定義によってどちらの関数を
 ビルド(コンパイル)時にリンクするかが決定します。これと同じです。『TEXT』マクロの機能は。
・以上。分かりましたか?

最後に:
・以前『C言語を用いた環境変数の作成/削除方法』で質問した xf710 さんですね。
・そのときに http://support.microsoft.com/kb/104011/ja を紹介しましたね。忘れていました。
    • good
    • 0
この回答へのお礼

お礼が遅くなり申し訳ありません。
TEXTの意味及びバッチファイルについてや余談の内容等、
分かり易い解説を本当にありがとうございました。

やりたい事が実現できて大変助かりました。
またAPI関数等様々な知識を学んでいきたいと感じられました。
しかも覚えて質問した内容まで覚えていられるとは…恐縮です。
また何か質問する事がありましたら何卒よろしくお願いいたします。

お礼日時:2006/12/24 00:55

EXEファイル自体で入力待ちをしたいということなら、getchar()あたりを


使うことがポピュラーではないでしょうか。
fflushはバッファにたまっているデータを掃きだすことをするので、
入力待ちにはなりません。ていうか fflush(stdin) って規格上未定義ですよ。

いっそのこと MessageBox を使って待つというのはダメでしょうか?
対応のライブラリをきちんとリンクしておけば、main() で始まる通常の
コンソールプログラムでもメッセージボックスを出すことはできますよ。
    • good
    • 0
この回答へのお礼

最初に質問した際には、
EXE自体で入力待ちにしたいと考えていたのでご回答助かりました。
fflush(stdin)で止められるような事を記述しているHPがあって、
それで止めれた事があったのでそう信じてたのですが違うんですね…
getchar()、MessageBox両方試してみたいと思います。
ご回答ありがとうございました。

お礼日時:2006/12/24 01:07

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!