Hashing is an one-way operation: you cannot decode the hashed value.
What you probably want to do here is verify the hash: create a brand new hash when your program runs on the client's system using "live" parameter values, and verify that the generated hash is equal to the one you have given to the client as a key.
This means that you wouldn't be able to include in the hash any information you cannot reliably discover when your program is running on the client. Unfortunately, "expiry date" and "number of pcs" fall into this category.
If you need to verify such information, then hashing is unsuitable and you will need to encrypt instead. Encryption comes in two flavors: symmetric and assymetric.
Symmetric encryption means that the secret key has to be known to your application so that it can decrypt the validation code, which in turn means that anyone with moderate working knowledge of how such things work will be able to crack it and generate any validation code they want.
In asymmetric encryption you have a private key (with which to encrypt) and a public key with which to decrypt. There is no problem if you make this public key available to everyone, so with this approach one cannot make a keygen for your program.
Of course this doesn't mean that your app will be safe from cracking, as it's really quite easy to modify the code of a managed application to skip the code validation entirely.
The question you have asked is really a can of worms, and there is no definitive answer to it. You might want to take a look at this question: https://stackoverflow.com/questions/5132943/licensing-system-for-net and follow the dozens of links to similar questions here on SO.