Recently one of my teachers asked me to create a program that will let standard users on his computers install fonts for their artistic needs. Sounds simple enough.. right? The OS at hand was Windows 7 Enterprise. I had an idea in mind to edit the registry or add a Windows policy that will let me do such a thing, so I created a batch script. The first thing I needed to do was get admin rights. Hmm….
Admin Access In DOS
Thanks to Eneerge @ https://sites.google.com/site/eneerge/scripts/batchgotadmin, I was able to implement a simple vbs script that will execute my whole batch script as an administrator. It looks something like this..
:RequestAdminElevation FilePath %* || goto:eof
setlocal ENABLEDELAYEDEXPANSION & set "_FilePath=%~1"
if NOT EXIST "!_FilePath!" (echo/Read RequestAdminElevation usage information)
set "_FN=_%~ns1" & echo/%TEMP%| findstr /C:"(" >nul && (echo/ERROR: %%TEMP%% path can not contain parenthesis &pause &endlocal &fc;: 2>nul & goto:eof)
set _vbspath="%temp:~%\%_FN:)=%.vbs" & set "_batpath=%temp:~%\%_FN:)=%.bat"
fltmc >nul 2>&1 || goto :_getElevation
(if exist %_vbspath% ( del %_vbspath% )) & (if exist %_batpath% ( del %_batpath% ))
endlocal & CD /D "%~dp1" & ver >nul & goto:eof
echo/Set UAC = CreateObject^("Shell.Application"^) > %_vbspath% || (echo/&echo/Unable to create %_vbspath% & endlocal &md; 2>nul &goto:eof)
echo/UAC.ShellExecute "%_batpath%", "", "", "runas", 1 >> %_vbspath% & echo/wscript.Quit(1)>> %_vbspath%
echo/@%* > "%_batpath%" || (echo/&echo/Unable to create %_batpath% & endlocal &md; 2>nul &goto:eof)
echo/@if %%errorlevel%%==9009 (echo/^&echo/Admin user could not read the batch file. If running from a mapped drive or UNC path, check if Admin user can read it.)^&echo/^& @if %%errorlevel%% NEQ 0 pause >> "%_batpath%"
%_vbspath% && (echo/&echo/Failed to run VBscript %_vbspath% &endlocal &md; 2>nul & goto:eof)
echo/&echo/Elevation was requested on a new CMD window &endlocal &fc;: 2>nul & goto:eof
This huge script is put at the bottom or invoked using call and then putting
call :RequestAdminElevation "%~dpfs0" %* || goto:eof anywhere before your admin-requiring code begins.
Giving Users group full control
To allow regular users (conveniently named Users in Windows) to add fonts, the Users group in Windows just has to own the fonts folder in everyway possible. I accomplished this with a set of commands that require admin:
attrib -r -s C:\Windows\Fonts
takeown /f C:\Windows\Fonts /r /d n
cacls C:\Windows\Fonts /e /t /g Users:C
cacls C:\Windows\System32\FNTCACHE.DAT /e /t /g Users:C
But this alone was not enough. There was one more step. The registry itself “owns” the Fonts folder in Windows, so you have to give the Users group permissions there too. Batch alone cannot do this.
With the help of a tool called SetACL, I was able to add this line
SetACL.exe -on "hklm\Software\Microsoft\Windows NT\CurrentVersion\Fonts" -ot reg -actn ace -ace "n:Users;p:full" to give the Users group full permissions over the registry key that handles Fonts. A reboot later.. and anyone could easily add their own awesome fonts!
You can see my full tool here on GitHub: Adminless-Fonts, or download yourself the latest release of it here: Latest Release