How can I add an environment variable to a process launched via ShellExecuteEx or IContextMenu?

Adding Environment Variables to a Process Launched via ShellExecuteEx or IContextMenu
To add an environment variable to a process launched via ShellExecuteEx
or IContextMenu
, you can leverage a custom site and the IShellExecuteHook
interface. This interface allows you to customize the creation of processes by adding a site object that can modify the execution process.
Here is an example in C++ using the C++/WinRT library:
// Create a custom site that sets an environment variable
struct CustomSite : winrt::implements<CustomSite, winrt::IUnknown, IShellExecuteHook>
{
HRESULT STDMETHODCALLTYPE Execute(
IUnknown* pUnknown,
LPCWSTR pszWorkingDir,
LPCWSTR pszCmdLine,
LPCWSTR pszEnvVar)
{
// Set the environment variable
SetEnvironmentVariable(pszEnvVar, L"custom_value");
// Return the result of the original Execute method
return pUnknown->QueryInterface<IShellExecuteHook>()->Execute(
pszWorkingDir, pszCmdLine, pszEnvVar);
}
};
// Launch a process via ShellExecuteEx and pass a custom site
SHELLEXECUTEINFO sei = { sizeof(sei) };
sei.fMask = SEE_MASK_HMONITOR;
sei.lpVerb = L"runas";
sei.lpFile = L"notepad.exe";
sei.lpParameters = L"";
sei.hwnd = hwnd;
sei.nShow = SW_SHOWDEFAULT;
sei.hInstApp = GetModuleHandle(NULL);
sei.lpIDList = NULL;
sei.lpClass = NULL;
sei.hkeyClass = NULL;
sei.dwHotKey = 0;
sei.hIcon = NULL;
sei.hMonitor = NULL;
sei.pfnHook = nullptr; // Remove existing hook
sei.lpfnHook = [](HWND, UINT, WPARAM, LPARAM) -> HRESULT
{
// Create and return the custom site
return winrt::make<CustomSite>().as<IShellExecuteHook>().copy_to(INT_PTR(&sei.pfnHook));
};
// Execute the process
BOOL success = ShellExecuteEx(&sei);
This code creates a custom site (implemented as CustomSite
) that sets an environment variable (pszEnvVar
) with a custom value. It then calls the original Execute
method to proceed with the execution of the process.
To pass the custom site to ShellExecuteEx
, we assign it to the SHELLEXECUTEINFO
struct's pfnHook
member. We also set the SEE_MASK_HMONITOR
flag to indicate that our pfnHook
member contains a valid hook function.
For IContextMenu
usage, you need to explicitly set your custom site as the context menu's site.
Remember that this code is just a starting point, and you should handle exceptions and memory management appropriately in a real application.