Shortcuts
There is no legal way to change the shortcut's (.lnk) tech properties except the well-known ones like TargetPath
or Arguments
.
The usual code for shortcut creation on C# is:
WshShell shell = new WshShell();
try
{
IWshShortcut link = (IWshShortcut)shell.CreateShortcut(myShortCutPath),
link.TargetPath = myExecutablePath,
link.Description = "Run my awesome app",
link.Arguments = myExecutableArgs,
link.Save(),
}
finally
{
Marshal.ReleaseComObject(shell);
}
This code will require adding COM dependency from Windows Script Host Object Model
to your project.
But you can read about it in MSDN and StackOverflow.
What else we can do for the shortcut? With Windows Explorer UI we can set different compatiblity settings for our executable. But changing them does not changes the shortcut file. Moreover, if we change it for some shortcut, it changes for all of shortcuts for this executable. These settings are related to the exectuable itself and not to the shortcut.
What else we can do? We can create the Admin Shortcut. It will not apply on our executable, but will allow to run it from admin with this shortcut. There is no legal options to do this from code except byte hack. Binary comparison of two shortcuts with and without this checkbox on gives us the clue.
The 21th (0x15) byte from the beginning changes:
- the value of
0
is default and means that checkbox is disabled - the value of
32
(0x20
) means that shortcut will run our executable from admin.
With knowing so we can use binary patching to alter this setting from code how we want.
0x20
is a single bit set in byte. What do the other ones mean? No answer. This is the weirdness of WinAPI.
Combatibility
SO gives us a clue of how we can change the executable's compatibility settings. All of them are stored in:
HKEY_CURRENT_USER\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
or (machine-wide, not only current user)
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers
There are a few values there with name of absolute executable's path, type of String
and different values. Layers
key may be missing,
so if we want to set up settings for some executable, we should create it.
Let's check them:
- Compatiblity with Windows 8 gives us
~ WIN8RTM
value. - Compatiblity with Windows 7 gives us
~ WIN7RTM
value. - Compatiblity with Windows Vista (Service Pack 2) gives us
~ VISTASP2
value. - Compatiblity with Windows Vista (Service Pack 1) gives us
~ VISTASP1
value. - Compatiblity with pure Windows Vista gives us
~ VISTARTM
value. - Compatiblity with Windows XP SP3 gives us
~ WINXPSP3
value. - Compatiblity with Windows XP SP2 gives us
~ WINXPSP2
value. - Compatiblity with Windows 98/ME gives us
~ WIN98
value. - Compatiblity with Windows 95 gives us
~ WIN95
value.
Disabling the compatibility setting will remove the record from the registry.
Let's check the other checkboxes:
- 640x480 resolution gives us
~ 640X480
value. - Disable display scaling gives us
~ HIGHDPIAWARE
value. - Run from admin gives us
~ RUNASADMIN
value. - Run app from non-elevated user (not admin)
~ RUNASINVOKER
value (update from 2 Jun 2021). - Reduced to 8-bit color gives us
~ 256COLOR
value. - Reduced to 16-bit color gives us
~ 16BITCOLOR
value.
Windows 10 Spring Update also added a few more settings:
- Fix scaling problems on sign in gives us
~ PERPROCESSSYSTEMDPIFORCEOFF
value. - Fix scaling problems on open app gives us
~ PERPROCESSSYSTEMDPIFORCEON
value. - Disable fullscreen optimizations gives us
~ DISABLEDXMAXIMIZEDWINDOWEDMODE
value. - Override scaling with application gives us
~ HIGHDPIAWARE
value (same as previous Disable display scaling). - Override scaling with system gives us
~ DPIUNAWARE
value. - Override scaling with system (enhanced) gives us
~ GDIDPISCALING DPIUNAWARE
value.
Combination of the flags gives as combined value like:
~ DISABLEDXMAXIMIZEDWINDOWEDMODE RUNASADMIN PERPROCESSSYSTEMDPIFORCEON HIGHDPIAWARE 640X480 16BITCOLOR WIN8RTM
.
Don't know if order is meaningful, so here they are in order of Explorer created them. It seems, that tilda in the beginning is not critical, Explorer sets it, but it will work without it.
If you are really get confused with all of these flags - just open properties of the executable file and explore the Compatibility tab.
There are some another hacks (DWM8And16BitMitigation
for example), they are related to DirectDraw and should be obtained from the appropriate documentation.
P.S. Complete list of compatibility flags can be obtained in MSDN.