В общем случае не существует способов решить твою задачу.
Если с архиваторами еще можно посмотреть на статистику нагрузки процессора процессом, и если она упала то считать что работа закончена, то с программами, не затрагивающими процессор этого не сделаешь (например загрузка файлов из интернета, тут даже по нагрузке на сеть не поймешь).
Курсор мог бы быть решением если одно но - он меняется только пока этот курсор находится строго над окном приложения, причем над его видимой частью, т.е. если приложение свернуть или оно будет загорожено другими окнами, то этого понять будет нельзя.
Можно написать библиотеку и вешать ее как hook на вызовы winapi SetCursor (для запуска приложения потребуется администраторские права а так же с высокой вероятностью в современных версиях win10-11 это уже будет не так просто сделать, по крайней мере я пользовался одним таким приложением minimize to tray и оно уже не работает), так же это не будет работать с windows store приложениями, а точнее те что написаны на .net и используют среду CLR.
Поэтому, для каждого приложения придется искать свой детектор их занятости.