While .NET ClickOnce applications offer simple tools for publishing applications and automatically handling dependencies, there are occasionally hiccups in the dependency management. Instead of automatically installing all dependencies in one run, for example, the program might require several attempted runs to install the prerequisites one-by-one. At other times, the prerequisites might not be properly packaged with the application, or require a custom installer to run. In these situations, manually handling the prerequisite management can offer ease-of-use and more control over deployment.
One of the beneficial features of the .NET environment is run-time dependency checking and delayed-load libraries. External libraries and DLLs are only loaded on an as-needed basis. If a library has not yet been requested at a particular point in program execution, it is not yet loaded by the environment. This enables a program to run dependency checks right at program start, and verify that all required DLLs are present before fully loading the application.
Each dependency installation may need to be verified in its own fashion. The most reliable method for dependency checking is querying the MSI registry through Interop functions – this provides an exact match against the GUID of the target library, which makes sure that the proper version of the target DLL is available. Alternatively, if the MSI product information is not available, a registry check or file check may suffice.
Sometimes, however, the registry, file, and MSI information may all be variable at each client installation. If there is no single reliable tool to query whether a DLL is installed, it may be easiest to simply perform a test load of the DLL through reflection, as follows:
try {
System.Reflection.Assembly a = System.Reflection.Assembly.Load("[Full Assembly Signature]");
}
catch (Exception ex) {
//Install Dependency
}
Running the dependency installer is often simply a matter of packaging the dependency with the application, and using the Process library to start the installation:
Process p = System.Diagnostics.Process.Start("[Application Installer]");
p.WaitForExit();
Once the installer completes, a final key line of code will enable additional dependencies to be installed without requiring the user to manually restart the application:
Application.Restart();
The Application.Restart command performs a full restart, so the newly installed prerequisites will be available after the reload. By chaining multiple dependency checks, this technique can provide a friendly interface that will continually install prerequisites until the program is ready to run.
When combined with friendly messages that guide the user through the process and ask for confirmation before running the appropriate installer, the dependency installation process can be turned from a harrowing user experience, into a simple and friendly feature of production-ready software
Written by Andrew Palczewski
About the Author
Andrew Palczewski is CEO of apHarmony, a Chicago software development company. He holds a Master's degree in Computer Engineering from the University of Illinois at Urbana-Champaign and has over ten years' experience in managing development of software projects.
Google+