Hi.
Is it possible to implement these:
1. The Sandbox has a font file (in %Fonts%). But if on the OS the font file with the same name is newer version, the Sandbox should use the one from the OS.
2. If the Sandbox path is set to the same folder but can't write the modifications (maybe is a CD/DVD, maybe there isn't enough free space available or perhaps doesn't have enough rights to write there...) then it should write in %AppData%\Thinstall.
3. When installing msi it should automatically erase the folder with the same project name from %AppData%\Thinstall (if it's gonna use that folder). This way you can avoid problems (like it happened to me).
Thank you for any idea...
Can, you, please, mark this thread as answered if you don't have more questions?
Thank you,
1. The Sandbox has a font file (in %Fonts%). But if on the OS the font file with the same name is newer version, the Sandbox should use the one from the OS.
There is not such a build-in option for failover based on font version. It could be possible to create script that would check such a condition and do some actions.
2. If the Sandbox path is set to the same folder but can't write the modifications (maybe is a CD/DVD, maybe there isn't enough free space available or perhaps doesn't have enough rights to write there...) then it should write in %AppData%\Thinstall.
If there is a problem with Sandbox, Thinapped application wouldn't start. There is not build-in option to failover sandbox location. And it cannot be neither scripted.
3. When installing msi it should automatically erase the folder with the same project name from %AppData%\Thinstall (if it's gonna use that folder). This way you can avoid problems (like it happened to me).
I think it's issue of MSI package/template. I'm not sure if you can implement native support to delete any directory using MSI. But I think you can create some script and put it into MSI package and you can script deletion of needed directory.
Thank you.
But how can I:
1. check the font version using a script
2. "tell" to ThinApp which one it should use
3. add it to the project to be started before the exe...?
Sorry for asking so many questions but in this matter I'm a total newbie :smileyblush:
1. check the font version using a script
I have no idea how to determine font version
. And I'm not sure if fonts have any kind of versioning.
If I would do this I would do checksum on font file I want to use and copare it to checksum used file on user's computer. Install font if checksums differ.
2. "tell" to ThinApp which one it should use
I don't understand what you mean. I think fonts are used by application and not by ThinApp. And if application is written to use for example font with name "Arial very bold", application (neither it's native or virtualized) asks OS to provide its font. There is an option to write script which will run just before running virtulized application. I would compare font files as I mentioned abobe and "install" font if needed.
All font files used in OS (windows based) are store in directory %SystemRoot%\Fonts\ and information about installed fonts are in registry key HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts so changing this two places is enought to install new font using following vbs script (script comes from web http://www.edugeek.net/forums/scripts/4756-script-install-fonts-workstations.html![]()
' ****************************************************************************
' Copy Fonts From Network Share To C:\WINDOWS\FONTS Folder Of Workstation
' ****************************************************************************
Set WshShell = CreateObject("WScript.Shell")
WshShell.Run "xcopy.exe ""\\%SERVERNAME%\%SHARE \FONTS"" ""C:\windows\fonts"" /C /I /S /E /H /Y /Q", 1,True
' ****************************************************************************
' Imports The Registry Information For The New Fonts - Add A New Line For Each New Font
' Example : WshShell. RegWrite"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\%FONT REG KEY%", "%FONT REG KEY ENTRY%", "REG_SZ"
' ****************************************************************************
Set WshShell = WScript.CreateObject("WScript.Shell")
WshShell. RegWrite"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\Twiggy-Bold (TrueType)", "Twiggy-Bold.ttf", "REG_SZ"
WshShell. RegWrite"HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Fonts\Twiggy-Light (TrueType)", "Twiggy-Light.ttf", "REG_SZ"
Of course you can add more cool stuff to this script. Some checking if file exists and so on.
3. add it to the project to be started before the exe...?
Yes, before executable of aplication. Not before ThinApp Entry Point. Read at http://pubs.vmware.com/thinapp4/help/scripts.html#996384.
Sorry for asking so many questions but in this matter I'm a total newbie :smileyblush:
That's why this forum is doing it's job well. ![]()
Ok, thank you.
Can, you, please, mark this thread as answered if you don't have more questions?
Thank you,
Ok, I will mark it, even thow I didn't get the answer 100%...
I gave up searching... I didn't know I have to mark it, sorry.
Hmm...and what other questions do you have?
Let's discuss them here.
Thank you for your kind offer but for now I have to solve other (more pressing) problems.
Best regards, Cosmin
For no 3 - I have made a small program.
It's made in Delphi and the code is:
program remset;
uses
SHFolder, Windows, Sysutils;
const
SHGFP_TYPE_CURRENT = 0;
var
path: array[0..MAX_PATH] of char;
i, fl: Integer;
Found: array of string;
s, Name: AnsiString;
Error: Boolean = False;
doAsk: Boolean = False;
isInstall: Boolean = True;
DisplayErrorMessages: Boolean = False;
function Ceil(const X: Extended): Integer;
begin
Result := Integer(Trunc(X));
if Frac(X) > 0 then
Inc(Result);
end;
procedure FindAll(DirName: string);
var sr: TSearchRec;
begin
if DirName[Length(DirName)] <> '\' then
DirName := Dirname + '\';
try
if FindFirst(DirName + '*.*', faDirectory, sr) = 0 then
repeat
if (sr.Name <> '.') and (sr.Name <> '..') then
begin
Inc(fl);
if fl > Length(Found) then
SetLength(Found, Ceil(1.1 * fl));
Found[fl - 1] := 'd ' + DirName + sr.Name;
FindAll(DirName + sr.Name);
end;
until FindNext(sr) <> 0;
FindClose(sr);
except
end;
try
if FindFirst(DirName + '*.*', faAnyFile, sr) = 0 then
repeat
Inc(fl);
if fl > Length(Found) then
SetLength(Found, Ceil(1.1 * fl));
Found[fl - 1] := 'f ' + DirName + sr.Name;
until FindNext(sr) <> 0;
FindClose(sr);
except
end;
end;
begin
if ParamCount = 0 then
begin
MessageBox(0, 'No parameter set!', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;
for i := 2 to ParamCount do
begin
if AnsiLowerCase(ParamStr(i)) = '/ask' then
doAsk := True;
if AnsiLowerCase(ParamStr(i)) = '/uninstall' then
isInstall := False;
if AnsiLowerCase(ParamStr(i)) = '/verbose' then
DisplayErrorMessages := True;
end;
try
if not SUCCEEDED(SHGetFolderPath(0, CSIDL_APPDATA, 0, SHGFP_TYPE_CURRENT, @path[0])) then
begin
if DisplayErrorMessages then
MessageBox(0, 'Problem getting AppData folder name!', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;
except
Exit;
end;
s := ParamStr(1);
if s[Length(s)] = '\' then
Delete(s, Length(s), 1);
s := ExtractFileName(s);
i := Pos(' (vmware thinapp)', AnsiLowerCase(s));
if i > 0 then
s := Copy(s, 1, i - 1);
if s = '' then
begin
if DisplayErrorMessages then
MessageBox(0, 'Error getting folder name!', 'Error', MB_OK or MB_ICONERROR);
Exit;
end;
if DirectoryExists(path + '\Thinstall\' + s) then
begin
if doAsk then
if isInstall then
begin
if MessageBox(0, PChar('Previous settings found in "AppData\Thinstall\' + s + '".'#13#10'Do you want the data to be deleted?'), 'Warning', MB_YESNO or MB_ICONWARNING) <> 6 {mrYes} then
Exit;
end
else
if MessageBox(0, PChar('Do you want the current settings from "AppData\Thinstall\' + s + '" to be deleted?'), 'Warning', MB_YESNO or MB_ICONWARNING) <> 6 {mrYes} then
Exit;
fl := 0;
FindAll(path + '\Thinstall\' + s);
if fl > 0 then
begin
for i := fl - 1 downto 0 do
begin
Name := Copy(Found[i], 3, Length(Found[i]) - 2);
try
SetFileAttributes(PChar(Name), FILE_ATTRIBUTE_NORMAL);
except
end;
try
if Found[i][1] = 'f' then
Error := not DeleteFile(Name)
else
Error := not RemoveDir(Name);
except
Error := True;
end;
end;
SetLength(Found, 0);
end;
try
Error := not RemoveDir(path + '\Thinstall\' + s);
except
Error := True;
end;
if Error and DisplayErrorMessages then
MessageBox(0, 'Not all the data could be removed...', 'Error', MB_OK or MB_ICONERROR);
end;
end.
I attached the compiled exe and I will explain how it can be used for those who might find it useful.
Now, using a msi editor (like Orca or InstEd) open template.msi from ThinApp's folder.
Add a row in Binary section with the name remset and the path to the exe file as value.
In CustomAction section add 2 rows:
RemovePreviousSettings 258 remset "[INSTALLDIR]"
RemoveCurrentSettings 258 remset "[INSTALLDIR]" /uninstall
In InstEd set 0x0102 instead of 258.
The first is for installation, the second is for uninstallation.
If you want to be asked if it's ok to delete add /ask as a parameter at Target.
In InstallExecutteSequence add these rows:
RemoveCurrentSettings REMOVE 2000
RemovePreviousSettings NOT Installed OR REINSTALL 2000
Now save the changes made to the msi file and close the editor.
Rebuild the application(s) with relink or build new one(s).
Feedback is appreciated - to help improve it...
Nice from you to share your code ![]()
No problem, it's not much of a code anyway... :smileygrin:
Later edit: I improved the code a bit. One of the improvements is that now is "silent" - it displays error messages only if /verbose parameter is used.
Question: Is there any better way to find out the path to sandbox..? Thank you.
