"Can you send me your public IP so I can add it to the firewall?"
If you work for clients, you have heard that sentence. And you have opened a browser, typed "what is my ip", closed three cookie banners and copied the address from between the ads.
I hear it a lot. And I have one more problem: depending on the client, I am connected to a different VPN. This one sends all the traffic through the tunnel, that one only part of it, a third one drops on its own after the laptop goes to sleep. So the question is not only "what is my IP?", but also "which IP am I going out from, right now?".
I already had a small app for that on the Microsoft Store, My Public IP Address. It had aged. I rewrote it from scratch, a little for the need, a lot for the fun. It is free on the Store and the code is on GitHub.
TL;DR
- Your public IP sits next to the clock: hover the icon to see it, click to copy it.
- A notification shows up as soon as it changes: VPN dropping, new network, new address from your provider.
- A history of your recent addresses, to know when it moved.
- WinUI 3 and .NET 10, with all the logic in a library that does not depend on Windows, so it is tested.
- No account, no ads, no tracking: the history stays on your PC.
What the app does
Nothing complicated, on purpose. It lives in the notification area, next to the clock.
Hover the icon: the tooltip gives the IPv4 and the IPv6.

Click it: a small Windows 11 style panel opens above the clock, with the public IP, the local network address, a copy button for each, and the recent addresses.

The screenshots use addresses reserved for documentation, not mine.
And above all, when the address changes, Windows tells me, with the old one and the new one:

That notification is what makes the difference with several VPNs. The tunnel drops without a word? I know right away, instead of spending ten minutes wondering why the client's server stopped answering.
Right-click gives the rest: copy, refresh, start with Windows, turn notifications off, quit.

A few details that kept me busy
Showing an IP takes three lines of code. Making it reliable is another story. Here is what I learned on the way.
Never show an error as if it were an address
The app asks public services that just answer the IP as plain text: ipify, icanhazip, and checkip.amazonaws.com as a fallback. If one is down, it moves on to the next.
The trap is reading the answer. IPAddress.TryParse is very lenient: it accepts "1" or "10.1" and turns them into valid addresses. One odd error page, and I would copy a fake IP and give it to a client. So parsing is strict:
internal static bool TryParse(string text, AddressFamily family, out IPAddress? address)
{
address = null;
string candidate = text.Trim();
if (family == AddressFamily.InterNetwork && candidate.Count(c => c == '.') != 3)
{
return false;
}
if (!IPAddress.TryParse(candidate, out IPAddress? parsed) || parsed.AddressFamily != family)
{
return false;
}
address = parsed;
return true;
}
Following network changes
When you turn a VPN on, Windows reports a network change... then another one, then another, while the adapters settle. The app waits two seconds for things to calm down before asking for the address again. On top of that, it checks every 15 minutes, and retries more and more slowly after a failure (3 s, 5 s, 10 s, 30 s, then one minute).
Another detail: HttpClient keeps its connections open. After a VPN switch, it could reuse a connection from the old network. Short lifetimes fix that:
var handler = new SocketsHttpHandler
{
ConnectTimeout = TimeSpan.FromSeconds(4),
// Short lifetimes so that a network switch (VPN, Wi-Fi...) never reuses a stale connection
PooledConnectionLifetime = TimeSpan.FromMinutes(1),
PooledConnectionIdleTimeout = TimeSpan.FromSeconds(20),
};
IPv6 changes all the time, without it being a change
First tests with IPv6: one notification a day, for no reason. Windows uses "privacy extensions": the second half of the IPv6 address changes regularly, so that you cannot be tracked. The network itself does not change.
So for IPv6, I only compare the /64 prefix, the part that identifies the network:
internal static bool IsSameConnection(IpHistoryEntry a, IpHistoryEntry b) =>
a.IPv4 == b.IPv4 && IPv6Prefix(a.IPv6) == IPv6Prefix(b.IPv6);
No notification for the first result of a session either: if the router got a new address overnight, I do not need to be told every time I log in.
The icon that vanished after an update
I did not see that one coming. Windows ties the identifier (a GUID) of a notification area icon to the path of the executable. But a Store app is installed in a folder that contains its version number. Update, new path, GUID rejected... and no more icon.
The fix fits in two lines: derive the GUID from the path.
string path = (Environment.ProcessPath ?? "MyPublicIp").ToUpperInvariant();
return new Guid(MD5.HashData(Encoding.UTF8.GetBytes(path)));
Under the hood
- WinUI 3 and .NET 10, packaged as MSIX for the Store (x86, x64 and ARM64).
- All the logic (IP lookup, refresh, history, change detection, panel placement) lives in
MyPublicIp.Core, a library with no Windows dependency at all. The WinUI app is only a thin shell around it. - Direct consequence: everything is tested with xUnit. Time is injected with
TimeProvider, so the refresh tests move a fake clock forward instead of waiting. - MVVM with CommunityToolkit.Mvvm: the panel and the menu share the same view model.
- Self-contained, fully trimmed .NET runtime: about 8 MB per architecture instead of 60.
- Starts with Windows through the MSIX startup task, which can be turned off from the app or from Windows Settings.
Privacy is simple: the app sends one HTTPS request to a "what is my IP" service, and that is all. No account, no analytics, no ads. The history (20 addresses at most) stays on your PC.
What I take away
- Small tools are the best playgrounds. The need is clear, the scope fits in your head, and you can polish every detail.
- A reliable app is mostly about the odd cases. Services going down, networks changing in bursts, IPv6 moving on its own.
- Separating the logic from the UI always pays off. With a Core that knows nothing about Windows, I could test everything without ever starting the app.
If you also juggle several VPNs, or if people often ask for your IP, the app is on the Microsoft Store. The code is on GitHub, under the MIT license. Ideas and feedback are welcome in the issues.

Comments (0)
No comments yet. Be the first to comment!
Leave a comment