Write an Adapter or Facade that wraps the external DLL. Make it implement an interface IExternalDLL (of course choose a better name), which documents/specifies your needs from the external DLL ; it does not have to exactly mimic the function signatures of the actual implementation.
Write up a set of 'contract tests' against the interface, the way you expect the interface to work.
Now you can write different adapters per new version - in case of some breaking changes from v1 to v2. Your client is abstracted due to the interface.. Its the job of the adapter/facade to make sure the corresponding version of the dll meets the contract tests. You write one set of tests and exercise it with all implementations of the adapter/facade.
The next time a new version is rolled out - you can
- use the last adapter/facade if it meets your need
- roll out a new one to fix any breaking changes ; ensure that you run it against the contract tests so that your client doesn't break with this adapter.