From 85d5e4a13e6bf6a4a20a924f3c26a29f2d968bb3 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 11 Dec 2015 12:30:09 -0800 Subject: [PATCH 1/8] Adding the VC project system's .opendb file to .gitignore --- .gitignore | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.gitignore b/.gitignore index 1bc915c..de7a209 100644 --- a/.gitignore +++ b/.gitignore @@ -154,3 +154,6 @@ $RECYCLE.BIN/ # Mac desktop service store files .DS_Store + +# Vc project file +*.VC.opendb \ No newline at end of file From 7d9961d9274501507f3ec727cedde26a36897dfd Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Wed, 25 May 2016 12:49:36 -0700 Subject: [PATCH 2/8] First cut of process montioring for launching edge --- src/Helpers.cpp | 144 ++++++++++++ src/Helpers.h | 27 +++ src/MicrosoftEdgeLauncher.cpp | 263 ++++++++++++++++++---- src/MicrosoftEdgeLauncher.h | 17 +- src/MicrosoftEdgeLauncher.vcxproj | 2 + src/MicrosoftEdgeLauncher.vcxproj.filters | 6 + src/stdafx.h | 6 +- 7 files changed, 424 insertions(+), 41 deletions(-) create mode 100644 src/Helpers.cpp create mode 100644 src/Helpers.h diff --git a/src/Helpers.cpp b/src/Helpers.cpp new file mode 100644 index 0000000..6886981 --- /dev/null +++ b/src/Helpers.cpp @@ -0,0 +1,144 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// + +#include "stdafx.h" +#include "Helpers.h" +#include +#include +#include +#include +#include +#include + +#define IDM_STARTDIAGNOSTICSMODE 3802 +#define CP_AUTO 50001 +#define VERSION_SIGNATURE 0xFEEF04BD + +namespace Helpers +{ + BOOL EnumWindowsHelper(_In_ const function& callbackFunc) + { + return ::EnumWindows([](HWND hwnd, LPARAM lparam) -> BOOL { + return (*(function*)lparam)(hwnd); + }, (LPARAM)&callbackFunc); + } + + BOOL EnumChildWindowsHelper(HWND hwndParent, _In_ const function& callbackFunc) + { + return EnumChildWindows(hwndParent, [](HWND hwnd, LPARAM lparam) -> BOOL { + return (*(function*)lparam)(hwnd); + }, (LPARAM)&callbackFunc); + } + + bool IsWindowClass(_In_ const HWND hwnd, _In_ LPCWSTR pszWindowClass) + { + if (hwnd && pszWindowClass && *pszWindowClass) + { + const int BUFFER_SIZE = 100; + WCHAR szClassname[BUFFER_SIZE]; + + int result = ::GetClassName(hwnd, (LPWSTR)&szClassname, BUFFER_SIZE); + if (result && _wcsicmp(szClassname, pszWindowClass) == 0) + { + return true; + } + } + + return false; + } + + HRESULT GetDocumentFromSite(_In_ IUnknown* spSite, _Out_ CComPtr& spDocumentOut) + { + ATLENSURE_RETURN_HR(spSite != nullptr, E_INVALIDARG); + + CComQIPtr spDocument(spSite); + if (spDocument.p != nullptr) + { + CComQIPtr spDocDisp(spDocument); + ATLENSURE_RETURN_HR(spDocDisp.p != nullptr, E_NOINTERFACE); + + spDocumentOut = spDocDisp; + return S_OK; + } + else + { + CComQIPtr spBrowser2(spSite); + if (spBrowser2 != nullptr) + { + CComPtr spDocDisp; + HRESULT hr = spBrowser2->get_Document(&spDocDisp); + FAIL_IF_NOT_S_OK(hr); + ATLENSURE_RETURN_HR(spDocDisp.p != nullptr, E_FAIL); + + spDocumentOut = spDocDisp; + return hr; + } + else + { + CComQIPtr webAppHost(spSite); + if (webAppHost.p != nullptr) + { + CComPtr spDoc; + HRESULT hr = webAppHost->get_Document(&spDoc); + FAIL_IF_NOT_S_OK(hr); + CComQIPtr spDocDisp(spDoc); + ATLENSURE_RETURN_HR(spDocDisp.p != nullptr, E_NOINTERFACE); + + spDocumentOut = spDocDisp; + return S_OK; + } + } + } + + return E_NOINTERFACE; + } + + HRESULT GetDocumentFromHwnd(_In_ const HWND browserHwnd, _Out_ CComPtr& spDocument) + { + DWORD_PTR messageResult = 0; + LRESULT sendMessageResult = ::SendMessageTimeoutW(browserHwnd, Helpers::GetHtmlDocumentMessage(), 0L, 0L, SMTO_ABORTIFHUNG, 2000, &messageResult); + + if (sendMessageResult != 0 && messageResult != 0) + { + HMODULE* hModule = new HMODULE(::LoadLibraryEx(L"oleacc.dll", nullptr, LOAD_LIBRARY_SEARCH_SYSTEM32)); + shared_ptr spOleAcc(hModule, [](HMODULE* hModule) { ::FreeLibrary(*hModule); delete hModule; }); + if (spOleAcc) + { + auto pfObjectFromLresult = reinterpret_cast(::GetProcAddress(*spOleAcc.get(), "ObjectFromLresult")); + if (pfObjectFromLresult != nullptr) + { + return pfObjectFromLresult(messageResult, IID_IHTMLDocument2, 0, reinterpret_cast(&spDocument.p)); + } + } + } + + return E_FAIL; + } + + UINT GetHtmlDocumentMessage() + { + if (s_getHtmlDocumentMessage == 0) + { + s_getHtmlDocumentMessage = ::RegisterWindowMessageW(L"WM_HTML_GETOBJECT"); + } + + return s_getHtmlDocumentMessage; + } + + CString FormatErrorMessage(_In_ DWORD ErrorCode) + { + TCHAR *pMsgBuf = NULL; + DWORD nMsgLen = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | + FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, ErrorCode, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + reinterpret_cast(&pMsgBuf), 0, NULL); + if (!nMsgLen) + { + return _T("FormatMessage fail"); + } + CString sMsg(pMsgBuf, nMsgLen); + LocalFree(pMsgBuf); + return sMsg; + } +} diff --git a/src/Helpers.h b/src/Helpers.h new file mode 100644 index 0000000..1cd4040 --- /dev/null +++ b/src/Helpers.h @@ -0,0 +1,27 @@ +// +// Copyright (C) Microsoft. All rights reserved. +// + +#pragma once +#include +#include + +// Define some assert helper macros +#define FAIL_IF_NOT_S_OK(hr) ATLENSURE_RETURN_HR(hr == S_OK, SUCCEEDED(hr) ? E_FAIL : hr) +#define THROW_IF_NOT_S_OK(hr) ATLENSURE_THROW(hr == S_OK, SUCCEEDED(hr) ? E_FAIL : hr) +#define FAIL_IF_ERROR(jec) ATLENSURE_RETURN_HR(jec == JsNoError, jec) +#define THROW_IF_ERROR(jec) ATLENSURE_THROW(jec == JsNoError, jec) + +namespace Helpers +{ + BOOL EnumWindowsHelper(_In_ const function& callbackFunc); + BOOL EnumChildWindowsHelper(HWND hwndParent, _In_ const function& callbackFunc); + bool IsWindowClass(_In_ const HWND hwnd, _In_ LPCWSTR pszWindowClass); + + HRESULT GetDocumentFromSite(_In_ IUnknown* spSite, _Out_ CComPtr& spDocumentOut); + HRESULT GetDocumentFromHwnd(_In_ const HWND browserHwnd, _Out_ CComPtr& spDocument); + UINT GetHtmlDocumentMessage(); + static UINT s_getHtmlDocumentMessage; + + CString FormatErrorMessage(_In_ DWORD ErrorCode); +} diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index 940b117..c3a34d6 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -2,58 +2,243 @@ #include "MicrosoftEdgeLauncher.h" #include #include +#include +#include +#include "Helpers.h" int _tmain(int argc, _TCHAR* argv[]) { - HRESULT hr = E_FAIL; + HRESULT hr = S_OK; hr = CoInitialize(NULL); + + PCWSTR pszUrl = L""; + bool bKeepAlive = false; + if (!SUCCEEDED(hr)) - { + { return hr; } - if (2 == argc) - { - if ((argv[1] == L"-h") | (argv[1] == L"-help")) - { - std::cout << "Launches the Microsoft Edge browser."; - std::cout << "\n"; - std::cout << "\n"; - std::cout << "Usage:"; - std::cout << "\n"; - std::cout << "\tMicrosoftEdgeLauncher.exe [url]"; - std::cout << "\n"; - std::cout << "\n"; - std::cout << "\turl - The URL to open in Microsoft Edge."; - std::cout << "\n"; - std::cout << "\n"; - hr = E_ABORT; - } - else - { - hr = OpenUrlInMicrosoftEdge(argv[1]); - } + if (argc == 2) + { + if ((argv[1] == L"-?") | (argv[1] == L"-h") | (argv[1] == L"--help")) + { + ShowHelp(); + hr = E_ABORT; + } + else + { + pszUrl = argv[1]; + } + } + else if (argc == 3) + { + pszUrl = argv[1]; + if ((argv[2] == L"-k") | (argv[2] == L"--keepalive")) + { + bKeepAlive = true; + } + else + { + std::cout << "Error: Expecting -k got: \n " << argv[2]; + std::cout << "\n"; + std::cout << "Use -h for usage info."; + hr = E_ABORT; + } } else - { - hr = OpenUrlInMicrosoftEdge(L""); + { + pszUrl = L"http://www.bing.com"; } + + DWORD pid = 0; + hr = LaunchEdge(pszUrl, pid); + + if (bKeepAlive) + { + AttachLifeTime(pid); + } + CoUninitialize(); return hr; } -HRESULT OpenUrlInMicrosoftEdge(__in PCWSTR url) + +HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid) +{ + PCWSTR pszAppUserModelId = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"; + PCWSTR pszInitialUrl = L"http://bing.com"; + HRESULT hr; + DWORD dwProcessID; + + CComPtr spActivationManager; + hr = CoCreateInstance(CLSID_ApplicationActivationManager, /*punkOuter*/ nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spActivationManager)); + hr = spActivationManager->ActivateApplication(pszAppUserModelId, pszInitialUrl, AO_NONE, &dwProcessID); + + EdgeTargetInfo info; + info = WatchForEdgeTab(pszInitialUrl); + pid = info.pid; + return hr; +} + +void ShowHelp() +{ + std::cout << "Launches the Microsoft Edge browser."; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "Usage:"; + std::cout << "\n"; + std::cout << "\tMicrosoftEdgeLauncher.exe [url] -k"; + std::cout << "\n"; + std::cout << "\n"; + std::cout << "\turl - The URL to open in Microsoft Edge."; + std::cout << "\t-k - Keep this program alive for as long as the launched process is alive."; + std::cout << "\n"; + std::cout << "\n"; +} + +HRESULT ShowLastError(_In_ PCWSTR pszErrorIntro) { - HRESULT hr = E_FAIL; - CoInitializeEx(nullptr, COINIT_APARTMENTTHREADED); - SHELLEXECUTEINFOW sei = { sizeof sei }; - sei.lpVerb = L"open"; - std::wstring mywstring(url); - std::wstring concatted_stdstr = L"microsoft-edge:" + mywstring; - sei.lpFile = concatted_stdstr.c_str(); - hr = ShellExecuteExW(&sei); - if (FAILED(hr)) - { - std::cout << L"Failed to launch Microsoft Edge"; - } - return hr; + DWORD dwError = GetLastError(); + + CString strErorrMessage = Helpers::FormatErrorMessage(dwError); + + std::cout << "\nError "; + std::cout << "\n"; + std::cout << "\n" << pszErrorIntro; + std::cout << "\n"; + std::cout << "\nError code: " << dwError; + std::cout << "\nError message:"; + std::cout << "\n" << strErorrMessage; + std::cout << "\n"; + + return HRESULT_FROM_WIN32(dwError); +} + + +HRESULT AttachLifeTime(_In_ DWORD dwPid) +{ + HRESULT hr = S_OK; + DWORD dwResult; + HANDLE hndProcess; + + hndProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, dwPid); + if (hndProcess == NULL) + { + return ShowLastError(L"Error opening process"); + } + + std::cout << "\nWaiting for process " << dwPid <<" to exit..."; + dwResult = WaitForSingleObject(hndProcess, LifetimeTimeoutMs); + + switch (dwResult) + { + case WAIT_OBJECT_0: + return S_OK; + break; + case WAIT_TIMEOUT: + std::cout << "\nTimed out waiting for process to exit."; + return E_FAIL; + break; + default: + return ShowLastError(L"Error wating for process exit."); + break; + } + + return hr; +} + +EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl) +{ + EdgeTargetInfo info = { 0 }; + int loopCounter = 0; + int waitTimeMS = 2000; + + do + { + Sleep(waitTimeMS); + loopCounter++; + vector vTargets; + + EnumerateTargets(vTargets); + + for (size_t i = 0; i < vTargets.size(); i++) + { + EdgeTargetInfo info = vTargets[i]; + if (info.url == pszUrl) { + return info; + } + } + + if (loopCounter > 5) + { + return{ 0 }; + } + } while (info.pid == 0); + + return info; +} + +HRESULT EnumerateTargets(vector& vTargets) +{ + vTargets.empty(); + Helpers::EnumWindowsHelper([&](HWND hwndTop) -> BOOL + { + Helpers::EnumChildWindowsHelper(hwndTop, [&](HWND hwnd) -> BOOL + { + if (Helpers::IsWindowClass(hwnd, L"Internet Explorer_Server")) + { + bool isEdgeContentProcess = false; + + DWORD processId; + ::GetWindowThreadProcessId(hwnd, &processId); + + CString processName; + CHandle handle(::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processId)); + if (handle) + { + DWORD length = ::GetModuleFileNameEx(handle, nullptr, processName.GetBufferSetLength(MAX_PATH), MAX_PATH); + processName.ReleaseBuffer(length); + isEdgeContentProcess = (processName.Find(L"MicrosoftEdgeCP.exe") == processName.GetLength() - 19); + + processName = ::PathFindFileNameW(processName); + } + + if (isEdgeContentProcess) + { + CComPtr spDocument; + HRESULT hr = Helpers::GetDocumentFromHwnd(hwnd, spDocument); + if (hr == S_OK) + { + CComBSTR url; + hr = spDocument->get_URL(&url); + if (hr != S_OK) + { + url = L"unknown"; + } + + CComBSTR title; + hr = spDocument->get_title(&title); + if (hr != S_OK) + { + title = L""; + } + + EdgeTargetInfo i; + i.hwnd = hwnd; + i.url = url; + i.title = title; + i.processName = processName; + i.pid = processId; + vTargets.push_back(i); + } + } + } + + return TRUE; + }); + + return TRUE; + }); + + return S_OK; } diff --git a/src/MicrosoftEdgeLauncher.h b/src/MicrosoftEdgeLauncher.h index eb10a96..5f3dc2d 100644 --- a/src/MicrosoftEdgeLauncher.h +++ b/src/MicrosoftEdgeLauncher.h @@ -1,4 +1,19 @@ #include "stdafx.h" #include +#include -HRESULT OpenUrlInMicrosoftEdge(__in PCWSTR url); \ No newline at end of file +struct EdgeTargetInfo { + HWND hwnd; + PCWSTR title; + PCWSTR url; + PCWSTR processName; + DWORD pid; +}; + +HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid); +EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl); +HRESULT EnumerateTargets(_Out_ std::vector& vTargets); +HRESULT AttachLifeTime(_In_ DWORD dwPid); +void ShowHelp(); +HRESULT ShowLastError(_In_ PCWSTR pszErrorIntro); +int LifetimeTimeoutMs = INFINITE; diff --git a/src/MicrosoftEdgeLauncher.vcxproj b/src/MicrosoftEdgeLauncher.vcxproj index c3fbd6d..7c2e917 100644 --- a/src/MicrosoftEdgeLauncher.vcxproj +++ b/src/MicrosoftEdgeLauncher.vcxproj @@ -79,12 +79,14 @@ + + Create diff --git a/src/MicrosoftEdgeLauncher.vcxproj.filters b/src/MicrosoftEdgeLauncher.vcxproj.filters index 040205a..34526c4 100644 --- a/src/MicrosoftEdgeLauncher.vcxproj.filters +++ b/src/MicrosoftEdgeLauncher.vcxproj.filters @@ -27,6 +27,9 @@ Header Files + + Header Files + @@ -35,6 +38,9 @@ Source Files + + Source Files + diff --git a/src/stdafx.h b/src/stdafx.h index 36b1da7..aa620ab 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -14,4 +14,8 @@ #define _ATL_CSTRING_EXPLICIT_CONSTRUCTORS // some CString constructors will be explicit #include -#include \ No newline at end of file +#include +#include +#include + +using namespace std; From 427fbc07bbe76efd890a75f3cdc1a7f38c639cb6 Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Wed, 25 May 2016 14:04:08 -0700 Subject: [PATCH 3/8] Updating string checks to actually compare strings... --- src/MicrosoftEdgeLauncher.cpp | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index c3a34d6..3d6b83d 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -20,7 +20,7 @@ int _tmain(int argc, _TCHAR* argv[]) } if (argc == 2) { - if ((argv[1] == L"-?") | (argv[1] == L"-h") | (argv[1] == L"--help")) + if ((wcscmp(argv[1], L"-?") == 0) | (wcscmp(argv[1], L"-h") == 0) | (wcscmp(argv[1], L"--help") == 0)) { ShowHelp(); hr = E_ABORT; @@ -33,7 +33,7 @@ int _tmain(int argc, _TCHAR* argv[]) else if (argc == 3) { pszUrl = argv[1]; - if ((argv[2] == L"-k") | (argv[2] == L"--keepalive")) + if ((wcscmp(argv[2], L"-k") == 0) | (wcscmp(argv[2], L"--keepalive") == 0)) { bKeepAlive = true; } @@ -47,13 +47,13 @@ int _tmain(int argc, _TCHAR* argv[]) } else { - pszUrl = L"http://www.bing.com"; + pszUrl = L"http://www.bing.com/"; } DWORD pid = 0; hr = LaunchEdge(pszUrl, pid); - if (bKeepAlive) + if (SUCCEEDED(hr) && bKeepAlive) { AttachLifeTime(pid); } @@ -66,7 +66,7 @@ int _tmain(int argc, _TCHAR* argv[]) HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid) { PCWSTR pszAppUserModelId = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"; - PCWSTR pszInitialUrl = L"http://bing.com"; + PCWSTR pszInitialUrl = L"http://www.bing.com/"; HRESULT hr; DWORD dwProcessID; @@ -76,8 +76,17 @@ HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid) EdgeTargetInfo info; info = WatchForEdgeTab(pszInitialUrl); - pid = info.pid; - return hr; + if (info.pid == 0) + { + return E_NOINTERFACE; + } + else + { + pid = info.pid; + return S_OK; + } + + return E_FAIL; } void ShowHelp() @@ -164,7 +173,7 @@ EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl) for (size_t i = 0; i < vTargets.size(); i++) { EdgeTargetInfo info = vTargets[i]; - if (info.url == pszUrl) { + if ((wcscmp(info.url, pszUrl) == 0)) { return info; } } From d2d6d6f86ce1d09dcb488d10cad4d63c4c4c0cb4 Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Wed, 25 May 2016 15:00:36 -0700 Subject: [PATCH 4/8] Adding logic for navigation to final url --- src/MicrosoftEdgeLauncher.cpp | 41 ++++++++++++++++++++++------------- src/MicrosoftEdgeLauncher.h | 10 +++++---- src/stdafx.h | 1 + 3 files changed, 33 insertions(+), 19 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index 3d6b83d..99f7b56 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -3,7 +3,6 @@ #include #include #include -#include #include "Helpers.h" int _tmain(int argc, _TCHAR* argv[]) @@ -50,29 +49,32 @@ int _tmain(int argc, _TCHAR* argv[]) pszUrl = L"http://www.bing.com/"; } - DWORD pid = 0; - hr = LaunchEdge(pszUrl, pid); - - if (SUCCEEDED(hr) && bKeepAlive) - { - AttachLifeTime(pid); - } + hr = LaunchEdge(pszUrl, bKeepAlive); CoUninitialize(); return hr; } -HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid) +HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive) { PCWSTR pszAppUserModelId = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"; PCWSTR pszInitialUrl = L"http://www.bing.com/"; HRESULT hr; DWORD dwProcessID; - CComPtr spActivationManager; - hr = CoCreateInstance(CLSID_ApplicationActivationManager, /*punkOuter*/ nullptr, CLSCTX_INPROC_SERVER, IID_PPV_ARGS(&spActivationManager)); - hr = spActivationManager->ActivateApplication(pszAppUserModelId, pszInitialUrl, AO_NONE, &dwProcessID); + SHELLEXECUTEINFOW sei = { sizeof sei }; + sei.lpVerb = L"open"; + std::wstring wsUrl(pszUrl); + std::wstring concatted_stdstr = L"microsoft-edge:" + wsUrl; + sei.lpFile = concatted_stdstr.c_str(); + hr = ShellExecuteExW(&sei); + if (!SUCCEEDED(hr)) + { + ShowLastError(L"Failed to launch Microsoft Edge"); + return hr; + } + EdgeTargetInfo info; info = WatchForEdgeTab(pszInitialUrl); @@ -80,10 +82,18 @@ HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid) { return E_NOINTERFACE; } - else + + info.pDoc->put_URL(SysAllocString(pszUrl)); + + if(bKeepAlive) + { + hr = WaitForProcessToExit(info.pid); + return hr; + } + else { - pid = info.pid; return S_OK; + } return E_FAIL; @@ -124,7 +134,7 @@ HRESULT ShowLastError(_In_ PCWSTR pszErrorIntro) } -HRESULT AttachLifeTime(_In_ DWORD dwPid) +HRESULT WaitForProcessToExit(_In_ DWORD dwPid) { HRESULT hr = S_OK; DWORD dwResult; @@ -238,6 +248,7 @@ HRESULT EnumerateTargets(vector& vTargets) i.title = title; i.processName = processName; i.pid = processId; + i.pDoc = spDocument; vTargets.push_back(i); } } diff --git a/src/MicrosoftEdgeLauncher.h b/src/MicrosoftEdgeLauncher.h index 5f3dc2d..e33194e 100644 --- a/src/MicrosoftEdgeLauncher.h +++ b/src/MicrosoftEdgeLauncher.h @@ -1,19 +1,21 @@ #include "stdafx.h" #include -#include +#include -struct EdgeTargetInfo { +struct EdgeTargetInfo +{ HWND hwnd; PCWSTR title; PCWSTR url; PCWSTR processName; DWORD pid; + IHTMLDocument2 *pDoc; }; -HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _Out_ DWORD pid); +HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive); EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl); HRESULT EnumerateTargets(_Out_ std::vector& vTargets); -HRESULT AttachLifeTime(_In_ DWORD dwPid); +HRESULT WaitForProcessToExit(_In_ DWORD dwPid); void ShowHelp(); HRESULT ShowLastError(_In_ PCWSTR pszErrorIntro); int LifetimeTimeoutMs = INFINITE; diff --git a/src/stdafx.h b/src/stdafx.h index aa620ab..f84dc02 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -17,5 +17,6 @@ #include #include #include +#include using namespace std; From fe8915602d7e79930257471e573280fa6cbca24e Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Thu, 26 May 2016 13:16:38 -0700 Subject: [PATCH 5/8] Adding a random param to the initial url to navigate to --- src/MicrosoftEdgeLauncher.cpp | 52 ++++++++++++++++++++++------------- src/MicrosoftEdgeLauncher.h | 1 + src/stdafx.h | 2 ++ 3 files changed, 36 insertions(+), 19 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index 99f7b56..8ec1ff9 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -4,6 +4,7 @@ #include #include #include "Helpers.h" +#include int _tmain(int argc, _TCHAR* argv[]) { @@ -58,24 +59,28 @@ int _tmain(int argc, _TCHAR* argv[]) HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive) { - PCWSTR pszAppUserModelId = L"Microsoft.MicrosoftEdge_8wekyb3d8bbwe!MicrosoftEdge"; - PCWSTR pszInitialUrl = L"http://www.bing.com/"; + if(!bKeepAlive) + { + return LaunchEdgeViaShellExec(pszUrl); + } + HRESULT hr; DWORD dwProcessID; - SHELLEXECUTEINFOW sei = { sizeof sei }; - sei.lpVerb = L"open"; - std::wstring wsUrl(pszUrl); - std::wstring concatted_stdstr = L"microsoft-edge:" + wsUrl; - sei.lpFile = concatted_stdstr.c_str(); - hr = ShellExecuteExW(&sei); + std::srand(std::time(0)); + + int iRandomSeed = rand() % 1000 + 1; + wstringstream ss; + ss << L"http://example.com/?" << iRandomSeed; + wstring wsInitialUrl = ss.str(); + PCWSTR pszInitialUrl = wsInitialUrl.c_str(); + + hr = LaunchEdgeViaShellExec(pszInitialUrl); if (!SUCCEEDED(hr)) { - ShowLastError(L"Failed to launch Microsoft Edge"); return hr; } - - + EdgeTargetInfo info; info = WatchForEdgeTab(pszInitialUrl); if (info.pid == 0) @@ -85,18 +90,27 @@ HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive) info.pDoc->put_URL(SysAllocString(pszUrl)); - if(bKeepAlive) + hr = WaitForProcessToExit(info.pid); + return hr; +} + +HRESULT LaunchEdgeViaShellExec(PCWSTR pszUrl) +{ + HRESULT hr; + SHELLEXECUTEINFOW sei = { sizeof sei }; + sei.lpVerb = L"open"; + std::wstring wsUrl(pszUrl); + std::wstring concatted_stdstr = L"microsoft-edge:" + wsUrl; + sei.lpFile = concatted_stdstr.c_str(); + hr = ShellExecuteExW(&sei); + + if (!SUCCEEDED(hr)) { - hr = WaitForProcessToExit(info.pid); + ShowLastError(L"Failed to launch Microsoft Edge via shell execute"); return hr; } - else - { - return S_OK; - } - - return E_FAIL; + return hr; } void ShowHelp() diff --git a/src/MicrosoftEdgeLauncher.h b/src/MicrosoftEdgeLauncher.h index e33194e..59b9b31 100644 --- a/src/MicrosoftEdgeLauncher.h +++ b/src/MicrosoftEdgeLauncher.h @@ -13,6 +13,7 @@ struct EdgeTargetInfo }; HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive); +HRESULT LaunchEdgeViaShellExec(_In_ PCWSTR pszUrl); EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl); HRESULT EnumerateTargets(_Out_ std::vector& vTargets); HRESULT WaitForProcessToExit(_In_ DWORD dwPid); diff --git a/src/stdafx.h b/src/stdafx.h index f84dc02..910fc92 100644 --- a/src/stdafx.h +++ b/src/stdafx.h @@ -18,5 +18,7 @@ #include #include #include +#include +#include using namespace std; From aecbc4b8449c42d22421b42a48d97d344c7ee03f Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Thu, 26 May 2016 14:16:07 -0700 Subject: [PATCH 6/8] Adding logic to log all urls when no match is found --- src/MicrosoftEdgeLauncher.cpp | 57 +++++++++++++++++++++++------------ src/MicrosoftEdgeLauncher.h | 4 +-- 2 files changed, 38 insertions(+), 23 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index 8ec1ff9..b67628c 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -88,7 +88,25 @@ HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive) return E_NOINTERFACE; } - info.pDoc->put_URL(SysAllocString(pszUrl)); + if (info.pDoc == nullptr) + { + return E_NOINTERFACE; + } + + CComPtr spWindow; + hr = info.pDoc->get_parentWindow(&spWindow); + if (!SUCCEEDED(hr)) + { + ShowLastError(L"Failed to get the IHTMLWindow2"); + return hr; + } + + spWindow->navigate(SysAllocString(pszUrl)); + if (!SUCCEEDED(hr)) + { + ShowLastError(L"Failed to navigate to launch URL"); + return hr; + } hr = WaitForProcessToExit(info.pid); return hr; @@ -184,7 +202,8 @@ EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl) { EdgeTargetInfo info = { 0 }; int loopCounter = 0; - int waitTimeMS = 2000; + int waitTimeMS = 1000; + int maxTries = 20; do { @@ -202,8 +221,17 @@ EdgeTargetInfo WatchForEdgeTab(_In_ PCWSTR pszUrl) } } - if (loopCounter > 5) + if (loopCounter > maxTries) { + std::cout << "\nCouldn't find Edge URL with URL: " << pszUrl; + std::cout << "\nFound"; + + for (size_t i = 0; i < vTargets.size(); i++) + { + EdgeTargetInfo info = vTargets[i]; + std::cout << "\n" << info.url; + } + return{ 0 }; } } while (info.pid == 0); @@ -242,27 +270,16 @@ HRESULT EnumerateTargets(vector& vTargets) HRESULT hr = Helpers::GetDocumentFromHwnd(hwnd, spDocument); if (hr == S_OK) { - CComBSTR url; - hr = spDocument->get_URL(&url); - if (hr != S_OK) - { - url = L"unknown"; - } + EdgeTargetInfo i; + i.hwnd = hwnd; + i.pid = processId; + i.pDoc = spDocument; - CComBSTR title; - hr = spDocument->get_title(&title); + hr = spDocument->get_URL(&i.url); if (hr != S_OK) { - title = L""; + i.url = L"unknown"; } - - EdgeTargetInfo i; - i.hwnd = hwnd; - i.url = url; - i.title = title; - i.processName = processName; - i.pid = processId; - i.pDoc = spDocument; vTargets.push_back(i); } } diff --git a/src/MicrosoftEdgeLauncher.h b/src/MicrosoftEdgeLauncher.h index 59b9b31..27c7453 100644 --- a/src/MicrosoftEdgeLauncher.h +++ b/src/MicrosoftEdgeLauncher.h @@ -5,9 +5,7 @@ struct EdgeTargetInfo { HWND hwnd; - PCWSTR title; - PCWSTR url; - PCWSTR processName; + BSTR url; DWORD pid; IHTMLDocument2 *pDoc; }; From d016d9bbd7c9db02c5530212bff92ec4e73d40b7 Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Thu, 26 May 2016 14:39:37 -0700 Subject: [PATCH 7/8] Changing to use a CComPtr rather than a raw pointer that fell out of scope. whoops --- src/MicrosoftEdgeLauncher.cpp | 8 ++++---- src/MicrosoftEdgeLauncher.h | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index b67628c..202f77e 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -47,7 +47,7 @@ int _tmain(int argc, _TCHAR* argv[]) } else { - pszUrl = L"http://www.bing.com/"; + pszUrl = L"https://www.bing.com/"; } hr = LaunchEdge(pszUrl, bKeepAlive); @@ -88,13 +88,13 @@ HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive) return E_NOINTERFACE; } - if (info.pDoc == nullptr) + if (info.spDoc == nullptr) { return E_NOINTERFACE; } CComPtr spWindow; - hr = info.pDoc->get_parentWindow(&spWindow); + hr = info.spDoc->get_parentWindow(&spWindow); if (!SUCCEEDED(hr)) { ShowLastError(L"Failed to get the IHTMLWindow2"); @@ -273,7 +273,7 @@ HRESULT EnumerateTargets(vector& vTargets) EdgeTargetInfo i; i.hwnd = hwnd; i.pid = processId; - i.pDoc = spDocument; + i.spDoc = spDocument; hr = spDocument->get_URL(&i.url); if (hr != S_OK) diff --git a/src/MicrosoftEdgeLauncher.h b/src/MicrosoftEdgeLauncher.h index 27c7453..258751a 100644 --- a/src/MicrosoftEdgeLauncher.h +++ b/src/MicrosoftEdgeLauncher.h @@ -7,7 +7,7 @@ struct EdgeTargetInfo HWND hwnd; BSTR url; DWORD pid; - IHTMLDocument2 *pDoc; + CComPtr spDoc; }; HRESULT LaunchEdge(_In_ PCWSTR pszUrl, _In_ BOOL bKeepAlive); From ef3d92f850de37fc370087771a0f3331393803be Mon Sep 17 00:00:00 2001 From: Andy Sterland Date: Thu, 26 May 2016 16:56:41 -0700 Subject: [PATCH 8/8] Updating help comments --- src/MicrosoftEdgeLauncher.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/MicrosoftEdgeLauncher.cpp b/src/MicrosoftEdgeLauncher.cpp index 202f77e..006010c 100644 --- a/src/MicrosoftEdgeLauncher.cpp +++ b/src/MicrosoftEdgeLauncher.cpp @@ -41,7 +41,7 @@ int _tmain(int argc, _TCHAR* argv[]) { std::cout << "Error: Expecting -k got: \n " << argv[2]; std::cout << "\n"; - std::cout << "Use -h for usage info."; + std::cout << "\nUse -h for usage info."; hr = E_ABORT; } } @@ -140,10 +140,8 @@ void ShowHelp() std::cout << "\n"; std::cout << "\tMicrosoftEdgeLauncher.exe [url] -k"; std::cout << "\n"; - std::cout << "\n"; - std::cout << "\turl - The URL to open in Microsoft Edge."; - std::cout << "\t-k - Keep this program alive for as long as the launched process is alive."; - std::cout << "\n"; + std::cout << "\nurl - The URL to open in Microsoft Edge."; + std::cout << "\n-k - Keep this program alive for as long as the launched process is alive."; std::cout << "\n"; }