I've had this happen numerous times and the best solution is to ensure the modifier keys are up as previously pointed out. This also occurs if you attempt to block keyboard input while a modifer is down.
Although I have never had the problem persist AFTER closing or reloading the script.
The only problem with using a sequence of "keywaits" like this is the program simply waits for each one to be released in seuquence.
KeyWait, Shift
KeyWait, LWin
KeyWait, RWin
If the user releases the shift key but still has the Lwin down, then holds the shift key down again before releasing the Left win key you can still end up having the shift key stuck down.
To have maximum reliability you really need to loop through all of the modifier and only proceed with the actions once none of them are down.
Here's a function from a script of mine which achieves this - it has more complexity than what you require (as its used by numerous other functions in my script), but im too lazy to simplify it for this post. Note: you probably don't need the 'sleep' times but the game i use it in requires these.
It checks the modifiers keys and if one is down it will continually re-check them every 5ms - when they are all released it will then wait 35ms and recheck them again (this second re-check is only required for this game) - if none are down it will return otherwise it keeps going (unless a 'timeout' period was specified).
Also as pointed out some people have had success sending modifer up keystrokes like {LWin up} - but I think this is hit and miss for many. Some find using Senevent or Send blind is required to 'unstick' the key.
ReleaseModifiers(Beep = 1, CheckIfUserPerformingAction = 0, AdditionalKeys = "", timeout := "") ;timout in ms
{
GLOBAL HotkeysZergBurrow
startTime := A_Tickcount
startReleaseModifiers:
count := 0
firstRun++
while getkeystate("Ctrl", "P") || getkeystate("Alt", "P")
|| getkeystate("Shift", "P") || getkeystate("LWin", "P") || getkeystate("RWin", "P")
|| AdditionalKeys && (ExtraKeysDown := isaKeyPhysicallyDown(AdditionalKeys)) ; ExtraKeysDown should actually return the actual key
|| (isPerformingAction := CheckIfUserPerformingAction && isUserPerformingAction()) ; have this function last as it can take the longest if lots of units selected
{
count++
if (timeout && A_Tickcount - startTime >= timeout)
return 1 ; was taking too long
if (count = 1 && Beep) && !isPerformingAction && !ExtraKeysDown && firstRun = 1 ;wont beep if casting or burrow AKA 'extra key' is down
SoundPlay, %A_Temp%\ModifierDown.wav
if ExtraKeysDown
LastExtraKeyHeldDown := ExtraKeysDown ; as ExtraKeysDown will get blanked in the loop preventing detection in the below if
else LastExtraKeyHeldDown := ""
sleep, 5
}
if count
{
if (LastExtraKeyHeldDown = HotkeysZergBurrow)
sleep 50 ;as burrow can 'buffer' within sc2
else sleep, 35 ;give time for sc2 to update keystate - it can be a slower than AHK (or it buffers)!
Goto, startReleaseModifiers
}
return
}
isaKeyPhysicallyDown(Keys)
{
if isobject(Keys)
{
for Index, Key in Keys
if getkeystate(Key, "P")
return key
}
else if getkeystate(Keys, "P")
return Keys ;keys!
return 0
}