Closed twinstar6980 closed 2 months ago
From Windows terminal, you can try: app.exe "" -x opt1 opt2 In my understanding, this plugin however is based on custom Url handler using Windows default app feature. I am not sure how an empty url can help Windows recognizing and getting back to your app.
From Windows terminal, you can try: app.exe "" -x opt1 opt2 In my understanding, this plugin however is based on custom Url handler using Windows default app feature. I am not sure how an empty url can help Windows recognizing and getting back to your app.
Passing a empty string does not solve this problem, according to implementation, when argc > 1
, app_links will treat argv[1]
as the app url and pass it to linkStream.
My current solution is:
Like this:
AppLinks().stringLinkStream.listen((link) async {
if (link.startsWith('my-scheme:')) {
handleLink(Uri.parse(link));
}
});
// pass "my-scheme:" as pattern
bool SendAppLinkToInstance(const std::wstring& title, const std::string& pattern) {
// check argv[1]
std::vector<std::string> command_line_arguments = GetCommandLineArguments();
if (command_line_arguments.size() != 1) {
return false;
}
std::string& link = command_line_arguments.front();
if (link.size() < pattern.size() || link.substr(0, pattern.size()) != pattern) {
return false;
}
// ...
}
Indeed, on Windows you have to handle it by yourself if your app handles multiple command line parameters for now. Labeling this as an enhancement.
Indeed, on Windows you have to handle it by yourself if your app handles multiple command line parameters for now. Labeling this as an enhancement.
If possible, I would like to create a PR to solve this problem.
My solution is to add a check in the AppLinksPlugin::GetLink
function: GetLink will only return the url if argc == 2 and argv[1] is an app url, otherwise it returns nullopt.
The situation that needs to be considered is how to check argv[1]. If it is simply judged whether it is a url, then if a url that does not belong to the app itself is passed, applinks will also pass it to linkStream, and developers may receive a url that does not belong to them in get*Link
. For example:
app.exe my-scheme:/...
app.exe other-app-scheme:/...
Both urls are passed to the flutter app, but the url in the second case does not belong to my-app itself.
Should add a new api to allow users to set the allowed url scheme in wWinMain
?
Do you think this solution is ok? Can I make a PR?
In addition, I also found a problem. If argc == 1
, the GetLink
function does not perform the LocalFree
operation on the return value of CommandLineToArgvW
. Will this cause a memory leak?
Of course, PR are always welcome!
I would avoid to introduce any new API here (also specific to Windows platform).
Could we look for registry scheme and make a match with the current process executable? In this way, new API is avoided, this is simplier for developers and also dynamic.
Of course, PR are always welcome!
I would avoid to introduce any new API here (also specific to Windows platform).
Could we look for registry scheme and make a match with the current process executable? In this way, new API is avoided, this is simplier for developers and also dynamic.
I don't really understand how Windows URL Protocol register works. I have a few questions:
HKEY_CURRENT_USER\Software\Classes\<my-scheme>
in the registry, but it does not have shell/open/command
keys. Is there any other way to retrieve the URL protocol more safely?Btw, I think adding Windows-specific APIs is not unacceptable, because AppLinks already requires us to add a lot of dirty code in main.cpp. (why not add SendAppLinkToInstance
to app_links_plugin_c_api
? In this way, users don't need to introduce too much code in main.cpp.)
The idea was to put matching scheme/executable around GetLink
method. So this would be fully internal.
About performance, don't worry, there's nothing to search in the registry since we already know the path:
HKEY_CURRENT_USER\Software\Classes\<my-scheme>\shell\open\command
. If this path does not exist, argument is not a link (or an associated one).
Pseudo positive flow from GetLink
:
1- check arguments for potential link
2- get potential value from registry
3- check matching from registry value and current process (registry value should be with this form <executable_full_path> <maybe_other_params> %1
.
shell\open\command
should be present as subkeys, this is how Windows triggers the app launch (as far as I know).
Please see the second point of my previous comment. When we use the MSIX protocol extension, HKEY_CURRENT_USER\Software\Classes\<my-scheme>
exists in the registry, but there is no shell/open/command
, so it is impossible to determine whether it points to the app's exe.
For MSIX app, the actual protocol information is stored here, but I don't know how to get the AppX....
id corresponding to the exe.
Ok, so you register your app as an UWP app if I understand well... I didn't know that was still possible this way since Flutter removed its support.
Ok, so you register your app as an UWP app if I understand well... I didn't know that was still possible this way since Flutter removed its support.
not uwp, just win32 app, msix can packing win32 app and run it as full trust. MSIX is a more modern, cleaner and simpler app distribution solution. you can pack flutter app to msix use this dart plugin
Ok I may have found something with windows implementation library which should make the bridge with win32 apps.
Here's how we can experiment a solution to this internally:
Are you able to continue this research?
I tried winrt, for my MSIX packaged app, the program works as expected when I launch the app from the startmenu or protocol.
However, there is a serious problem, if I launch the app's exe from the command line, the program will crashes because of the args.Kind()
statement.
In addition, when the application registers the url protocol by adding registry entry, args.Kind
will also crash (I think this is because shell/open/command
actually executes the bat command line).
It seems that the solution provided by winrt can only be used for msix packaged apps, and it will also cause the packaged app exe to fail to start from the command line. I have no experience with WinRT so I don't know how to avoid this crash.
I published version 6.2.1 which partially helps here. Now, a single argument with a protocol scheme is required. This mitigates the issue described in OP.
What I don't know is about your use case with activation from the manifest packaged by MSIX. Does it open the app the same way as with a manual registration? If so, do you use http
or https
scheme? Would it work?
Does it open the app the same way as with a manual registration?
Yes, after the user installs MSIX, the system will automatically associate the URL with the app.
However, unlike manual registration, in this case, you cannot find shell/open/command
under HKCU/....../<scheme>
, so you cannot determine whether the URL is associated with the exe, unless the user passes a parameter representing the URL scheme in the cpp code.
WinRT can work in MSIX-wrapped apps, but for non-MSIX apps, WinRT will cause the app to crash (I am not a professional WinRT user, and I don’t know if there is any way to avoid crashes in non-MSIX).
If so, do you use http or https scheme? Would it work?
I don’t know, I don’t use http/https scheme in my app.
On Windows, when an app is started with a URL, the system passes the URL to the app as argv[1]. However, developers may need to customize some command line parameters, see the following examples:
app.exe my-app:/path?query
starts the app with a URL, app_links passes the URL to linkStream, which is the expected behavior of developers.app.exe -x opt1 opt2
passes custom parameters. In this case, there is no URL, but app_links passes the argv[1]-x
as the URL to linkStream, which is not the expected behavior of developers.Therefore, please allow app_links to judge the passed command line parameters to decide whether to pass argv[1] to linkStream.