Fonts installed by MSI not available until next logon
Hi Guys,
We have a simple MSI package that installs a few files to Program Files and then installs 4 font files (they are in the Font table in the MSI) and we deploy this package via SCCM, so the MSI gets installed silently from the services session. All machines that we deploy this package to are Windows 7 (mixture of 32 bit and 64 bit).
The problem is, if a user is currently logged on when the MSI is installed by the SCCM agent service, the fonts are not available to any applications in that user's session until they log out and log back in. If we run exact same silent MSI installation but as the user (making them admin temporarily) then the fonts are available straight away.
Basically I just want to know if anyone else experiences this issue and if they have a solution?
I will add that I've spent the last 3 days looking into this and have come up with my own theory as to why this works the way it does and have created a rather elaborate solution to the problem (involving writing two applications that use various Windows APIs add the fonts to the current user's session until they log out) but I just wondered how other people deal with this. I'll explain my full solution and post a link to the programs I created if anyone is interested.
We have a simple MSI package that installs a few files to Program Files and then installs 4 font files (they are in the Font table in the MSI) and we deploy this package via SCCM, so the MSI gets installed silently from the services session. All machines that we deploy this package to are Windows 7 (mixture of 32 bit and 64 bit).
The problem is, if a user is currently logged on when the MSI is installed by the SCCM agent service, the fonts are not available to any applications in that user's session until they log out and log back in. If we run exact same silent MSI installation but as the user (making them admin temporarily) then the fonts are available straight away.
Basically I just want to know if anyone else experiences this issue and if they have a solution?
I will add that I've spent the last 3 days looking into this and have come up with my own theory as to why this works the way it does and have created a rather elaborate solution to the problem (involving writing two applications that use various Windows APIs add the fonts to the current user's session until they log out) but I just wondered how other people deal with this. I'll explain my full solution and post a link to the programs I created if anyone is interested.
0 Comments
[ + ] Show comments
Answers (10)
Please log in to answer
Posted by:
rich0864
13 years ago
Posted by:
chris128
13 years ago
Thanks for the suggestion, hadn't thought of that, but I'm afraid it doesn't work. The service was not started but if I start/restart it the fonts still do not work until logging out and back in.
Oh and making the user's admins makes no difference - I was logged on as a Domain Admin when I tested it just now.
I've refined my current solution and got it all working correctly now, so I'm happy to stick with that. I was just curious if other people had the same issue and how they got round it.
I've posted a full write up that includes an explanation of why this happens and download links for the two apps I wrote as part of the solution just in case it helps other people out: http://cjwdev.wordpress.com/2011/06/12/install-fonts-for-logged-on-user-via-sccm-package/
If anyone else wants to chip in with how they get around this issue (or if you just live with it) I'd be happy to hear your comments :)
Oh and making the user's admins makes no difference - I was logged on as a Domain Admin when I tested it just now.
I've refined my current solution and got it all working correctly now, so I'm happy to stick with that. I was just curious if other people had the same issue and how they got round it.
I've posted a full write up that includes an explanation of why this happens and download links for the two apps I wrote as part of the solution just in case it helps other people out: http://cjwdev.wordpress.com/2011/06/12/install-fonts-for-logged-on-user-via-sccm-package/
If anyone else wants to chip in with how they get around this issue (or if you just live with it) I'd be happy to hear your comments :)
Posted by:
anonymous_9363
13 years ago
Posted by:
chris128
13 years ago
I can check that but I think you might be misunderstanding the issue.
The problem is not that the fonts don't get installed - it is that they are not available to the currently logged on user when the MSI is run from SCCM (or indeed any service). Once the user has logged out and logged back in then the fonts work fine.
Also, if the user runs the exact same silent MSI installation manually then the fonts work straight away without a logoff/logon.
Therefore I am pretty sure it is not an issue with the MSI itself, unless of course you can tell me that this is not normal behaviour and that you can execute an MSI installation from a service and the fonts work for the currently logged on user instantly.
Like I said, I believe I've figured out why this is and have come up with my own solution. See previous post for a link to my blog post where I have written it up in full :)
The problem is not that the fonts don't get installed - it is that they are not available to the currently logged on user when the MSI is run from SCCM (or indeed any service). Once the user has logged out and logged back in then the fonts work fine.
Also, if the user runs the exact same silent MSI installation manually then the fonts work straight away without a logoff/logon.
Therefore I am pretty sure it is not an issue with the MSI itself, unless of course you can tell me that this is not normal behaviour and that you can execute an MSI installation from a service and the fonts work for the currently logged on user instantly.
Like I said, I believe I've figured out why this is and have come up with my own solution. See previous post for a link to my blog post where I have written it up in full :)
Posted by:
rich0864
13 years ago
I have modified a VB Script as follows:
option explicit
Dim arrFileLines()
parseFileToArray "fonts.txt", arrFileLines
'echoArraySimple arrFileLines
echoArrayNice arrFileLines
wscript.quit
'=====
sub parseFileToArray(byVal pFilename, byRef pArray)
'open - declare variables and stuff
dim objFSO,objFile, hwmArray,x 'hwm = HighWaterMark
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(pFilename, ForReading)
CONST ForReading = 1
CONST INIT = 100 'INIT = Inital Array Size
CONST EXP = 250 'EXP = expand the array by this much if it fills up
'main - do the work
hwmArray = -1
redim pArray(INIT)
Do Until objFile.AtEndOfStream
hwmArray = hwmArray + 1
x = hwmArray
if hwmArray >= ubound(pArray) then redim preserve pArray(hwmArray + EXP) 'if the array fills up, buffer EXP more entries
pArray(x) = objFile.ReadLine
Loop
redim preserve pArray(hwmArray) 'shrink array to actual size
'close - set the return value, close objects and stuff
objFile.Close
set objFile = nothing
set objFSO = nothing
end sub
sub echoArrayNice(byRef pArray)
dim strLine,msg
dim oShell
Set oShell = WScript.CreateObject("WScript.Shell")
For Each strLine in pArray
' msg = "RegisterFont.exe add " & strLine
msg = "StartInConsoleSession.exe CurrentSessionFonts.exe add " & strLine & " c:\windows\fonts\" & strLine
' wscript.echo msg
oShell.run msg
Next
end sub
I have all of my ttf's sitting at the root of the folder I am working out of and the fonts.txt lists the font name to populate the array. I have successfully tested that the array is doing what I need by echoing the commands I am formatting to pass to the cmd line, so I know all the prelim stuff is working.
I have tried this with both of Chris' exe's as well as the 'registerfonts.exe' that I found referenced on Chris' technet social posting.
All 3 exe's run without errors when called [respectively, not running all 3 at the same time] by the script but alas no fonts, either immediately or with a logoff/logon [I am testing this with a domain admin account as the logged on user, running from cmd line as system using psexec].
Any ideas?
Cheers
Rich
EDIT:
Just ran Chris' exe's from cmd line [cmd: >StartInConsoleSession.exe CurrentSessionFonts.exe add
Attempting to get handle to primary access token of console session user...
Failed to get handle to primary token, the last error reported was: An attempt was made to reference a token that does not exist
----------------------------------
>StartInConsoleSession.exe CurrentSessionFonts.exe add exampleFont.ttf %windir%\fonts\exampleFont.ttf
StartInConsoleSession.exe
Version 1.0.0.0
Developed by Chris Wright (cwright@cjwdev.co.uk)
Command line = "CurrentSessionFonts.exe" "add" "exampleFont.ttf" "C:\Windows\fonts\exampleFont.ttf"
Wait for exit = False
Attempting to get console session ID...
Console session ID = 1
Attempting to get handle to primary access token of console session user...
Failed to get handle to primary token, the last error reported was: A required privilege is not held by the client
C:\run\IDAutomationFonts>CurrentSessionFonts.exe add exampleFont.ttf %windir%\fonts\exampleFont.ttf
CurrentSessionFonts.exe
Version 1.0.0.0
Developed by Chris Wright (cwright@cjwdev.co.uk)
Font successfully added (exampleFont.ttf)
Didn't run directly as SYSTEM this time, only with domain admin creds
I could use your help on this Chris...sorry to bother you man.
Posted by:
chris128
13 years ago
No worries I'm happy to try and help :)
First of all, what OS is this running on? As I mentioned earlier, I only tested this on Windows 7.
Anyway, I think you have misunderstood how to use my currentsessionfonts.exe app - you are passing in the font file name and then C:\Windows\Fonts\font.ttf, where as you should only be passing in the path to the font file. E.g currentsessionfonts.exe add C:\Windows\Fonts\font.ttf. Of course if your font does not already exist in C:\Windows\Fonts then your script should copy it into there first before doing this (I didn't need to do that because the MSI had already actually installed the fonts). Another thing that the MSI had already done that you will need to do is to add the font to that registry location I mentioned in my blog post: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts, as otherwise it will not be available after the user logs off.
As for the errors with StartInConsoleSession.exe - the first one about the token not existing I am unsure about, I would have thought you would only get that if no user was currently logged on to the console session. The second one about a required privilege not being held is understandable because that was when you were not running as Local System account and only that account has the required permissions to do this.
First of all, what OS is this running on? As I mentioned earlier, I only tested this on Windows 7.
Anyway, I think you have misunderstood how to use my currentsessionfonts.exe app - you are passing in the font file name and then C:\Windows\Fonts\font.ttf, where as you should only be passing in the path to the font file. E.g currentsessionfonts.exe add C:\Windows\Fonts\font.ttf. Of course if your font does not already exist in C:\Windows\Fonts then your script should copy it into there first before doing this (I didn't need to do that because the MSI had already actually installed the fonts). Another thing that the MSI had already done that you will need to do is to add the font to that registry location I mentioned in my blog post: HKLM\Software\Microsoft\Windows NT\CurrentVersion\Fonts, as otherwise it will not be available after the user logs off.
As for the errors with StartInConsoleSession.exe - the first one about the token not existing I am unsure about, I would have thought you would only get that if no user was currently logged on to the console session. The second one about a required privilege not being held is understandable because that was when you were not running as Local System account and only that account has the required permissions to do this.
Posted by:
rich0864
13 years ago
Posted by:
rich0864
13 years ago
Wrapped it in an sfx wrapper for good measure, which extracts to c:\temp with:
c:\temp\ExampleFonts\psexec\psexec.exe -i -s -accepteula "%windir%\system32\cmd.exe" /K "c:\temp\ExampleFonts\registerfonts.cmd"
passing as the command at extraction
regedit.exe /S "c:\temp\ExampleFonts\ExampleFonts.reg"
copy "c:\temp\ExampleFonts\*.ttf" "%windir%\fonts" /Y
cscript.exe c:\temp\ExampleFonts\registerfonts.vbs
registerfonts.vbs:
option explicit
Dim arrFileLines()
parseFileToArray "c:\temp\ExampleFonts\fonts.txt", arrFileLines
'echoArraySimple arrFileLines
echoArrayNice arrFileLines
wscript.quit
sub parseFileToArray(byVal pFilename, byRef pArray)
'open - declare variables and stuff
dim objFSO,objFile, hwmArray,x 'hwm = HighWaterMark
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile(pFilename, ForReading)
CONST ForReading = 1
CONST INIT = 100 'INIT = Inital Array Size
CONST EXP = 250 'EXP = expand the array by this much if it fills up
'main - do the work
hwmArray = -1
redim pArray(INIT)
Do Until objFile.AtEndOfStream
hwmArray = hwmArray + 1
x = hwmArray
if hwmArray >= ubound(pArray) then redim preserve pArray(hwmArray + EXP) 'if the array fills up, buffer EXP more entries
pArray(x) = objFile.ReadLine
Loop
redim preserve pArray(hwmArray) 'shrink array to actual size
'close - set the return value, close objects and stuff
objFile.Close
set objFile = nothing
set objFSO = nothing
end sub
sub echoArrayNice(byRef pArray)
dim strLine,msg,oExe1,oExe2
oExe1 = "c:\temp\ExampleFonts\StartInConsoleSession.exe"
oExe2 = "c:\temp\ExampleFonts\CurrentSessionFonts.exe"
dim oShell
Set oShell = WScript.CreateObject("WScript.Shell")
For Each strLine in pArray
msg = oExe1 & " " & oExe2 & " add " & strLine & " %windir%\fonts\" & strLine
oShell.run msg
Next
end sub
It is something of a hack job, happy to accept suggestions on cleaning it up and simplifying. I'd love to find a way to do this without having to rely on absolute pathes but environmental permissions are restrictive and I did not want to add any 'runas' to the code as that would have just complicated things even further :)
Thanks heaps for your help Chris!
Posted by:
chris128
13 years ago
Posted by:
rich0864
13 years ago
So, as a result I have not performed any further troubleshoot or test on it.
I do have to say a big thank you though, it got me out of a jam that another caused [:@]
Cheers
Rating comments in this legacy AppDeploy message board thread won't reorder them,
so that the conversation will remain readable.
so that the conversation will remain readable.