2

I tried the solutions in Launching Microsoft Edge with URL from code and How to open URL in Microsoft Edge from the command line? but they do not work for me.

Here's my code:

    std::string url = "http://www.test.com";
    std::wstring quotedArg = L"microsoft-edge:\"" + url + L"\"";
    std::vector<WCHAR> argBuff(quotedArg.w_size() + 1);
    wcscpy_s(&argBuff[0], argBuff.size(), quotedArg.w_str());

    STARTUPINFO si = {0};
    PROCESS_INFORMATION pi = {0};
    si.cb = sizeof si;
    si.dwFlags = STARTF_USESHOWWINDOW;
    si.wShowWindow = SW_SHOWNORMAL;

    if (!CreateProcess(L"start", &argBuff[0], NULL, NULL, FALSE,
                       0, NULL, NULL, &si, &pi)) {
       DWORD error = GetLastError(); // here error = 2
       return false;
    }

    CloseHandle(pi.hProcess);
    CloseHandle(pi.hThread);

The error code after CreateProcess() is 2, which in https://msdn.microsoft.com/en-us/library/windows/desktop/ms681382%28v=vs.85%29.aspx stands for ERROR_FILE_NOT_FOUND.


Update 1: To Dúthomhas's questions: I'm not binding the user with Edge. I was using ShellExecuteEx() to open http/https URL as below snippet.

    SHELLEXECUTEINFO sei = { };
    sei.cbSize = sizeof sei;
    sei.nShow = SW_SHOWNORMAL;
    sei.lpFile = url.w_str();
    sei.lpVerb = L"open";

    sei.fMask = SEE_MASK_CLASSNAME;

    sei.lpClass = url.startsWith("https:")
                  ? L"https"
                  : L"http";

    if (ShellExecuteEx(&sei)) {
       return true;
    }

However this does not work for Microsoft Edge and will pop up error dialog saying

<URL> The specified module could not be found.


Update 2:

Put the full path of cmd /C start in CreateProcess() as suggested by Dúthomhas make the call succeeds,

    wui::string quotedArg = L"/C start microsoft-edge:" + url;
    std::vector<WCHAR> argBuf(quotedArg.w_size() + 1);
    wcscpy_s(&argBuf[0], argBuf.size(), quotedArg.w_str());
    CreateProcess(L"C:\\Windows\\System32\\cmd.exe", &argBuf[0], NULL, 
                  NULL, FALSE, 0, NULL, NULL, &si, &pi)

But the result is no browser opened and a pop up dialog showing

microsoft-edge:<UR> The specified module could not be found.

Community
  • 1
  • 1
Lee
  • 535
  • 5
  • 19
  • @david-heffernan This is not a duplicate of "How to open URL in Microsoft Edge from the command line" because the solution in that answer does not work here. – Lee Oct 29 '15 at 18:45
  • That's not how duplicates work. Presumably you just need to use `ShellExecuteEx` anyway. – David Heffernan Oct 29 '15 at 18:53

2 Answers2

5

From what I can see, you are making rather heavy weather of this. Certainly, it is not as complicated as it seems. The following code brings up an Edge window, and navigates to the desired site:

#include <Windows.h>

int main()
{
    CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED);

    SHELLEXECUTEINFOW sei = { sizeof sei };
    sei.lpVerb = L"open";
    sei.lpFile = L"microsoft-edge:http://www.stackoverflow.com";
    ShellExecuteExW(&sei);
}

I suspect that you were getting your quotes in a muddle.

David Heffernan
  • 601,492
  • 42
  • 1,072
  • 1,490
  • I tried your program, it pops up an error dialog with title "microsoft-edge:http://www.stackoverflow.com" and content "This file does not have a program associated with it for performing this action. Please install a program or, if one is already installed, create an association in the Default Programs control panel." I checked "Default Programs" in control panel and chose "Set this program as default" in Microsoft Edge config, which makes no difference. BTW my OS is Windows Server 2016. – Lee Nov 02 '15 at 19:37
  • It's working here. I'm using Windows 10 as the question is tagged. – David Heffernan Nov 02 '15 at 19:51
  • Let me find a Win 10 to test and report the result back later. – Lee Nov 02 '15 at 20:00
  • OK your code works in my Win 10 test. So the way to start Edge in Windows Server 2016 is not the same with the one in Windows 10 as I thought. Anyway, thanks for your help! – Lee Nov 02 '15 at 22:54
  • You tagged the question windows-10 – David Heffernan Nov 02 '15 at 23:00
  • Thanks for reminding. I tagged win10 because I thought win10 and winsvr2016 are the same on this issue. Tags have been updated. – Lee Nov 03 '15 at 00:13
  • That's not how it works. I reverted the tags. I answered the question you asked. If you asked the wrong question then that's your problem. It's rude and tactless to have people spend time and effort and then change the question after the fact. – David Heffernan Nov 03 '15 at 07:04
  • OK I got what you mean. I'm not trying to waste your time and do appreciate your discussion. I'll open a new question with the correct tag. – Lee Nov 05 '15 at 00:54
3

You are doing a few weird things, like using a std::vector instead of a straight-up std::wstring. (It is okay to pass the .c_str() to functions like this.)

In any case, always make sure to read the documentation for functions like CreateProcess.

You must supply the complete command-line for your your process, not just pieces. There is no executable named 'start' -- it is a subcommand of cmd.exe. So if you use CreateProcess you must also give the full, true command-line:

C:\Windows\System32\cmd.exe /C start microsoft-edge:http://www.test.com

All said, however, you really shouldn't be dictating to your user which browser he should be using. Your user has selected a default browser because that is the browser he wishes to use. When you subvert that choice and launch a different browser anyway, he will hate your software.

[edit] Well, I don't have Windows 10 installed, so I haven't messed around with Edge, but it appears that MS has not given it the standard command-line abilities. I cannot fathom why.

Nevertheless, it looks like you might have to stick with the 'start' command "protocol", with the method used by your Update 2, simply leaving out the "microsoft-edge" part.

The only other recourse that I can suggest (and I don't know enough about Windows 10 to say that this is necessarily the only correct way) is to look in the Registry to see if edge is installed, and start the browser with the correct method.

Alas.

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • No it is really not OK to pass a constant buffer to the second arg of CreateProcess. Read the docs. – David Heffernan Oct 28 '15 at 22:13
  • No, it really _is_ OK to pass it along, since the buffer is guaranteed to be yours to modify by the C++11 standard. Read the docs. – Dúthomhas Oct 29 '15 at 00:37
  • No. `c_str` returns a pointer to non-modifiable buffer, `const char*` or `const wchar_t*`. – David Heffernan Oct 29 '15 at 08:25
  • Updates provided in the question area. – Lee Oct 29 '15 at 18:46
  • Yes. `c_str()` returns const for hysterical raisins. You're really going to pick a fight over something you know better? _Every_ extant implementation have continuous, directly accessible storage, C++11 guarantees it _and_ a trailing null. [Read more?](http://stackoverflow.com/a/16502000/2706707) – Dúthomhas Oct 29 '15 at 21:03
  • I'm not arguing about contiguous directly accessible storage. You are wrong in your belief that `c_str()` returns a pointer to a modifiable buffer. It does not. And `CreateProcessW` does modify the buffer. So instead of `str.c_str()` use `&str[0]`. – David Heffernan Oct 29 '15 at 21:28
  • LOL. Someone is wrong in the interwebs. You know full well that `str.c_str()` === `&str[0]`. – Dúthomhas Oct 29 '15 at 21:45
  • 1
    Perhaps you don't know what `const` means – David Heffernan Nov 02 '15 at 19:50