Cosmin2
Contributor
Contributor

a few questions...

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...

Reply
0 Kudos
Cievo
Commander
Commander

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.

***Good question is half of the answer...***
Cosmin2
Contributor
Contributor

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:

Reply
0 Kudos
Cievo
Commander
Commander

1. check the font version using a script

I have no idea how to determine font version Smiley Happy. 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:disappointed_face:

' ****************************************************************************
' 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. Smiley Happy

***Good question is half of the answer...***
Cosmin2
Contributor
Contributor

Ok, thank you.

Reply
0 Kudos
Cievo
Commander
Commander

Can, you, please, mark this thread as answered if you don't have more questions?

Thank you,

***Good question is half of the answer...***

View solution in original post

Reply
0 Kudos
Cosmin2
Contributor
Contributor

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.

Reply
0 Kudos
Cievo
Commander
Commander

Hmm...and what other questions do you have?

Let's discuss them here.

***Good question is half of the answer...***
Reply
0 Kudos
Cosmin2
Contributor
Contributor

Thank you for your kind offer but for now I have to solve other (more pressing) problems.

Best regards, Cosmin

Reply
0 Kudos
Cosmin2
Contributor
Contributor

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...

Reply
0 Kudos
Cievo
Commander
Commander

Nice from you to share your code Smiley Happy

***Good question is half of the answer...***
Reply
0 Kudos
Cosmin2
Contributor
Contributor

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.

Reply
0 Kudos