链接多个 ShellExecute 调用

发布于 2024-08-25 01:05:46 字数 1341 浏览 3 评论 0原文

考虑以下代码及其可执行文件 - 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 参数,则 runner.exe 的第二个实例为 14,它们都是奇怪的东西,例如 Files\Microsoft、SQL、Files\Common 等在。我不明白为什么会发生这种情况。我希望能够使用命令行参数连接尽可能多的 runner.exe 调用,或者至少 2 个。我该怎么做?

我正在使用 Windows 7,如果这有什么区别的话。

Consider the following code and its executable - 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;
}

These two batch files both do what they're supposed to, which is run notepad.exe and run notepad.exe and tell it to try to open test.txt:

1.
runner.exe notepad.exe

2.
runner.exe notepad.exe test.txt

Now, consider this batch file:

3.
runner.exe runner.exe notepad.exe

This one should run runner.exe and send notepad.exe as one of its command line arguments, shouldn't it? Then, that second instance of runner.exe should run notepad.exe - which doesn't happen, I get a "Windows cannot find 'am'. Make sure you typed the name correctly, and then try again" error. If I print the argc argument, it's 14 for the second instance of runner.exe, and they are all weird stuff like Files\Microsoft, SQL, Files\Common and so on. I can't figure out why this happens. I want to be able to string as many runner.exe calls using command line arguments as possible, or at least 2. How can I do that?

I am using Windows 7 if that makes a difference.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

泪冰清 2024-09-01 01:05:46

这行代码有一个错误:

Params += argv[i] + ' ';

这会将 32 添加到指针 argv[i],这不是您想要的。您可以将其分成两行:

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

或使用:

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

您可能还想在每个参数周围添加引号,以防它包含空格。


我还将 fMask 设置为 SEE_MASK_NOASYNC,因为 MSDN 指出:

调用 ShellExecuteEx 后立即退出的应用程序应指定此标志。

You have a bug in this line:

Params += argv[i] + ' ';

This will add 32 to the pointer argv[i], which isn't what you want. You can separate it to two lines:

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

Or use:

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

You may also want to add quotes around each parameter in case it contains spaces.


I'd also set fMask to SEE_MASK_NOASYNC, because MSDN states:

Applications that exit immediately after calling ShellExecuteEx should specify this flag.

舟遥客 2024-09-01 01:05:46

问题是这一行:

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];
}

The problem is this line:

Params += argv[i] + ' '

Because argv[i] is of type char * that adding 32 to argv[i] so will give you a pointer to the middle of random memory.

I would rewrite that to:

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

Or if you wanted to be real good, you can modify that to only add a space when it's really necesssary:

for ( int i = 2; i < argc; ++i )
{
    if (!Params.empty())
        Params += ' ';
    Params += argv[i];
}
榆西 2024-09-01 01:05:46

我认为问题在于您如何为下一次调用创建命令行参数:

 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;
}

I think the problem is how you create the command line parameters for your next call:

 Params += argv[i] + ' ';

does not work as expected. Try the following out:

#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;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文