Jumplist in Windows 10 failing - c++

I'm using the below code to have the taskbar jumplist open the users default browser at certain pages.
Everything has been working fine for about a year now on Win 7/8 but with Windows 10 the browser is not called when the taskbar task is clicked and the Microsoft documentation shows no changes from Win 8 to 10.
bool SetUpJumpList( )
{
HRESULT hr;
CComPtr<ICustomDestinationList> pDestList;
hr = pDestList.CoCreateInstance ( CLSID_DestinationList , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
hr = pDestList->SetAppID ( _TBID );
if ( FAILED ( hr ) )
{
return false;
}
UINT cMaxSlots;
CComPtr<IObjectArray> pRemovedItems;
hr = pDestList->BeginList ( &cMaxSlots , IID_PPV_ARGS ( &pRemovedItems ) );
if ( FAILED ( hr ) )
{
return false;
}
CComPtr<IObjectCollection> pObjColl;
hr = pObjColl.CoCreateInstance ( CLSID_EnumerableObjectCollection , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
if ( !AddJumpListTasks ( pObjColl ) )
{
return false;
}
CComQIPtr<IObjectArray> pTasksArray = pObjColl;
if ( !pTasksArray )
{
return false;
}
hr = pDestList->AddUserTasks ( pTasksArray );
if ( FAILED ( hr ) )
{
return false;
}
hr = pDestList->CommitList( );
return SUCCEEDED ( hr );
}
bool AddJumpListTasks ( IObjectCollection* pObjColl )
{
wchar_t pBuf[ MAX_PATH ];
int bytes = GetModuleFileName ( NULL , pBuf , MAX_PATH );
CJumpListTask aTasks[ ] =
{
{ _T ( "https://www.google.co.uk" ) , _T ( "Home Page" ) , _T ( "Home" ) , 0 },
{ _T ( "https://www.google.co.uk" ) , _T ( "Twitter Page" ) , _T ( "Twitter" ) , 9 },
{ _T ( "https://www.google.co.uk" ) , _T ( "Facebook Page" ) , _T ( "Facebook" ) , 10 }
};
CString strBrowser;
DWORD size = 1024;
AssocQueryString ( 0 , ASSOCSTR_EXECUTABLE , L"http" , L"Open" , strBrowser.GetBufferSetLength ( size ) , &size );
for ( int i = 0; i < _countof ( aTasks ); i++ )
{
if ( !AddJumpListTask ( pObjColl , aTasks[ i ] , strBrowser , pBuf ) )
{
strBrowser.ReleaseBuffer( );
return false;
}
}
strBrowser.ReleaseBuffer( );
return true;
}
bool AddJumpListTask ( IObjectCollection* pObjColl , const CJumpListTask& rTask , LPCTSTR szExePath , LPCTSTR pBuf )
{
HRESULT hr;
CComPtr<IShellLink> pLink;
hr = pLink.CoCreateInstance ( CLSID_ShellLink , NULL , CLSCTX_INPROC_SERVER );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetPath ( szExePath );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetArguments ( rTask.szArgs );
if ( FAILED ( hr ) )
{
return false;
}
hr = pLink->SetIconLocation ( pBuf , rTask.nIconIndex );
if ( FAILED ( hr ) )
{
return false;
}
CComQIPtr<IPropertyStore> pPropStore = pLink;
PROPVARIANT pv;
if ( !pPropStore )
{
return false;
}
hr = InitPropVariantFromString ( CT2CW ( rTask.szTitle ) , &pv );
if ( FAILED ( hr ) )
{
return false;
}
hr = pPropStore->SetValue ( PKEY_Title , pv );
PropVariantClear ( &pv );
if ( FAILED ( hr ) )
{
return false;
}
hr = pPropStore->Commit( );
if ( FAILED ( hr ) )
{
return false;
}
hr = pObjColl->AddObject ( pLink );
return SUCCEEDED ( hr );
}
I've noticed several other applications such as CCleaner that also use this method do not function either but Microsoft applications such as Office 2013 still work so the question is how do I get this running again on Windows 10?
I'm certain this is not related to the customDestinations-ms files stored in the CustomDestinations folder as with a clean install of Windows 10 the same non functionality appears.
The taskbar task menu is created with the desired text and icon and debugging shows the correct URL is added along with the correct default browser and browser path.
Edit:
Using Visual Studio 2015 with toolset Windows XP v140_xp

As a workaround you could use, if possible for you, the MFC Class "CJumplist" from the latest Windows SDK.
We found out it would fix this issue, but only if using the latest SDK version. Using an older SDK using the same MFC class (eg Windows 7 SDK) would cause exactly the same issues you are experiencing.
This is a sample code working on Windows 10 with VC2013 and latest SDK (Target v12.0), but only when using MFC in a shared Dll. Linking with a static MFC Dll does not seem to work.
CJumpList *pJumpList = new CJumpList();
pJumpList->SetAppID(m_pszAppID);
result = pJumpList->AddTask(szPath, _T("-data1"), _T("number 4"), szPath, 0);
result = pJumpList->AddTask(szPath, _T("-data2"), _T("number 5"), szPath, 0);
pJumpList->CommitList();
delete pJumpList;
I do not know what changes Microsoft developers have done in this class to make it work. Our pure Win32 code suffers the same issues as you reported.

A little update to this, a reinstall of Windows due to other issues followed by a reinstall of VS but not checking the XP compatibility options results in the Jumplists working again, I dont need XP support anyhow but I assume this issue is related to the XP library's.

Related

Crash in DuplicateOutput

I'm developing an application which captures frames using DXGI mechanism from an application.
First creation of the IDXGIOutputDuplication is correct. When the application changes its display (for example from fullscreen to windowed or vice versa), the frame acquire failed (expected behaviour), then I recreate the IDXGIOutputDuplication and regularly the call to DuplicateOutput crash.
Below creation of the D3d11 device:
D3D_FEATURE_LEVEL FeatureLevels[] =
{
D3D_FEATURE_LEVEL_11_1,
D3D_FEATURE_LEVEL_11_0,
D3D_FEATURE_LEVEL_10_1,
D3D_FEATURE_LEVEL_10_0,
D3D_FEATURE_LEVEL_9_1
};
UINT NumFeatureLevels = ARRAYSIZE( FeatureLevels );
D3D_FEATURE_LEVEL FeatureLevel = D3D_FEATURE_LEVEL_11_1;
D3D11CreateDevice( _pDxgiAdapter, D3D_DRIVER_TYPE_UNKNOWN, nullptr, 0, FeatureLevels, NumFeatureLevels, D3D11_SDK_VERSION, &_pD3D11Device, &FeatureLevel, &_pD3D11DeviceCtx );
_pDxgiAdapter is created before the device.
Below creation of the IDXGIOutputDuplication:
int DxgiVideoCapture::open() {
findDxgiAdapter();
if( nullptr != _pDxgiAdapter ) {
// Duplicate output
uint32_t ui32OutputIndex = 0;
HRESULT hr = S_OK;
while( SUCCEEDED( hr ) ) {
IDXGIOutput* pDxgiOutput = nullptr;
hr = _pDxgiAdapter->EnumOutputs( ui32OutputIndex, &pDxgiOutput );
if( SUCCEEDED( hr ) ) {
IDXGIOutput1* pDxgiOutput1 = nullptr;
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&pDxgiOutput1 ) ) ) {
uint32_t ui32EnumMode = 0;
uint32_t ui32Flags = 0xffffffff;
}
if( SUCCEEDED ( pDxgiOutput->QueryInterface( __uuidof( IDXGIOutput1 ), ( void** )&_pDxgiOutput1 ) ) ) {
LOGI( "/!\\ Call which crash regularly /!\\" );
HRESULT hrDup = _pDxgiOutput1->DuplicateOutput( _pD3D11Device, &_pOutputDuplication );
if( SUCCEEDED( hrDup ) ) {
LOGI( "Output duplication created." );
} else {
switch( hrDup ) {
case E_INVALIDARG :
{
LOGW( "Invalid device or output already duplicated" );
}
break;
case E_ACCESSDENIED :
{
LOGW( "Access denied" );
}
break;
case DXGI_ERROR_UNSUPPORTED :
{
LOGW( "DXGI_ERROR_UNSUPPORTED" );
}
break;
case DXGI_ERROR_NOT_CURRENTLY_AVAILABLE :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
case DXGI_ERROR_SESSION_DISCONNECTED :
{
LOGW( "DXGI_ERROR_NOT_CURRENTLY_AVAILABLE" );
}
break;
default:
{
LOGW( "default" );
}
}
} else {
LOGE( "Unable to retrieve interface creating the ouput duplication" );
}
}
pDxgiOutput->Release();
}
ui32OutputIndex++;
}
return RET_OK;
}
Below the frame acquisition:
int DxgiVideoCapture::captureGameFrame() {
int iRet = RET_ERROR;
ID3D11Texture2D* pCapturedTexture = nullptr;
DXGI_OUTDUPL_FRAME_INFO frameInfo;
ZeroMemory(&frameInfo, sizeof(frameInfo));
HRESULT hr = _pOutputDuplication->AcquireNextFrame( 1000, &frameInfo, &_pDxgiResource );
if( FAILED( hr ) ) {
if( hr == DXGI_ERROR_WAIT_TIMEOUT ) {
LOGW( "Wait for %d ms timed out", 1000);
}
if (hr == DXGI_ERROR_INVALID_CALL) {
LOGW( "Invalid Call, previous frame not released?" );
}
if (hr == DXGI_ERROR_ACCESS_LOST) {
LOGW( "Error Access lost - is it a game end ?" );
}
iRet = RET_RESET_CAPTURE;
return iRet;
}
if( FAILED( hr = _pDxgiResource->QueryInterface( __uuidof( ID3D11Texture2D ), ( void** ) &pCapturedTexture ) ) ) {
LOGW( "unable to retrieve D3D11 texture 0x%x", hr );
return RET_WARNING;
} else {
// Store window of the game
D3D11_TEXTURE2D_DESC d3D11TextureDesc;
pCapturedTexture->GetDesc( &d3D11TextureDesc );
// Compute the zone to extract.
D3D11_BOX srcBox;
memset( &srcBox, 0, sizeof( srcBox ) );
if( _pGameWindow->getLeftPos() > 0 ) {
srcBox.left = _pGameWindow->getLeftPos();
}
if( _pGameWindow->getTopPos() > 0 ) {
srcBox.top = _pGameWindow->getTopPos();
}
srcBox.front = 0;
srcBox.right = _pGameWindow->getLeftPos() + _pGameWindow->getWidth();
if( srcBox.right > _pGameWindow->getMonitorWidth() ) {
srcBox.right = _pGameWindow->getMonitorWidth();
}
if( ( srcBox.right - srcBox.left ) % 2 != 0 ) {
srcBox.right--;
}
srcBox.bottom = _pGameWindow->getTopPos() + _pGameWindow->getHeight();
if( srcBox.bottom > _pGameWindow->getMonitorHeight() ) {
srcBox.bottom = _pGameWindow->getMonitorHeight();
}
if( ( srcBox.bottom - srcBox.top ) % 2 != 0 ) {
srcBox.bottom--;
}
srcBox.back = 1;
// AVFrame info are udpate just when the captured game window and the texture are diffrent.
// In the same time texture is reallocated.
if( ( ( srcBox.right - srcBox.left ) != _CapturedTextureDesc.Width )
|| ( ( srcBox.bottom - srcBox.top ) != _CapturedTextureDesc.Height )
) {
LOGD( "Game window: %dx%d ; %d->%d", _pGameWindow->getLeftPos(), _pGameWindow->getTopPos(), _pGameWindow->getWidth(), _pGameWindow->getHeight() );
LOGD( "Texture creation %dx%d -> %dx%d", srcBox.left, srcBox.top, srcBox.right, srcBox.bottom );
// Create the new texture
iRet = createCapturedTexture( srcBox.right - srcBox.left, srcBox.bottom - srcBox.top );
}
DirectX11Util::GetInstance()->getD3D11DeviceContext()->CopySubresourceRegion( _pGameTexture, 0, 0, 0, 0, pCapturedTexture, 0, &srcBox );
}
if( nullptr != _pDxgiResource ) {
_pOutputDuplication->ReleaseFrame();
pCapturedTexture->Release();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
iRet = RET_OK;
return iRet;
}
Below the release of the D3d11 capture before recreation of the IDXGIOutputDuplication:
int DxgiVideoCapture::close() {
if( nullptr != _pGameTexture ) {
ZeroMemory( &_CapturedTextureDesc, sizeof( D3D11_TEXTURE2D_DESC ) );
_pGameTexture->Release();
_pGameTexture = nullptr;
}
if( nullptr != _pDxgiResource ){
_pOutputDuplication->ReleaseFrame();
_pDxgiResource->Release();
_pDxgiResource = nullptr;
}
if( nullptr != _pOutputDuplication ) {
_pOutputDuplication->Release();
_pOutputDuplication = nullptr;
}
return RET_OK;
}
What I would like to know is how can I invest this crash (application ends without any message). To be more accurate I cross compile my application, but the behaviour seems the same. Do you have any idea how to invest this issue ?
Tell me if you want more details.
Thanks in advance !

Shell Extension: IShellExtInit::Initialize called 4 times

I've run into a situation that is not so unique (others have been asking exact same question) Offsite similar question..
Basically, for some reason, the code in IShellExtInit::Initialize implementation that is supposed to be invoked once after each right-click on a file, ends up being invoked 4 times.
STDMETHODIMP My_ShellExtInit::Initialize (LPCITEMIDLIST pidlFolder, LPDATAOBJECT pDataObj, HKEY hProgID ) {
FORMATETC fmt = { CF_HDROP, NULL, DVASPECT_CONTENT,
-1, TYMED_HGLOBAL };
STGMEDIUM stg = { TYMED_HGLOBAL };
HDROP hDrop;
if ( FAILED( pDataObj->GetData ( &fmt, &stg ) ))
return E_INVALIDARG;
hDrop = (HDROP) GlobalLock ( stg.hGlobal );
if ( NULL == hDrop )
return E_INVALIDARG;
UINT uNumFiles = DragQueryFile ( hDrop, 0xFFFFFFFF, NULL, 0 );
HRESULT hr = S_OK;
if ( 0 == uNumFiles ) {
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return E_INVALIDARG;
}
if ( 0 == DragQueryFile ( hDrop, 0, m_szFile, MAX_PATH ) )
hr = E_INVALIDARG;
system("echo INVOKED >> log.txt");
// QMessageBox::warning(NULL, "Foo!", TCHARToQString(m_szFile));
GlobalUnlock ( stg.hGlobal );
ReleaseStgMedium ( &stg );
return hr;
}
Depending on the file/type, your context menu handler is called multiple times:
for the file/folder itself
for the parent folder of the file
for the folder background
in case of a *.lnk file also for the target it points to
And if explorer shows the tree view, then that part also calls your handler.

Firewall exception code just works for outgoing connections

I took this code from the web to add a firewall exception for my application:
STDAPI AddApplicationToExceptionListW( const WCHAR* strGameExeFullPath, const WCHAR* strFriendlyAppName )
{
HRESULT hr = E_FAIL;
bool bCleanupCOM = false;
BSTR bstrFriendlyAppName = NULL;
BSTR bstrGameExeFullPath = NULL;
INetFwAuthorizedApplication* pFwApp = NULL;
INetFwAuthorizedApplications* pFwApps = NULL;
INetFwProfile* pFwProfile = NULL;
#ifdef SHOW_DEBUG_MSGBOXES
WCHAR sz[1024];
StringCchPrintf( sz, 1024, L"strFriendlyAppName='%s' strGameExeFullPath='%s'", strFriendlyAppName, strGameExeFullPath );
MessageBox( NULL, sz, L"AddApplicationToExceptionListW", MB_OK );
#endif
if( strGameExeFullPath == NULL || strFriendlyAppName == NULL )
{
assert( false );
return E_INVALIDARG;
}
bstrGameExeFullPath = SysAllocString( strGameExeFullPath );
bstrFriendlyAppName = SysAllocString( strFriendlyAppName );
if( bstrGameExeFullPath == NULL || bstrFriendlyAppName == NULL )
{
hr = E_OUTOFMEMORY;
goto LCleanup;
}
hr = CoInitialize( 0 );
bCleanupCOM = SUCCEEDED( hr );
pFwProfile = GetFirewallProfile();
if( pFwProfile == NULL )
{
hr = E_FAIL;
goto LCleanup;
}
hr = pFwProfile->get_AuthorizedApplications( &pFwApps );
if( FAILED( hr ) )
goto LCleanup;
// Create an instance of an authorized application.
hr = CoCreateInstance( __uuidof( NetFwAuthorizedApplication ), NULL,
CLSCTX_INPROC_SERVER, __uuidof( INetFwAuthorizedApplication ), ( void** )&pFwApp );
if( FAILED( hr ) )
goto LCleanup;
// Set the process image file name.
hr = pFwApp->put_ProcessImageFileName( bstrGameExeFullPath );
if( FAILED( hr ) )
goto LCleanup;
// Set the application friendly name.
hr = pFwApp->put_Name( bstrFriendlyAppName );
if( FAILED( hr ) )
goto LCleanup;
// Add the application to the collection.
hr = pFwApps->Add( pFwApp );
LCleanup:
if( bstrFriendlyAppName ) SysFreeString( bstrFriendlyAppName );
if( bstrGameExeFullPath ) SysFreeString( bstrGameExeFullPath );
if( pFwApp ) pFwApp->Release();
if( pFwApps ) pFwApps->Release();
if( pFwProfile ) pFwProfile->Release();
if( bCleanupCOM ) CoUninitialize();
return hr;
}
Everything works great when I try to send data through the Windows firewall, but incoming connections are still blocked. So I have to disable my firewall to recieve data. I thought, that exception would allow all connections (outgoing and incoming)...
Does somebody know what I should add to this code so I can recieve incoming data?
It is not enough to just add the application by itself. The firewall has no way of discovering which port(s) the application is listening on for inbound connections. You have to tell the firewall which port(s) the application is using. You do that via the INetFwProfile::GloballyOpenPorts collection, eg:
INetFwOpenPorts *pFwPorts = NULL;
INetFwOpenPort *pFWPort = NULL;
...
hr = pFwProfile->get_GloballyOpenPorts( &pFwPorts );
if( FAILED( hr ) )
goto LCleanup;
// Create an instance of an open port.
hr = CoCreateInstance( __uuidof( NetFwOpenPort ), NULL, CLSCTX_INPROC_SERVER, __uuidof( INetFwOpenPort ), ( void** )&pFwPort );
if( FAILED( hr ) )
goto LCleanup;
// Set the port number.
hr = pFWPort->put_Port( ... );
if( FAILED( hr ) )
goto LCleanup;
// Add the port to the collection.
hr = pFwPorts->Add( pFwPort );
...
if( pFwPort ) pFwPort->Release();
if( pFwPorts ) pFwPorts->Release();
In my case the solution was deleting the firewall rules that blocked my application. I don't know where these rules came from, but now it finally works.

Obtaining the Excel.Application IDispatch* within a dll that's been loaded into Excel

Does anyone know how to get hold of the Excel.Application IDispatch* pointer associated with an excel process into which an dll has been loaded?
A key thing here is that the process is excel.exe, and the pointer I need must belong to that process. Using the Running Object Table will not fly since Excel only registers its first instance with that.
I'm hoping there is some low-level COM trickery, but I'm not an expert in that field.
EDITED II Code is under the WTFPL license version 2.
EDITED: Add PID parameter to allow filtering when several Excel processes are currently running, as per comment suggestion from #EricBrown.
I managed to get a working IDispatch* to an Excel "Application" object without using the ROT. The trick is to use MSAA. My code works as a stand alone console application, but I think that if the code is executed in an Excel process, via DLL Injection, it MAY works fine. You may have to be in a dedicated thread. Let me know if you want me to push the expriment to the DLL injection level.
Tested OK on Window7 64b, with a UNICODE builds (32 bits and 64 bits).
Excel version 2010 64 bits (version "14")
I get the IDispatch via the "application" property from an "Worksheet" object. Consequence: there must be an opened worksheet. In order to find the good MSSA Window, I need the class name of the Top Level Excel Frame Window. In Excel 2010, it's "XLMAIN". The class name for worksheets is "EXCEL7" and that seems to be a "standard".
I was not able to directly get a working IDispatch* from the main Excel Window, but have not tried very hard. That may involve #import with a automation DLL from Excel, in order to QueryInterface the IDispatch that MSAA gives for the main Window (that IDispatch is NOT for an Application object)
#include <atlbase.h>
#pragma comment( lib, "Oleacc.lib" )
HRESULT GetExcelAppDispatch( CComPtr<IDispatch> & spIDispatchExcelApp, DWORD dwExcelPID ) {
struct ew {
struct ep {
_TCHAR* pszClassName;
DWORD dwPID;
HWND hWnd;
};
static BOOL CALLBACK ewp( HWND hWnd, LPARAM lParam ) {
TCHAR szClassName[ 64 ];
if ( GetClassName( hWnd, szClassName, 64 ) ) {
ep* pep = reinterpret_cast<ep*>( lParam );
if ( _tcscmp( szClassName, pep->pszClassName ) == 0 ) {
if ( pep->dwPID == 0 ) {
pep->hWnd = hWnd;
return FALSE;
} else {
DWORD dwPID;
if ( GetWindowThreadProcessId( hWnd, &dwPID ) ) {
if ( dwPID == pep->dwPID ) {
pep->hWnd = hWnd;
return FALSE;
}
}
}
}
}
return TRUE;
}
};
ew::ep ep;
ep.pszClassName = _TEXT( "XLMAIN" );
ep.dwPID = dwExcelPID;
ep.hWnd = NULL;
EnumWindows( ew::ewp, reinterpret_cast<LPARAM>( &ep ) );
HWND hWndExcel = ep.hWnd;
if ( ep.hWnd == NULL ) {
printf( "Can't Find Main Excel Window with EnumWindows\n" );
return -1;
}
ep.pszClassName = _TEXT( "EXCEL7" );
ep.dwPID = 0;
ep.hWnd = NULL;
EnumChildWindows( hWndExcel, ew::ewp, reinterpret_cast<LPARAM>( &ep ) );
HWND hWndWorkSheet = ep.hWnd;
if ( hWndWorkSheet == NULL ) {
printf( "Can't Find a WorkSheet with EnumChildWindows\n" );
return -1;
}
CComPtr<IDispatch> spIDispatchWorkSheet;
HRESULT hr = AccessibleObjectFromWindow( hWndWorkSheet, OBJID_NATIVEOM, IID_IDispatch,
reinterpret_cast<void**>( &spIDispatchWorkSheet ) );
if ( FAILED( hr ) || ( spIDispatchWorkSheet == 0 ) ) {
printf( "AccessibleObjectFromWindow Failed\n" );
return hr;
}
CComVariant vExcelApp;
hr = spIDispatchWorkSheet.GetPropertyByName( CComBSTR( "Application" ), &vExcelApp );
if ( SUCCEEDED( hr ) && ( vExcelApp.vt == VT_DISPATCH ) ) {
spIDispatchExcelApp = vExcelApp.pdispVal;
return S_OK;
}
return hr;
}
int _tmain(int argc, _TCHAR* argv[])
{
DWORD dwExcelPID = 0;
if ( argc > 1 ) dwExcelPID = _ttol( argv[ 1 ] );
HRESULT hr = CoInitialize( NULL );
bool bCoUnInitializeTodo = false;
if ( SUCCEEDED( hr ) ) {
bCoUnInitializeTodo = true;
CComPtr<IDispatch> spDispatchExcelApp;
hr = GetExcelAppDispatch( spDispatchExcelApp, dwExcelPID );
if ( SUCCEEDED( hr ) && spDispatchExcelApp ) {
CComVariant vExcelVer;
hr = spDispatchExcelApp.GetPropertyByName( CComBSTR( "Version" ), &vExcelVer );
if ( SUCCEEDED( hr ) && ( vExcelVer.vt == VT_BSTR ) ) {
wprintf( L"Excel Version is %s\n", vExcelVer.bstrVal );
}
}
}
if ( bCoUnInitializeTodo ) CoUninitialize();
return 0;
}
You should be able to find out how to do this by reviewing the code in ExcelDNA. This project contains code that hooks back into Excel from the extension library. The code is likely to be more elaborate that you need, but will implement the reference you require.
This is how I do it: (acknowledge #manuell). dispatch_wrapper is a class, here is the constructor to set m_disp_application:
dispatch_wrapper(void)
{
DWORD target_process_id = ::GetProcessId(::GetCurrentProcess());
if (getProcessName() == "excel.exe"){
HWND hwnd = ::FindWindowEx(0, 0, "XLMAIN", NULL);
while (hwnd){
DWORD process_id;
::GetWindowThreadProcessId(hwnd, &process_id);
if (process_id == target_process_id){
HWND hwnd_desk = ::FindWindowEx(hwnd, 0, "XLDESK", NULL);
HWND hwnd_7 = ::FindWindowEx(hwnd_desk, 0, "EXCEL7", NULL);
IDispatch* p = nullptr;
if (SUCCEEDED(::AccessibleObjectFromWindow(hwnd_7, OBJID_NATIVEOM, IID_IDispatch, (void**)&p))){
LPOLESTR name[1] = {L"Application"};
DISPID dispid;
if (SUCCEEDED(p->GetIDsOfNames(IID_NULL, name, 1U, LOCALE_SYSTEM_DEFAULT, &dispid))){
CComVariant v;
DISPPARAMS dp;
::memset(&dp, NULL, sizeof(DISPPARAMS));
EXCEPINFO ei;
::memset(&ei, NULL, sizeof(EXCEPINFO));
if (SUCCEEDED(p->Invoke(dispid, IID_NULL, LOCALE_SYSTEM_DEFAULT, DISPATCH_PROPERTYGET, &dp, &v, &ei, NULL))){
if (v.vt == VT_DISPATCH){
m_disp_application = v.pdispVal;
m_disp_application->AddRef();
return;
}
}
}
}
}
hwnd = ::FindWindowEx(0, hwnd, "XLMAIN", NULL);
}
}
m_disp_application = nullptr;
}
getProcessName() returns lower case.
Because Office applications register their documents in the ROT, you can attach to instances beside the first one (which is already in the ROT) by getting IDispatch for documents in the ROT, then you can use document.Application.hwnd (this is VBA, you need to translate to IDispatch::GetIDsOfNames and IDispatch::Invoke with DISPATCH_PROPERTYGET) to get the window handles of all Excel instances.
Now you have a mapping between IDispatch and Windows handles of all Excel instances, it is time to find your own Excel instance. You can call GetWindowThreadProcessId on the window handles to get the process ids, then compare to your own process id returned by GetCurrentProcessId to see which excel window belongs to your current process, and look up in the HWND to IDispatch mapping to find your current Excel application's IDispatch interface.

How to pin Application icon to the metro start screen in windows 8 programmatically

How can I pin application icon to metro start screen in win8 programmatically(c++)? I know how to do it manually. I also know that it will be added automatically once I launch that application.
I found this solution here
BOOL PinToStart( LPCWSTR szFilePath )
{
BOOL bSuccess = FALSE;
// break into file name and path
WCHAR lpszDirectoryName[ MAX_PATH ] = { 0 };
LPCWSTR lpszFileName = ::PathFindFileName( szFilePath );
wcscpy_s( lpszDirectoryName, szFilePath );
::PathRemoveFileSpec( lpszDirectoryName );
// load shell32.dll
HMODULE hShell32 = LoadLibrary( L"SHELL32" );
if( hShell32 != NULL )
{
// get the localized translation of 'Pin to Start' verb
WCHAR szPinToStartLocalized[ MAX_PATH ] = { 0 };
int nPinToStartLocalizedLength = LoadString( (HINSTANCE)hShell32, 51201, szPinToStartLocalized, MAX_PATH );
if( nPinToStartLocalizedLength > 0 )
{
// create the shell object
IShellDispatch *pShellDispatch = NULL;
HRESULT hr = CoCreateInstance(CLSID_Shell, NULL, CLSCTX_INPROC_SERVER, IID_IShellDispatch, (void**)&pShellDispatch);
if( SUCCEEDED( hr ) )
{
Folder *pFolder = NULL;
variant_t vaDirectory( lpszDirectoryName );
// get the namespace
if( SUCCEEDED( pShellDispatch->NameSpace( vaDirectory, &pFolder ) ) )
{
FolderItem *pItem = NULL;
bstr_t vaFileName( lpszFileName );
// parse the name
if( SUCCEEDED( pFolder->ParseName( vaFileName, &pItem ) ) )
{
FolderItemVerbs* pVerbs = NULL;
// get the verbs
if( SUCCEEDED( pItem->Verbs(&pVerbs) ) )
{
long nCount = 0;
if( SUCCEEDED ( pVerbs->get_Count( &nCount ) ) )
{
variant_t vaIndex;
vaIndex.vt = VT_I4;
// iterate through verbs
for( vaIndex.lVal = 0; vaIndex.lVal<nCount; vaIndex.lVal++ )
{
FolderItemVerb* pVerb = NULL;
if( SUCCEEDED( pVerbs->Item( vaIndex, &pVerb ) ) )
{
BSTR bstrVerbName = NULL;
// check for 'Pin to Start' verb
if( SUCCEEDED( pVerb->get_Name( &bstrVerbName ) ) )
{
if( 0 == wcscmp( bstrVerbName, szPinToStartLocalized ) )
{
bSuccess = SUCCEEDED( pVerb->DoIt() );
vaIndex.lVal = nCount; // break for
}
::SysFreeString( bstrVerbName );
}
pVerb->Release();
} // if
} // for
}
pVerbs->Release();
}
pItem->Release();
}
pFolder->Release();
}
pShellDispatch->Release();
}
}
::FreeLibrary( hShell32 );
}
return bSuccess;
}
Hope it's help you