This is a PR for an uwp text editor app where I am implementing desktop extension to give user choice of opening file for which association not declared in manifest. User can choose to open the file with the extension which then launches the file with the uwp app. However I am having following issues:
StorageFile.GetFileFromPathAsync()
doesn't work for hidden files. Trying to handle file activation using this article gives following error:
System.Exception HResult=0xD0000225 Message=The text associated with this error code could not be found.
The text associated with this error code could not be found.
Source=Windows.ApplicationModel StackTrace: at Windows.ApplicationModel.AppInstance.GetActivatedEventArgs()
Launcher.LaunchFileAsync()
doesn't work for unsupported extensions.Any help regarding these issues??
In Windows 10 2004 (build 19041) microsoft introduced uap10:FileType
attribute in package manifest and by providing *
as the value the app is available in open with menu of all types of files even files without any extension. To use this just add the following code to your manifest:
xmlns:uap10="http://schemas.microsoft.com/appx/manifest/uap/windows10/10"
...
<uap:Extension Category="windows.fileTypeAssociation">
<uap:FileTypeAssociation Name="anyfile">
<uap:Logo>Assets\mylogo.png</uap:Logo>
<uap:SupportedFileTypes>
<uap:FileType>.txt</uap:FileType>
<uap10:FileType>*</uap10:FileType>
</uap:SupportedFileTypes>
</uap:FileTypeAssociation>
</uap:Extension>
This only works for Windows 10 build 19041 and above. The additional uap:FileType
is necessary if app targets minimum version below 19041 to pass manifest validation, otherwise it can be omitted.
For Windows 10 version older than build 19041, a desktop component can be provided that uses IApplicationActivationManager::ActivateForFile
to redirect file activation to UWP app. The sample code in C++/WinRT looks like this:
init_apartment();
LPWSTR* szArglist = NULL;
INT nArgs;
szArglist = CommandLineToArgvW(GetCommandLine(), &nArgs);
if (szArglist && nArgs > 1)
{
INT ct = nArgs - 1;
HRESULT hr = E_OUTOFMEMORY;
com_ptr<IShellItemArray> ppsia = NULL;
PIDLIST_ABSOLUTE* rgpidl = new(std::nothrow) PIDLIST_ABSOLUTE[ct];
if (rgpidl)
{
hr = S_OK;
INT cpidl;
for (cpidl = 0; SUCCEEDED(hr) && cpidl < ct; cpidl++)
{
hr = SHParseDisplayName(szArglist[cpidl + 1], NULL, &rgpidl[cpidl], 0, NULL);
}
if (cpidl > 0 && SUCCEEDED(SHCreateShellItemArrayFromIDLists(cpidl, rgpidl, ppsia.put())))
{
com_ptr<IApplicationActivationManager> appActivationMgr = NULL;
if (SUCCEEDED(CoCreateInstance(CLSID_ApplicationActivationManager, NULL, CLSCTX_LOCAL_SERVER, __uuidof(appActivationMgr), appActivationMgr.put_void())))
{
DWORD pid = 0;
appActivationMgr->ActivateForFile(AUMID, ppsia.get(), NULL, &pid);
}
appActivationMgr.~com_ptr();
}
for (INT i = 0; i < cpidl; i++)
{
CoTaskMemFree(rgpidl[i]);
}
}
ppsia.~com_ptr();
delete[] rgpidl;
}
LocalFree(szArglist);
uninit_apartment();
Additional advantage of using above method to redirect activation is user can even open restricted file types (i.e. .cmd, .bat etc) with UWP app directly.