Имеется ввиду окончание загрузки программы или окончание работы программы?
Если брать язык С++ (компилятор GCC для Windows), то есть системный вызов waitpid(pid_t pid), который ожидает завершения процесса с идентификатором pid (pid может быть порожден, например, системным вызвовм fork(), после fork() обычно следует вызов exec(const char *path, const char *arg, ...)).
Аналогом функций fork() и exec() в Windows - CreateProcess.
Аналогов функции waitpid() в Windows является - WaitForSingleObject.
Однако, если требуется узнать, когда приложение именно окончило загрузку, то тут уже сложнее ;-)
Например, можно контролировать появление окна приложения, например по заголовку (EnumChildWindows - получить список окон, GetWindowRect - зазмер окна, GetWindowText - заголовок окна).
Вообще, однозначного способа я точно сказать не могу, т.к. в основном работаю под Linux, но думаю, что копать нужно в сторону GetProcessInformation, а точнее, когда линкер (linker) закончит связывание исполняемого файла с динамическими библиотеками. Но, в данном случае, не учитывается собственная загрузка ресурсов приложением.
Есть еще один момент, некоторые приложения создают мьютекс в разделяемом сегменте памяти, что-бы предотвратить повторный запуск приложения, можно также отслеживать и его создание. Для получения информации о подобных вещах проще всего воспользоваться отладчиком windbg.
p.s. будут вопросы - обращайтесь, что нибудь придумаем ;-)