Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
?
Solved

Using a local Users Application Data folder issue with access

Posted on 2006-04-17
11
Medium Priority
?
583 Views
Last Modified: 2010-04-05
Hi,

I have a little program that I want to store some application settings in the local users Application Data folder, i'm creating this program with Delphi 7, however whenever I try to use TiniFile to write some information to the inifile if it doesn't exist (defaults basically).

Here is the code i'm using to try and write to the inifile...

procedure TAddInModule.CreateBlankSettings(cType:char);
begin
  try
    case cType of
      'G': begin
          SettingsIni := TIniFile.Create(sLocalSettingsPath);
          if assigned(SettingsIni) then begin
            SettingsIni.WriteString('EM', 'AllowChanges', 'True');                              //THIS IS THE LINE IT DIES AT
            SettingsIni.WriteString('EM', 'StartupFolder', 'Outlook Today (HN Style)');
            SettingsIni.WriteString('EM', 'TabSite','HN Folder');
            Settingsini.WriteString('EM', 'CustomSite','http://');
          end;
      end;
      'U': begin
          Settingsini := TIniFile.Create(sLocalUserSettingsPath);
          SettingsIni.WriteString(sCurrentUserAddress, 'UserType', 'Local');
          SettingsIni.WriteString(sCurrentUserAddress, 'StartupFolder', 'Outlook Today (HN Style)');
          SettingsIni.WriteString(sCurrentUserAddress,'TabSite', 'HN Folder');
          Settingsini.WriteString(sCurrentUserAddress,'CustomSite', 'http://');
          Settingsini.WriteString(sCurrentUserAddress,'Version', sVersion);
      end;
    end;
  finally
    Settingsini.Free;
  end;
end;

for Reference the sLocalSettingsPath = the Windows API App Data folder + '\EM\HN.ini'
I've checked the path and its all fine.  I can create folders either manually or with Delphi, but cannot edit this ini file.  As a test I've also created a blank ini file in this location, and it still breaks down at the same spot.

If anyone has any ideas, it would be greatly appreciated.  If you require more info, please let me know, I'll be checking this regularly as I need to find a solution quite quickly.  While these settings I could store in the registry (and at some point I might even change that) this is a Outlook Addin that requires a seperate PST File to be stored locally, in a location that would be somewhat secure from Users accidently deleting their information.

Thanks
0
Comment
Question by:beezee
  • 3
  • 2
  • 2
  • +4
11 Comments
 
LVL 6

Expert Comment

by:Imthiyaz_ph
ID: 16475741
Is this is an executable file or some kind of dll?
Could you also please mention the exception message here.
0
 
LVL 9

Expert Comment

by:sun4sunday
ID: 16476764
If the applicaiton is running under a user Limited account with windowsXP , will face problem to write into the files.
sun4sunday.
0
 
LVL 26

Expert Comment

by:Eddie Shipman
ID: 16478158
I would suppose that it is the particular user account that has problems with not being able to create or modify files in
that directory.
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
LVL 17

Expert Comment

by:TheRealLoki
ID: 16481185
I dont think you are using a filename, try this

SettingsIni := TIniFile.Create(InclideTrailingBackslash(sLocalSettingsPath) + 'MYINIFILENAME.ini');
0
 
LVL 17

Expert Comment

by:TheRealLoki
ID: 16481216
oops, I should have read the entire question first :-D
Is this running as a service by any chance?
What is the actual error message you receive when you try to do this?
0
 
LVL 9

Expert Comment

by:bernani
ID: 16482246
Don't know if it's what you want (code below is a form with 2 buttons. A Click on the first buttons creates the file in the COMMON_APPDATA folder (for all users) with hn.ini file with settings declared for 'G' and the same for 'U' with the click on the second button but writing the file in the COMMON_DOCUMENTS folder (for all users) - Tested on XP with administrator's rights.

unit Unit1;

interface

uses
{add : IniFiles,ShellApi,ShlObj, FileCtrl}
  Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, IniFiles,ShellApi, StdCtrls, ShlObj, FileCtrl;


type
  TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
  sLocalSettingsPath, sLocalUserSettingsPath, sCurrentUserAddress, sVersion: String;
  SettingsIni : TIniFile;

{Add those lines}
Const
  CSIDL_COMMON_APPDATA   = $0023;   // all users common application data
  CSIDL_COMMON_DOCUMENTS = $002E; // all users documents folder

implementation


{$R *.DFM}

Function SpecialFolder(Form:Tform; Folder: Integer): String;
var
  SFolder : pItemIDList;
  SpecialPath : Array[0..MAX_PATH] Of Char;
begin
  SHGetSpecialFolderLocation(Form.Handle, Folder, SFolder);
  SHGetPathFromIDList(SFolder, SpecialPath);
  Result := StrPas(SpecialPath);
end;


procedure CreateBlankSettings(cType:char);
begin
ForceDirectories(SpecialFolder(Form1, CSIDL_COMMON_APPDATA)+ '\EM\');
sLocalSettingsPath:= SpecialFolder(Form1, CSIDL_COMMON_APPDATA)+ '\EM\HN.ini';

ForceDirectories(SpecialFolder(Form1, CSIDL_COMMON_DOCUMENTS)+ '\EM\');
sLocalUserSettingsPath:= SpecialFolder(Form1, CSIDL_COMMON_DOCUMENTS)+ '\EM\HN.ini';

sCurrentUserAddress := 'Test Current user adress';
sVersion := 'Test Version';
  try
    case cType of

      'G': begin
          SettingsIni := TIniFile.Create(sLocalSettingsPath);
          if assigned(SettingsIni) then begin
            SettingsIni.WriteString('EM', 'AllowChanges', 'True');                              //THIS IS THE LINE IT DIES AT
            SettingsIni.WriteString('EM', 'StartupFolder', 'Outlook Today (HN Style)');
            SettingsIni.WriteString('EM', 'TabSite','HN Folder');
            Settingsini.WriteString('EM', 'CustomSite','http://');
          end;
      end;

      'U': begin
          Settingsini := TIniFile.Create(sLocalUserSettingsPath);
          SettingsIni.WriteString(sCurrentUserAddress, 'UserType', 'Local');
          SettingsIni.WriteString(sCurrentUserAddress, 'StartupFolder', 'Outlook Today (HN Style)');
          SettingsIni.WriteString(sCurrentUserAddress,'TabSite', 'HN Folder');
          Settingsini.WriteString(sCurrentUserAddress,'CustomSite', 'http://');
          Settingsini.WriteString(sCurrentUserAddress,'Version', sVersion);
      end;
    end;
  finally
    Settingsini.Free;
  end;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
CreateBlankSettings('G');
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
CreateBlankSettings('U');
end;

end.


0
 

Author Comment

by:beezee
ID: 16482349
Thanks all for the quick response, this is a Outlook Add-in, so dll.

The exception on the other hand really doesn't help me much, no error number or address just that the Add-in fired an exception.

---------------------------
Error
---------------------------
EM error: the add-in has fired an exception.
Unable to write to "C:\Documents and Settings\<uname>\Application Data\<busname>\EM\EM.ini"
---------------------------
OK  
---------------------------
0
 

Author Comment

by:beezee
ID: 16482520
After a quick test of bernani's code, works great on a normal App, but when put into my DLL Still fails, the user account has the full control in the security settings, so I don't think this is the issue.  I'm starting to think its something to do with it being a DLL...

For reference, when I moved bernani's code to my dll and made slight modifications (ie it has no form), the force directories still worked, creating directories, just not files.
0
 
LVL 9

Accepted Solution

by:
bernani earned 2000 total points
ID: 16492780
Strange, I test this in a dll and test application and it's working for me. The folders are correctly created with the ini files in them:

The dll code
____________________________________________________________________________
library DllTest; {DllTest.dpr}

{ Remarque importante concernant la gestion de mémoire des DLL : ShareMem doit être
  la première unité de la clause USES de votre bibliothèque ET de votre projet
  (sélectionnez Projet-Voir source) si votre DLL exporte des procédures ou des
  fonctions qui passent des chaînes comme paramètres ou résultats de fonctions.
  Ceci s'applique à toutes les chaînes passées de et vers votre DLL - même celles
  qui sont imbriquées dans des enregistrements et classes. ShareMem est l'unité d'interface pour
  le gestionnaire de mémoire partagée BORLNDMM.DLL, qui doit être déployé avec
  vos DLLs. Pour éviter d'utiliser BORLNDMM.DLL, passez les informations de chaînes
  avec des paramètres PChar ou ShortString.}

uses
  ShareMem,
  SysUtils,
  Classes,
  Forms,
  Windows,
  Messages,
  Graphics,
  Controls,
  Dialogs,
  inifiles,
  shellapi,
  StdCtrls,
  ShlObj,
  filectrl;

var
  sLocalSettingsPath, sLocalUserSettingsPath, sCurrentUserAddress, sVersion: String;
  SettingsIni : TIniFile;

const
  CSIDL_COMMON_APPDATA   = $0023;
  CSIDL_COMMON_DOCUMENTS = $002E;

{$R *.RES}

function SpecialFolder(Folder: Integer): PChar;stdcall;
var
  SFolder : pItemIDList;
  SpecialPath : Array[0..MAX_PATH] Of Char;
begin
  SHGetSpecialFolderLocation(0, Folder, SFolder);
  SHGetPathFromIDList(SFolder, SpecialPath);
  Result := Pchar(StrPas(SpecialPath));
end;

procedure CreateBlankSettings(cType:char);stdcall;
begin
{needs filectrl in use clause}
// be sure the folder exists and create it if not true
//you could check this elsewhere - put here for simplification
forcedirectories(SpecialFolder(CSIDL_COMMON_APPDATA)+ '\EM\');
sLocalSettingsPath:= SpecialFolder( CSIDL_COMMON_APPDATA)+ '\EM\HN.ini';
forcedirectories(SpecialFolder( CSIDL_COMMON_DOCUMENTS)+ '\EM\');
sLocalUserSettingsPath:= SpecialFolder(CSIDL_COMMON_DOCUMENTS)+ '\EM\HN.ini';
sCurrentUserAddress := 'Current user adress from the DllTest';
sVersion := 'Version from Dll';
  try
    case cType of
      'G': begin
          SettingsIni := TIniFile.Create(sLocalSettingsPath);
          if assigned(SettingsIni) then begin
            SettingsIni.WriteString('EM', 'AllowChanges', 'True');                              //THIS IS THE LINE IT DIES AT
            SettingsIni.WriteString('EM', 'StartupFolder', 'Outlook Today (HN Style)');
            SettingsIni.WriteString('EM', 'TabSite','HN Folder');
            Settingsini.WriteString('EM', 'CustomSite','http://');
          end;
      end;
      'U': begin
          Settingsini := TIniFile.Create(sLocalUserSettingsPath);
          SettingsIni.WriteString(sCurrentUserAddress, 'UserType', 'Local');
          SettingsIni.WriteString(sCurrentUserAddress, 'StartupFolder', 'Outlook Today (HN Style)');
          SettingsIni.WriteString(sCurrentUserAddress,'TabSite', 'HN Folder');
          Settingsini.WriteString(sCurrentUserAddress,'CustomSite', 'http://');
          Settingsini.WriteString(sCurrentUserAddress,'Version', sVersion);
      end;
    end;
  finally
    Settingsini.Free;
  end;
end;

exports
SpecialFolder,
CreateBlankSettings;

begin
{code to procede on open}
end.


The application test (1 form + 2 buttons)
__________________________________

unit Unit1; {unit1.pas}

interface

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

type
  TForm1 = class(TForm)
    Button3: TButton;
    Button4: TButton;
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
  private
    { Déclarations privées }
  public
    { Déclarations publiques }
  end;

var
  Form1: TForm1;
  function SpecialFolder(Folder: Integer): PChar;stdcall;external 'DllTest.dll';
  procedure CreateBlankSettings(cType:char); stdcall;external 'DllTest.dll';

implementation

{$R *.DFM}

procedure TForm1.Button3Click(Sender: TObject);
begin
CreateBlankSettings('G');
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
CreateBlankSettings('U');
end;

end.

__________________________________________

{Unit1.dfm}

object Form1: TForm1
  Left = 189
  Top = 113
  Width = 128
  Height = 163
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object Button3: TButton
    Left = 16
    Top = 24
    Width = 75
    Height = 25
    Caption = 'G'
    TabOrder = 0
    OnClick = Button3Click
  end
  object Button4: TButton
    Left = 16
    Top = 56
    Width = 75
    Height = 25
    Caption = 'U'
    TabOrder = 1
    OnClick = Button4Click
  end
end
0
 

Author Comment

by:beezee
ID: 16493374
I've accepted this as it works beautifully in a clean app calling a dll function scenario.  For some reason when running an Outlook Com Add-In, TiniFile is unable to write to the AppData path be it the Common path or not.  Unfortunately at this stage I don't have the time to figure out exaclty why this wont work...  I have found that I can create a PST File in the AppData folder of my choice, it just seems that TiniFile in that particular spot dies.

Thanks for all your help especially bernani for all the test source code :)

If I do stumble over a solution in the near future I'll be sure to come back and post it.

Thanks all.
0
 
LVL 1

Expert Comment

by:jjoz
ID: 27751650
 
how can I access the following folder:<!--[if gte mso 9]>   Normal  0          false  false  false    EN-AU  X-NONE  X-NONE                                 MicrosoftInternetExplorer4                                     <![endif]--><!--[if gte mso 9]>                                                                                                                                                                                                                                                                                    <![endif]--><!--[if gte mso 10]><![endif]-->C:\Users\username\Application Data


i got access denied when I'm an administrator ?

0

Featured Post

Upgrade your Question Security!

Your question, your audience. Choose who sees your identity—and your question—with question security.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction The parallel port is a very commonly known port, it was widely used to connect a printer to the PC, if you look at the back of your computer, for those who don't have newer computers, there will be a port with 25 pins and a small print…
Exchange organizations may use the Journaling Agent of the Transport Service to archive messages going through Exchange. However, if the Transport Service is integrated with some email content management application (such as an anti-spam), the admin…
When cloud platforms entered the scene, users and companies jumped on board to take advantage of the many benefits, like the ability to work and connect with company information from various locations. What many didn't foresee was the increased risk…
Suggested Courses
Course of the Month14 days, 17 hours left to enroll

578 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question