That's complicated: there are major companies that try to do this and spend huge amounts of money only to find that a "cracked" version becomes available on the same day they release a new version of the software (Photoshop is a good example)
Pretty much the only way to do it would be to assemble a "fingerprint" of a system (by getting it's various component ID's and serial numbers where possible, converting that to a hashed form and storign that on an internet server with it's expiry date.
When you app starts, it generates the hash value from eth current config, and checks with your server to see if it is permitted to run.
It's not foolproof: VMs, Sandboxes and so forth can defeat it, the code can be hacked to remove the checking, and so on - and it can seriously annoy legitimate users if it "breaks" for any reason (like a minor hardware change).
Unless you are planning on shipping lots of units and there is serious money involved it's probably not a good investment of your time to add this.
A much simpler one is just to store a local value which is the expiry date of the software and check it on start up. Uninstall doesn't remove it so reinstalling won't do anything useful, but it is pretty easy to defeat even for low-tech users.
Google will show you how to do these:
time limit my software C# - Google Search[
^] but it's very easy to spend more money (in terms of time) than you protect, and just end up alienating genuine customers - so think carefully about how much value you ar eactually protecting before you get too far down this rabbit hole.