如何实现Windows.Forms/Xamarin.Forms从外部URI/链接打开应用并传参?
Hey there! Let's walk through how to handle deep linking (opening your app via external URIs) for both Windows Forms and Xamarin.Forms, plus a cross-platform approach that works like Android's Intent system.
To make your Windows Forms app respond to external URIs, you need two key steps: register a custom URI scheme, then handle incoming URIs in your app.
Step 1: Register the URI Scheme
Windows needs to know which app handles your custom URI. For development, you can set this up via the Registry:
- Open Registry Editor (
regedit.exe) - Navigate to
HKEY_CLASSES_ROOT - Create a new key named after your scheme (e.g.,
mywinapp) - Set the default value to a friendly name like "My Windows Forms App"
- Add a string value named
URL Protocolwith an empty value - Create subkeys
shell > open > command - Set the default value of
commandto your app's EXE path, followed by"%1"(to pass the URI as a command-line argument)
Step 2: Handle Incoming URIs in Your App
When your app is launched via the URI, the full URI will be passed as a command-line argument. Catch this in your Program.cs:
static void Main(string[] args) { Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); string incomingData = null; if (args.Length > 0) { // Parse the incoming URI (e.g., mywinapp://open?data=hello-world) var uri = new Uri(args[0]); var queryParams = System.Web.HttpUtility.ParseQueryString(uri.Query); incomingData = queryParams["data"]; } // Pass the data to your main form Application.Run(new MainForm(incomingData)); }
Then update your MainForm constructor to accept and use the incoming data:
public MainForm(string incomingData = null) { InitializeComponent(); if (!string.IsNullOrEmpty(incomingData)) { MessageBox.Show($"Received data: {incomingData}"); // Add your logic to process the data here } }
Xamarin.Forms requires platform-specific configuration, but we can use Xamarin.Essentials to handle most of the cross-platform heavy lifting.
Step 1: Platform Configuration
Android
Open AndroidManifest.xml and add an intent filter inside your <activity> tag to register your URI scheme:
<intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <!-- Replace "myxamarinapp" with your custom scheme --> <data android:scheme="myxamarinapp" /> </intent-filter>
iOS
Open Info.plist and add URL scheme configuration:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <!-- Replace "myxamarinapp" with your custom scheme --> <string>myxamarinapp</string> </array> </dict> </array>
Then update AppDelegate.cs to pass incoming URIs to Xamarin.Essentials:
public override bool OpenUrl(UIApplication app, NSUrl url, NSDictionary options) { if (Xamarin.Essentials.AppLinks.OpenUrl(url)) return true; return base.OpenUrl(app, url, options); }
Step 2: Handle Incoming Links in Xamarin.Forms
In your shared App.xaml.cs, subscribe to the AppLinkReceived event to process incoming URIs:
protected override void OnStart() { Xamarin.Essentials.AppLinks.OnAppLinkReceived += AppLinks_OnAppLinkReceived; } private void AppLinks_OnAppLinkReceived(object sender, Xamarin.Essentials.AppLinkReceivedEventArgs e) { var uri = e.Uri; var queryParams = System.Web.HttpUtility.ParseQueryString(uri.Query); var incomingData = queryParams["data"]; // Navigate to a page and pass the data MainPage.Navigation.PushAsync(new DataDisplayPage(incomingData)); }
Step 3: Share Links with Data
To share a link that opens your app and passes data, use Xamarin.Essentials' Share API:
private async Task ShareAppLink() { // Encode the data to avoid URI issues var encodedData = Uri.EscapeDataString("Check out this shared content!"); var appLink = new Uri($"myxamarinapp://share?data={encodedData}"); await Xamarin.Essentials.Share.RequestAsync(new Xamarin.Essentials.ShareTextRequest { Text = "Open this in my Xamarin app!", Uri = appLink.ToString() }); }
If you want a unified approach similar to Android's Intent system, you can wrap the platform-specific logic in an abstract service:
Step 1: Define a Cross-Platform Interface
public interface IDeepLinkService { // Register the URI scheme (if needed for the platform) void RegisterScheme(string scheme); // Open another app via URI (or your own app) Task<bool> OpenUri(string uri); // Get the incoming URI when the app is launched via deep link string GetIncomingUri(); }
Step 2: Implement the Service for Each Platform
- Windows Forms: Implement using command-line arguments and Registry registration
- Android: Use
Intent.ACTION_VIEWto open URIs, and extract data from incoming intents - iOS: Use
UIApplication.SharedApplication.OpenUrland extract data from incoming URLs
Xamarin.Essentials already provides most of this functionality out of the box, so using it is usually the fastest path instead of building a custom service.
内容的提问来源于stack exchange,提问作者Javi

