Server Fault really isn't for product recommendations. There was a similar question on SF in 2013, and the OP ended up creating a logon script asking for the reason until it's given i.e. not empty:
<!-- language: lang-vb -->
' Display an input dialog asking the reason for a login and writes it to the event viewer with information of the user.
Const EVENT_TYPE = "Information" 'Available Values: Success, Error, Warning, Information
Const EVENT_SOURCE = "LoginAudit" 'Setting the event source requires that the script runs with administrative privileges
firstname = GetUserFirstname()
username = GetUsername()
loginReason = ""
Do While (loginReason = "")
loginReason = InputBox("Hi " + firstname + ", please describe the reason of your login:", "Login Audit")
Loop
eventDescription = "User '" & username & "' logged in, providing the following reason: " & Chr(13) & Chr(13) & loginReason
Set WshShell = WScript.CreateObject("WScript.Shell")
strCommand = "eventcreate /T " & EVENT_TYPE & " /ID 100 /L Application /SO LoginAudit /D " & _
Chr(34) & eventDescription & Chr(34)
WshShell.Run strcommand
Function GetUserFirstname()
Set objSysInfo = CreateObject("ADSystemInfo")
Set objCurrentUser = GetObject("LDAP://" & objSysInfo.UserName)
GetUserFirstname = objCurrentUser.givenName
End Function
Function GetUsername()
Set objNetwork = CreateObject("Wscript.Network")
GetUsername = objNetwork.UserName
End Function
You could modify this to fit your needs. I think that this open form field approach attracts giving some one-letter answers instead of real reasons. A drop-down menu could be better, if all the actions can fall within known standard procedures. This being part of GDPR related work, you probably have already thought of these procedures for handling personally identifiable information.