web-dev-qa-db-ja.com

2つの異なるパラメーターにスペースがある場合、C ++ system()が機能しない

System()を使用して、いくつかのパラメーターを必要とする.exeを実行しようとしています。

.exeのパスと、パラメーターで渡されたファイルのパスにスペースがある場合、次のエラーが発生します。

The filename, directory name, or volume label syntax is incorrect.

そのエラーを生成するコードは次のとおりです。

#include <stdlib.h>
#include <conio.h>

int main (){
    system("\"C:\\Users\\Adam\\Desktop\\pdftotext\" -layout \"C:\\Users\\Adam\\Desktop\\week 4.pdf\"");
    _getch();
}

「pdftotext」のパスで引用符が使用されていない場合(ディレクトリにスペースが含まれる場合があるため、引用符が必要です)、すべて正常に機能します。また、「system()」の内容を文字列に入れて出力し、実際のコマンドウィンドウにコピーすれば動作します。

次のようなコマンドを使用して、いくつかのコマンドをチェーンできると思いました。

cd C:\Users\Adam\Desktop;
pdftotext -layout "week 4.pdf"

したがって、私はすでに正しいディレクトリにいますが、同じsystem()関数で複数のコマンドを使用する方法がわかりません。

私のコマンドが機能しない理由、または私が考えた2番目の方法が機能するかどうかを誰かに教えてもらえますか?

編集:system()は引数をcmd/kに渡すため、追加の引用符のセットが必要だったようです。引用符で囲む必要があります。私はここでそれを見つけました:

C++:私のプログラムにオプションの引数を使用して.exeを開かせる方法

同じエラーメッセージが表示されなかったとしても、質問はかなり近いので、重複として閉じることに投票します。ありがとうございます。

16
Adam Smith

system()はコマンドをcmd /C commandとして実行します。そして、これがcmddocからの引用です。

If /C or /K is specified, then the remainder of the command line after
the switch is processed as a command line, where the following logic is
used to process quote (") characters:

    1.  If all of the following conditions are met, then quote characters
        on the command line are preserved:

        - no /S switch
        - exactly two quote characters
        - no special characters between the two quote characters,
          where special is one of: &<>()@^|
        - there are one or more whitespace characters between the
          two quote characters
        - the string between the two quote characters is the name
          of an executable file.

    2.  Otherwise, old behavior is to see if the first character is
        a quote character and if so, strip the leading character and
        remove the last quote character on the command line, preserving
        any text after the last quote character.

ケース2に該当しているようで、cmdは文字列全体C:\Users\Adam\Desktop\pdftotext" -layout "C:\Users\Adam\Desktop\week 4.pdf(つまり、最初と最後の引用符なし)が実行可能ファイルの名前であると考えています。

したがって、解決策は、コマンド全体を追加の引用符で囲むことです。

//system("\"D:\\test\" nospaces \"text with spaces\"");//gives same error as you're getting
system("\"\"D:\\test\" nospaces \"text with spaces\"\""); //ok, works

そして、これは非常に奇妙です。ケース2で常に文字列を解析するようにするために、/Sを追加することも良い考えだと思います。

system("cmd /S /C \"\"D:\\test\" nospaces \"text with spaces\"\""); //also works
30
hamstergene

私は答えを探してここに来ました、そしてこれは私が思いついたコードです(そして私は私のコードを維持する次の人の利益のためにこれを明示しました):

std::stringstream ss;
std::string pathOfCommand;
std::string pathOfInputFile;

// some code to set values for paths

ss << "\"";                             // command opening quote
ss << "\"" << pathOfCommand   << "\" "; // Quoted binary (could have spaces)
ss << "\"" << pathOfInputFile << "\"";  // Quoted input (could have spaces)
ss << "\"";                             // command closing quote
system( ss.str().c_str() );             // Execute the command

そしてそれは私のすべての問題を解決しました。

0
PfunnyGuy

ここからシステムコールの内部について学ぶことができます。C++文字列、TCHARなどで同じ問題を再現できます(もちろん)。常に私を助けてくれたアプローチの1つは、SetCurrentDirectory()呼び出しです。最初に現在のパスを設定してから実行します。これは私にとってこれまでのところうまくいきました。コメントは大歓迎です。 -Sreejith。 D.メノン

0