Цепочка нескольких вызовов ShellExecute - PullRequest
0 голосов
/ 15 марта 2010

Рассмотрим следующий код и его исполняемый файл - runner.exe:

#include <iostream>
#include <string>
#include <windows.h>

using namespace std;

int main(int argc, char *argv[])
{
    SHELLEXECUTEINFO shExecInfo;

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);

    shExecInfo.fMask = NULL;
    shExecInfo.hwnd = NULL;
    shExecInfo.lpVerb = "open";
    shExecInfo.lpFile = argv[1];

    string Params = "";
    for ( int i = 2; i < argc; ++i )
        Params += argv[i] + ' ';

    shExecInfo.lpParameters = Params.c_str();

    shExecInfo.lpDirectory = NULL;
    shExecInfo.nShow = SW_SHOWNORMAL;
    shExecInfo.hInstApp = NULL;

    ShellExecuteEx(&shExecInfo);

    return 0;
}

Оба этих пакетных файла делают то, что должны, то есть запускают notepad.exe и notepad.exe и говорят ему попытаться открыть test.txt:

1.
runner.exe notepad.exe

2.
runner.exe notepad.exe test.txt

Теперь рассмотрим этот командный файл:

3.
runner.exe runner.exe notepad.exe

Этот должен запустить runner.exe и отправить notepad.exe в качестве одного из аргументов командной строки, не так ли? Затем этот второй экземпляр runner.exe должен запустить notepad.exe - чего не происходит, я получаю сообщение «Windows не может найти« am ». Убедитесь, что вы правильно ввели имя, а затем повторите попытку». Если я напечатаю аргумент argc, это будет 14 для второго экземпляра runner.exe, и все они будут странными вещами, такими как Files \ Microsoft, SQL, Files \ Common и так далее. Я не могу понять, почему это происходит. Я хочу иметь возможность записывать как можно больше вызовов runner.exe, используя аргументы командной строки, или как минимум 2. Как я могу это сделать?

Я использую Windows 7, если это имеет значение.

Ответы [ 3 ]

3 голосов
/ 15 марта 2010

У вас есть ошибка в этой строке:

Params += argv[i] + ' ';

Это добавит 32 к указателю argv[i], что не то, что вам нужно. Вы можете разделить его на две строки:

Params += argv[i];
Params += ' ';

Или используйте:

Params += string(argv[i]) + ' ';

Вы также можете добавить кавычки вокруг каждого параметра, если он содержит пробелы.


Я бы также установил fMask на SEE_MASK_NOASYNC, поскольку MSDN сообщает:

Приложения, которые выходят сразу после вызова ShellExecuteEx, должны указывать этот флаг.

1 голос
/ 15 марта 2010

Я думаю, проблема в том, как вы создаете параметры командной строки для вашего следующего вызова:

 Params += argv[i] + ' ';

не работает должным образом. Попробуйте следующее:

#include <windows.h>
#include <fstream>
#include <iostream>
#include <tchar.h>
using namespace std;

#ifdef _UNICODE
    typedef std::wstring tstring;
#else
    typedef std::string tstring;
#endif

int _tmain(int argc, TCHAR *argv[])
{
    {
        std::ofstream f("C:\\output.txt", std::ios::app);
        f << "app called" << std::endl;
    }
    SHELLEXECUTEINFO shExecInfo;

    shExecInfo.cbSize = sizeof(SHELLEXECUTEINFO);

    shExecInfo.fMask = NULL;
    shExecInfo.hwnd = NULL;
    shExecInfo.lpVerb = _T("open");
    shExecInfo.lpFile = argv[1];

    tstring Params(_T(""));
    for ( int i = 2; i < argc; ++i )
    {
        Params += argv[i]; 
        Params += _T(' ');
    }

    shExecInfo.lpParameters = Params.c_str();

    shExecInfo.lpDirectory = NULL;
    shExecInfo.nShow = SW_SHOWNORMAL;
    shExecInfo.hInstApp = NULL;

    ShellExecuteEx(&shExecInfo);

    return 0;
}
1 голос
/ 15 марта 2010

Проблема в этой строке:

Params += argv[i] + ' '

Поскольку argv[i] относится к типу char *, то при добавлении 32 к argv[i] вы получите указатель на середину случайной памяти.

Я бы переписал это:

Params += std::string(argv[i]) + ' ';

Или, если вы хотите быть по-настоящему хорошим, вы можете изменить это, добавив пробел только тогда, когда это действительно необходимо:

for ( int i = 2; i < argc; ++i )
{
    if (!Params.empty())
        Params += ' ';
    Params += argv[i];
}
...