Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Mike Lewis on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Finding AppData path on Citrix etc

Status
Not open for further replies.

torhenrik

Programmer
Sep 27, 2010
11
BG
Hi All,

I have an application that store User and Application data in
"All Users\Application Data" and "[User Specific]\Application Data"
using CSIDL_COMMON_APPDATA and CSIDL_LOCAL_APPDATA.

My problem is that when my application is used in a Citrix or Terminal Services environment the files created in these directories is deleted next time the user log on.

I do not have a great knowledge in either Citrix or Terminal Services but know that the administrator sets up these directories to be elsewhere so the user can access them.

My question is: Does anyone know if there exists variables as CSIDL_COMMON_APPDATA and CSIDL_LOCAL_APPDATA I can use in Citrix and other equivalent systems to find these directories?
 
(about page 34)


It appears the standard Microsoft paths work for Citrix.

Look towards the bottom of the second page, there will be function prototypes that are used in Microsoft systems for working with these variables. Since I don't know what is available in Citrix (probably equivalent though I'm not sure), I hesitate to give you an example that might not work. So please post back if this isn't enough, and you can clarify what is available to you, if you need an example of how to handle these paths.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
I realized this might be useful to someone else. I know this works on Windows, so hopefully it can be useful to someone there.

You might find some of these definitions in units on newer Delphis than what I test/work on:

Code:
const
  SHGFP_TYPE_DEFAULT = 0;
// constants occur in SHFolder or SHLOBJ unit depending on Delphi
  CSIDL_LOCAL_APPDATA = $001C;
  CSIDL_COMMON_APPDATA = $0023;

function SHGetFolderPath(hwndOwner: HWnd; nFolder: Integer;
hToken:THandle; dwFlag: DWord; pszPath: PChar): HResult; stdcall;
external 'shell32.dll' name 'SHGetFolderPathA';

function GetCSIDLPath(PathID: Integer): string;
  var
    pathstr: array[0..MAX_PATH] of char;
  begin
    SHGetFolderPath(Application.Handle, PathID,
                  0, SHGFP_TYPE_DEFAULT, pathstr);
    Result := Pathstr;
  end;

Example call:
Code:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ShowMessage(GetCSIDLPath(CSIDL_COMMON_APPDATA));
end;

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Thanks for your quick reply, Glenn9999!

Maybe I misunderstood you but I think that it was not quite what I was looking for. I know that these variables also works in Citrix, but my problem is that the administrators that configure the Citrix-systems overrules these setting and configure their own user- and common-file directories. So when I store my data in the directories I get when using CSIDL_COMMON_APPDATA and CSIDL_LOCAL_APPDATA the result is that in some systems they are only saved in that session and in other system they are not saved at all, generating an error message saying the user do not have access to these directories.

So what I am wondering is when these directories are overruled, it must be somewhere in the system I can get hold of where common files and user files should be stored and therefore there must, hopefully, excists something I can use to get hold of these directories.
 
Those variables should return whatever they are set to. I actually think I need to use SHGFP_TYPE_CURRENT on the code above.

But anyway, that code I posted is what you use in Windows to obtain the CSIDL name for whatever you put into it.

Does Windows stuff work on Citrix? It seems like you're getting more into Citrix stuff if what I posted isn't sufficient. Try in this forum and see if you get an answer.

forum48

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
I researched this. The proper constants for the function above are as follows:

Code:
const
  SHGFP_TYPE_CURRENT = 0;
  SHGFP_TYPE_DEFAULT = 1;

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
I have done some more investigation surrounding my problem and here is what I have come up with.
First, here is my code that does not work in the Citrix environment:
Code:
function GetSpecialFolderPath(sFolder : string) : string;
const
  SHGFP_TYPE_CURRENT = 0;
var
  path: array [0..MAX_PATH] of char;
  iType : integer;
begin
   iType := -1;
   case StringToCaseSelect(sFolder,['curr_user_my_doc', 'all_user_my_doc', 'curr_user_my_app_data', 'all_user_my_app_data']) of
      0: iType := CSIDL_PERSONAL;
      1: iType := CSIDL_COMMON_DOCUMENTS;
      2: iType := CSIDL_LOCAL_APPDATA;
      3: iType := CSIDL_COMMON_APPDATA;
   end;
   if SUCCEEDED(SHGetFolderPath(0,iType,0,SHGFP_TYPE_CURRENT,@path[0])) then
      Result := path
   else
       Result := '';
end;

So I decided to try to approach it from a different angel, namely looking in the registry instead. I made a small program that listed the information in HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\AppData
and
HKEY_LOCAL_MACHINE\Software\Microsoft\Windows\CurrentVersion\Explorer\User Shell Folders\Common AppData

This worked well on my computer. And on the Citrix Server I got the correct path for AppData, but no result for the Common AppData.
It turns out that I can, using RegEdit or RegEdt32, see the information in HKEY_LOCAL_MACHINE\..\Common AppData but my program can not!
So I changed my old problem with a new one. I see that the function GetDataSize returns -1 for the HKEY_LOCAL_MACHINE-key on the server. Not on my computer.
I would excpect that when I can read this key using Regedit, my program should also be able to read it. So now I am getting kind of desperate and are considering using ExpandEnvironmentStrings to check if there is a path for %ALLUSERSPROFILE% or %PROGRAMDATA%. Which I think is very sloppy programming indeed...

 
Have you tried the function I put in this thread, exactly as posted?

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
I have to admit that I had not. At first glance it looked more or less like the code I already was running. But now I have and the result is unfortunately the same as with my code. Just to make sure I did nothing wrong, here is the code I was just running on the Citrix server:

Code:
unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,   SHFolder,
  Dialogs, StdCtrls;

type
  TForm1 = class(TForm)
    Button1: TButton;
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}
function GetCSIDLPath(PathID: Integer): string;
const
  SHGFP_TYPE_CURRENT = 0;
  SHGFP_TYPE_DEFAULT = 1;
// constants occur in SHFolder or SHLOBJ unit depending on Delphi
  var
    pathstr: array[0..MAX_PATH] of char;
  begin
    SHGetFolderPath(Application.Handle, PathID,
                  0, SHGFP_TYPE_DEFAULT, pathstr);
    Result := Pathstr;
  end;

procedure TForm1.Button1Click(Sender: TObject);
const
  CSIDL_LOCAL_APPDATA = $001C;
  CSIDL_COMMON_APPDATA = $0023;

begin
   ShowMessage(GetCSIDLPath(CSIDL_COMMON_APPDATA));
   ShowMessage(GetCSIDLPath(CSIDL_LOCAL_APPDATA));
end;

end.
The paths I get in return from GetCSIDLPath is not the correct ones and differs from the ones in the registry.
 
The paths I get in return from GetCSIDLPath is not the correct ones and differs from the ones in the registry.

I would make sure that any constants that I listed are removed if they exist in SHFolder. Those might be different on Citrix than on Windows. But since I've been testing CSIDL's quite extensively lately (the function above, plus the directory browser component I posted here), I haven't run into a problem as you describe querying the local machine with this API.

But it might be good to consult with someone that has a little more knowledge about Citrix and see if you're doing something a bit different than expected.

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
And off the direct topic of the thread, it's interesting to study how much Microsoft has changed this particular API functioning. They used to have straight API calls (GetWindowsDirectory, GetSystemDirectory). Those got deprecated in favor of what we are discussing here (you use CSIDL_WINDOWS, and CSIDL_SYSTEM respectively). I understand that there are many more relevant configurable folders, which is why the API was changed. But then this API became deprecated in Vista and 7 when they went to a KNOWNFOLDERID API.

And as I understand, all 3 are supported to some extent on all of them for backward compatibility sake.

Fun stuff. :rolleyes

It is not possible for anyone to acknowledge truth when their salary depends on them not doing it.
 
Found a nice little thing called %APPDATA% that gives me exactly what I want. Thank you very much all of you for valuable help :)! Would not be able to solve this without you.
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top