こんばんわ。またわからないことができたので質問します。
ちょっと前、あるVC++のソフト(フリーウェアです)を
ダウンロードしてきたんですけれど、
コマンドプロンプトで
C:\XXXXXX> ~~~~.exe *
と言う風に、「.exe」のあとに半角スペースと
「*」という値(そのときは数字でした。)を
書いてリターンを押すと、
いつもとは違った感じでexeが起動しました。
(ちなみにこのやり方は、お姉ちゃんに教わりました。)
「これは何?不思議。どうやってやるの?」
と、お姉ちゃんに聞いても、コーディング方法は
知らないとのことです。
例えば、コマンドプロンプトで
C:\XXXXX> AAA.exe Q
って書くと、「Q」ってメッセージボックスがでるようなexeを作りたいです。
(Qを書いてなかったらなんにもでないで終わりたいです。)
コーディング方法がわかる方、いらっしゃいましたら、
教えてください。
よろしくお願いします。
コマンドライン引数ですね。
VC++ならCWinAppのメンバm_lpCmdLineです。
AppWizardを使ったならCWinAppのInitInstance()にm_lpCmdLineがあったはずです。
重さん、お返事ありがとうございます。
その節はホントに助かりました。
わたしは、AppWizardを使ってプログラムを作ってるんですけど、
CMyApp::InitInstance()関数の中には、m_lpCmdLineの
記述がありませんでした。
それとも、この関数の中に自分でm_lpCmdLineを書くのでしょうか?
例えば、
BOOL CMyApp::InitInstance()
{
~~~~~~;
~~~~~~;
if(m_lpCmdLine=****)
{
AfxMessageBox(Q,MB_OK);
}
}
のようにするのでしょうか。
(でもm_lpCmdLineの型がわからないです(悲)。)
何か、わたしが定義し忘れているとか、
もしお気づきなった点がございましたら、教えてください。
よろしくお願いします。
m_lpCmdLineはLPTSTRですね。
こんな感じで、コマンドラインパラメータを見ることができます。
MessageBox(NULL, m_lpCmdLine, test, MB_OK);
if (m_lpCmdLine[0] != '\0') {
何かする
} else {
何もしない
}
他には「Win32 Console Application」で「単純アプリケーション」を作成すれば
下記のような感じでコマンドラインのパラメータを表示することができます。
#include stdafx.h
#include <stdio.h>
int main(int argc, char* argv[])
{
int n;
for (n = 0; n < argc; n++) {
printf(%s\n, argv[n]);
}
return 0;
}
「Win32 Application」で「単純なWin32アプリケーション」の場合は下記のような感じ。
MFCのm_lpCmdLineとlpCmdLineは同じ物と考えて良いでしょう。
int APIENTRY WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance,
LPSTR lpCmdLine, int nCmdShow)
{
MessageBox(NULL, lpCmdLine, test, MB_OK);
return 0;
}
メニューの「編集」に「ファイルから検索」というのがありますので
検索文字列にm_lpCmdLineを指定し
C:\PROGRAM FILES\MICROSOFT VISUAL STUDIO\VC98\MFC\INCLUDE
(インストール先がデフォルトなら)で検索すれば
m_lpCmdLineがLPTSTRであると分かります。
普通はこれは自分のプロジェクトに対して検索のでしょうが
こういった使い方もできます。
僕はテキストエディタのgrep機能を使ってますが、世の中には
http://www.forest.impress.co.jp/search.html
こんな感じのソフトもあります。
> わたしは、AppWizardを使ってプログラムを作ってるんですけど、
> CMyApp::InitInstance()関数の中には、m_lpCmdLineの
> 記述がありませんでした。
実際にやってみたら出てきません。嘘つきでした。m(__)m
以下は確認済みです。
まず、m_lpCmdLineはLPSTR型です。(Afxwin.hで定義されています。)
起動引数取り出し方(InitInstance()に追加してみてください。)
その1
if (m_lpCmdLine[0] != _T('\0'))
MessageBox(NULL, m_lpCmdLine, m_lpCmdLineテスト, MB_OK);
その2
int iLoop;
for(iLoop = 1; iLoop < __argc; iLoop++)
MessageBox(NULL, __argv[iLoop], DOSと同じ?, MB_OK);
注
InitInstance()にある↓を無効にしないと***ファイルがありませんと言ってきます。
ParseCommandLine(cmdInfo);
実際にやってみると動作が違います。
私としては”その2”の方が馴染んでいるので好きなんですけど・・・
目的にあった方で使えばよいかと思います。
重さん、kuさん、お返事ありがとうございます。
お二人には、いつもお世話になってしまいますね。
ホントに、うれしいです(でも申し訳ないな…)。
InitInstance関数の中に、m_lpCmdLineの記述を
自分で書いて判定すればいいんですね。
kuさんと重さんのサンプルを見てみると、
for文でループしてあって、「なんでループしてるのかなぁ?」
って思ったんだけど、
「引数の最初の文字から終りの文字まで」
ということなんですよね?
例えば、重さんの「その1」では、1文字しか判定できない
(~.exe ABC って書いても、最初のAしか判定できない)けど、
「その2」なら全部の文字が判定できるとゆうことですよね?
さっき、以下の方法を試したんですけど、
if文がすどおりしちゃいました。
if(m_lpCmdLine==ABC)
{
~~~~;
}
これは、LPTSTR型の変数は、「==ABC」の判定ができないとゆうことなのかなぁ。
(Format関数でCString形の変数に置き換えると、「==ABC」の判定ができました)
でも、これでコマンドライン引数の取り方がわかりました。
kuさん、重さん、ありがとうございました。
これからも、いろいろ教えてください。
よろしくお願いします。
> 例えば、重さんの「その1」では、1文字しか判定できない
> (~.exe ABC って書いても、最初のAしか判定できない)けど、
> 「その2」なら全部の文字が判定できるとゆうことですよね?
違います。
「その1」では起動引数全てを1つの文字列としてm_lpCmdListに、
「その2」ではDOSと同じように、スペースで区切られた文字列を__argv[n]の代入します。
例えば、*.exe ABC DEF GHIとやった場合、
m_lpCmdListは ABC DEF GHI となります。
__argv[0]は *.exeのフルパス
__argv[1]は ABC
__argv[2]は DEF
__argv[3]は GHI
と、スペースを区切りとした各文字列となります。
ちなみに、__argvが **__argv、*__argv[]どちらが正規なのかは知らないです。
どう思います?
ご、ごめんなさい(恥)。
何か、とんでもない勘違いをしてたみたいで(恥)。
確かに、__argv[0]にはフルパス、
__argv[1]には最初の引数
が入ってました(AfxMessageBox関数で調べました)。
早とちりして、紛らわしいことを書いてしまい、
みなさんにご迷惑をおかけしたこと、反省します。
ところで、
AfxMessageBox(__argv[1],MB_OK);
だと、ちゃんとメッセージボックスに引数の値が表示されるのに、
if(__argv[1]==AAA)
{
~~~;
}
という書き方だと、引数を認めてくれません(m_lpCndLineもです)。
この理由は、やっぱりLPTSTR型だからでしょうか?
解決したのにイジイジと質問を続けるのは良くないと思うんですけど、
やっぱり気になるんです…。
> この理由は、やっぱりLPTSTR型だからでしょうか?
そうですね。
但しLPSTR型だからと言うよりは、CStringは==をオーバーロードしてあるので
==に因る判定が可能と言った方が正しいかと思います。
LPTSTR型を追っていくと char* となっているのが解りますよ。
> if(__argv[1]==AAA)
> {
> ~~~;
> }
この様な方法で判別したい場合には
if(*(__argv[1] +?) == 'A')
こんな感じに1文字ずつ判別していかなければなりません。
重さん、何回もすみませんでした。
>但しLPSTR型だからと言うよりは、CStringは==をオーバーロードしてあるので
>==に因る判定が可能と言った方が正しいかと思います。
わたし、文字を扱うときは、ほとんどCString型(クラス?)で
定義してるので、==で判定できるのが当たり前のように
思ってたんですけど、実は「CStringだから==で判定できる」とゆう
ことなんですね(また勘違いだったら恥ずかしいなぁ)。
==を使って判定する場合、一文字ずつ見ていくか、
もしくは一回CString型に変換すれば、判定できるってゆうことか…。
重さん、ここまで付き合ってくださって、
とてもうれしいです。
ホントにありがとうございました。
> ==を使って判定する場合、一文字ずつ見ていくか、
> もしくは一回CString型に変換すれば、判定できるってゆうことか…。
1回で文字列を判定するならstrcmpがあります。
今回、起動引数と言うことで、殆ど *.exe /? /?の様に/の後の1文字を判別することが多いので
> if(*(__argv[1] +?) == 'A')
>
> こんな感じに1文字ずつ判別していかなければなりません。
こんな書き込みをしました。言葉足らずでした、申し訳ないです。m(__)m
過去に使用したリストの一部(起動引数判別部分のみ)をつけてみました。
多少は参考になるかと思います。
int main(int argc, char **argv)
{
int iLoop;
for(iLoop = 1; iLoop < argc; iLoop++) {
if(**(argv +iLoop) == '/') {
// 引数判別
if(*(*(argv +iLoop) +1) == 'D') {
// デバックログ作成
}
if(*(*(argv +iLoop) +1) == 'P') {
// ログデータ印刷
}
}
}
・
・
・
こんばんわ。重さん。
ここまで回答してくださったこと、
ホントにうれしく思います。
教えていただいた、strcmp関数を使って、
以下のように書いてみました。
if(__argv[1]!=NULL)
{
if(strcmp(__argv[1],ABC)==0)
{
AfxMessageBox(おめでとう!,MB_OK);
}
}
最初のif文は、__argv[1]の値がNULLだったら
strcmp関数が異常エラーしちゃうので、
それを避けるために書きました。
上に書いたとおりにコーディングしたら、
文字全部の判定ができました。
重さん、一回一回超初心者のわたしにもわかるように、
教えてくださって、ほんとにありがとうございます。
地道に知識を広げて、
早くわたしも、人に教えてあげられるくらいに
なりたいなぁ、と思います。
これからも、よろしくお願いします!