Create multiple text files - file

what would be a neat way to create multiple *.txt files on application
startup i.e check if they exist if not create them.
I need to create about 10 text files.
Will I have to do like this for every single file:
var
MyFile: textfile;
ApplicationPath: string;
begin
ApplicationPath := ExtractFileDir(Application.ExeName);
if not FileExists(ApplicationPath + '\a1.txt') then
begin
AssignFile(MyFile, (ApplicationPath + '\a1.txt'));
Rewrite(MyFile);
Close(MyFile);
end
else
Abort;
end;

If you only want to create the empty files (or rewrite the existing) with subsequently numbered file names, you might try something like this. The following examples use the CreateFile API function. But pay attention that several things may forbid your file creation attempts!
If you want to create (overwrite) them in all circumstances, use CREATE_ALWAYS disposition flag
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
Name: string;
Path: string;
begin
Path := ExtractFilePath(ParamStr(0));
for I := 1 to 10 do
begin
Name := Path + 'a' + IntToStr(I) + '.txt';
CloseHandle(CreateFile(PChar(Name), 0, 0, nil, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0));
end;
end;
Or if you want to create the files only if they doesn't exist, use the CREATE_NEW disposition flag
procedure TForm1.Button1Click(Sender: TObject);
var
I: Integer;
Name: string;
Path: string;
begin
Path := ExtractFilePath(ParamStr(0));
for I := 1 to 10 do
begin
Name := Path + 'a' + IntToStr(I) + '.txt';
CloseHandle(CreateFile(PChar(Name), 0, 0, nil, CREATE_NEW, FILE_ATTRIBUTE_NORMAL, 0));
end;
end;

Something like this, perhaps:
var
ApplicationDir: string;
I: Integer;
F: TextFile;
begin
ApplicationDir := ExtractFileDir(Application.ExeName);
for I := 1 to 10 do
begin
Path := ApplicationDir + '\a' + IntToStr(I) + '.txt';
if not FileExists(Path) then
begin
AssignFile(F, Path);
Rewrite(F);
Close(F);
end
end;

procedure CreateFile(Directory: string; FileName: string; Text: string);
var
F: TextFile;
begin
try
AssignFile(F, Directory + '\' + FileName);
{$i-}
Rewrite(F);
{$i+}
if IOResult = 0 then
begin
Writeln(F, Text);
end;
finally
CloseFile(f);
end;
end;
...
for i := 0 to 10 do
CreateFile(Directory, Filename, Text);

Related

How can I use an array in a procedure

This is the code I use if I'm working with one array. I want to adjust this code so that it can work with any array by using a procedure:
Var
tf: TextFile;
sWord: String;
i: Integer;
arrDurban: array of string;
begin
if Location='Durban' then
begin
i := 0;
SetLength(arrDurban, 1);
AssignFile(tf, '');
Reset(tf);
while not eof(tf) do
begin
Readln(tf, sWord);
arrDurban[i] := sWord;
Inc(i);
SetLength(arrDurban, i + 1);
end;
end;

Command Line Parms: Function Return Type As Array?

Here's the current problem:
Executing an uninstall string with command line parameters following this solution:
Here's what we have in the form of non-functioning code:
const MAX_PATH = 260;
function GetUninstallString(): TArrayOfString;
var
sUnInstPath: String;
sUnInstallString: String;
sUnInstallStringPrm: String;
begin
sUnInstPath := ExpandConstant('Software\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}');
sUnInstallString := '';
if not RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString) then
RegQueryStringValue(HKCU, sUnInstPath, 'UninstallString', sUnInstallString);
if sUnInstallString = '' Then
Begin
sUnInstPath := ExpandConstant('Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{#MyAppName}');
RegQueryStringValue(HKLM, sUnInstPath, 'UninstallString', sUnInstallString);
End;
if sUnInstallString <> '' Then
Begin
sUnInstallStringPrm:= copy(sUnInstallString, pos(' ', sUnInstallString) + 1, MAX_PATH);
MsgBox(sUnInstallStringPrm, mbInformation, MB_OK);
Delete(sUnInstallString, pos(' ', sUnInstallString), MAX_PATH);
End;
Result := [sUnInstallString, UnInstallStringPrm];
end;
/////////////////////////////////////////////////////////////////////
function IsUpgrade(): Boolean;
begin
Result := (GetUninstallString() <> '');
end;
/////////////////////////////////////////////////////////////////////
function UnInstallOldVersion(): Integer;
var
sUnInstallString: String;
iResultCode: Integer;
begin
// Return Values:
// 1 - uninstall string is empty
// 2 - error executing the UnInstallString
// 3 - successfully executed the UnInstallString
// default return value
Result := 0;
// get the uninstall string of the old app
sUnInstallString := GetUninstallString();
if sUnInstallString <> '' then begin
sUnInstallString := RemoveQuotes(sUnInstallString);
if ShellExec('open', sUnInstallString, '','', SW_SHOW, ewWaitUntilTerminated, iResultCode) then
Result := 3
else
Result := 2;
end else
Result := 1;
end;
/////////////////////////////////////////////////////////////////////
procedure CurStepChanged(CurStep: TSetupStep);
begin
if (CurStep=ssInstall) then
begin
if (IsUpgrade()) then
begin
UnInstallOldVersion();
end;
end;
end;
There is very little info on how to use GetUninstallString in this context. Possible at all?
Not sure if, as an alternative, the string array containing sUnInstallString... can be passed as a parameter within the above fixture, albeit the return type as array appears to fit a little better.
The GetUninstallString is used twice in the code.
In IsUpgrade
and in UnInstallOldVersion.
In IsUpgrade it's only tested for non-empty value.
In UnInstallOldVersion it is executed.
So make the function return whole UninstallString as a simple string.
For IsUpgrade it is enough.
And do the actual parsing to program path and its arguments in the UnInstallOldVersion only.
Also you should:
Handle a situation where there's no space in the string (no parameters)
The path to the uninstaller can contain spaces too (and it typically will as the uninstallers tend to be in Program Files).

Select items from a combobox and write index of selected value to an INI file during installation

How to make the user select an item from a combobox and then write it to an INI file as a number (01, 02, 03, ..., 18)? I generated this code but I do not know what else to do. If you could help me I would be very grateful
[INI]
Filename: "{app}\rev.ini"; Section: "steamclient"; Key: "RankLevel"; String: ""
[Code]
var
NewComboBox1: TNewComboBox;
procedure RedesignWizardForm;
begin
{ NewComboBox1 }
NewComboBox1 := TNewComboBox.Create(WizardForm);
with NewComboBox1 do
begin
Name := 'NewComboBox1';
Parent := WizardForm.SelectDirPage;
Left := ScaleX(0);
Top := ScaleY(120);
Width := ScaleX(145);
Height := ScaleY(21);
Text := 'Alcon';
Items.Text := 'Alcon' + #13#10 +
'Aguila' + #13#10 +
'Elite' + #13#10 +
'Pro';
ItemIndex := 0;
end;
NewComboBox1.TabOrder := 5;
end;
procedure InitializeWizard();
begin
RedesignWizardForm;
end;
The easiest solution is using a scripted constant in the INI section:
[INI]
Filename: "{app}\rev.ini"; Section: "steamclient"; \
Key: "RankLevel"; String: "{code:GetRankLevel}"
[Code]
{ ... }
function GetRankLevel(Param: string): string;
begin
Result := Format('%.2d', [NewComboBox1.ItemIndex + 1]);
end;
Though this will not write the INI file "in a custom page after the components section". It will write it only during the actual installation, what is the correct behavior, imho.
See also Save Inno Setup custom page field values to an INI file.

open multiple files via shell context menu as params

I want to select more than one text file in the windows explorer and open the files via context menu in my app. For one file I found the solution but for more files there some ideas but no (working) solutions.
Anyone here that has the answer?
Here is an example that i've just searched and collected from internet.
Aim: Select multiple folders in Windows Explorer and get list of these folders' names via a shell context menu item "SelectedFolders", or using SendTo menu or drag-and-drop folders from shell onto the application form.
Please put a listbox named lstSelectedFolders and a speed button named sbClearList.
The main form name is frmSelectedFolders.
Here we go.
/////////////////////////////////////////////////////////////
program selectedfolders;
uses
Windows, Messages, SysUtils, Forms,
uSelectedFolders in 'uSelectedFolders.pas' {frmSelectedFolders};
{$R *.res}
var
receiver: THandle;
i, result: integer;
s: string;
dataToSend: TCopyDataStruct;
Mutex : THandle;
begin
Mutex := CreateMutex(nil, True, 'SelectedFolders');
if (Mutex <> 0) and (GetLastError = 0) then
begin
Application.Initialize;
Application.Title := 'Selected Folders';
Application.CreateForm(TfrmSelectedFolders, frmSelectedFolders);
Application.Run;
if Mutex <> 0 then CloseHandle(Mutex);
end
else
begin
receiver := FindWindow(PChar('TfrmSelectedFolders'), PChar('Selected Folders'));
if receiver <> 0 then
begin
for i:=1 to ParamCount do
begin
s := trim(ParamStr(i));
if s <> '' then
begin
dataToSend.dwData := 0;
dataToSend.cbData := 1 + Length(s);
dataToSend.lpData := PChar(s);
result := SendMessage(receiver, WM_COPYDATA, Integer(Application.Handle), Integer(#dataToSend));
//sleep(100);
//if result > 0 then
// ShowMessage(Format('Sender side: Receiver has %d items in list!', [result]));
end;
end; // for i
end;
end;
end.
/////////////////////////////////////////////////////////////
unit uSelectedFolders;
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls, ShellAPI, ActiveX, ComObj, ShlObj, Registry, Buttons;
type
TfrmSelectedFolders = class(TForm)
lstSelectedFolders: TListBox;
sbClearList: TSpeedButton;
procedure FormCreate(Sender: TObject);
procedure sbClearListClick(Sender: TObject);
private { Private declarations }
public { Public declarations }
procedure WMDROPFILES(var Message: TWMDROPFILES); message WM_DROPFILES;
procedure WMCopyData(var Msg: TWMCopyData); message WM_COPYDATA;
function GetTarget(const LinkFileName: string): string;
end;
var
frmSelectedFolders: TfrmSelectedFolders;
implementation
{$R *.dfm}
procedure RegisterContextMenuForFolders();
const
Key = 'Directory\shell\SelectedFolders\command\';
begin
with TRegistry.Create do
try
// for all users, class registration for directories
RootKey := HKEY_CLASSES_ROOT;
if OpenKey(Key, true) then
WriteString('', '"' + Application.ExeName + '" "%l"');
finally
Free;
end;
end;
procedure TfrmSelectedFolders.WMDROPFILES(var Message: TWMDROPFILES);
var
N, i: integer;
buffer: array[0..255] of Char;
s: string;
begin
try
N := DragQueryFile(Message.Drop, $FFFFFFFF, nil, 0);
for i:=1 to N do
begin
DragQueryFile(Message.Drop, i-1, #buffer, SizeOf(buffer));
s := buffer;
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
end;
finally
DragFinish(Message.Drop);
end;
end;
function TfrmSelectedFolders.GetTarget(const LinkFileName: string): string;
var
//Link : String;
psl : IShellLink;
ppf : IPersistFile;
WidePath : Array[0..260] of WideChar;
Info : Array[0..MAX_PATH] of Char;
wfs : TWin32FindData;
begin
if UpperCase(ExtractFileExt(LinkFileName)) <> '.LNK' then
begin
Result := 'NOT a shortuct by extension!';
Exit;
end;
CoCreateInstance(CLSID_ShellLink, nil, CLSCTX_INPROC_SERVER, IShellLink, psl);
if psl.QueryInterface(IPersistFile, ppf) = 0 Then
Begin
MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, PChar(LinkFileName), -1, #WidePath, MAX_PATH);
ppf.Load(WidePath, STGM_READ);
psl.GetPath(#info, MAX_PATH, wfs, SLGP_UNCPRIORITY);
Result := info;
end
else
Result := '';
end;
procedure TfrmSelectedFolders.WMCopyData(var Msg: TWMCopyData);
var
s: string;
begin
s := trim(PChar(Msg.copyDataStruct.lpData));
if s = '' then
begin
msg.Result := -1;
exit;
end;
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
msg.Result := lstSelectedFolders.Items.Count;
end;
procedure TfrmSelectedFolders.FormCreate(Sender: TObject);
var
i: integer;
s: string;
begin
RegisterContextMenuForFolders();
DragAcceptFiles(Handle, TRUE);
lstSelectedFolders.Clear;
s := ExtractFileDir(Application.ExeName);
lstSelectedFolders.Items.Add(s);
for i:=1 to ParamCount do
begin
s := trim(ParamStr(i));
if UpperCase(ExtractFileExt(s)) = '.LNK' then
s := GetTarget(s);
if lstSelectedFolders.Items.IndexOf(s) < 0 then
lstSelectedFolders.Items.Add(s);
end;
end;
procedure TfrmSelectedFolders.sbClearListClick(Sender: TObject);
begin
lstSelectedFolders.Clear;
end;
end.

PASCAL: Looping through an array to create folders?

So I am creating a pascal script that will create a directory within a main directory and ALSO create multiple folders inside of that new directory. (Insert XZibit pun)
Now the way we do this where I work, we send these variables to an exe that will then create directories based on what is being passed (in this case, path 'fullpath').
I am not sure if I am approaching this correctly and would love the much more prominent PASCAL guru's input :)
const
ARRAY1: Array[1..9] of String = (
'NQN', 'Documents', 'Correspondences',
'Worksheets', 'Reports', 'Claims',
'Certificate of Insurance', 'Invoice', 'Monthly Reports'
);
var
i: Integer;
fullpath, path, name, os, es, cmd: String;
Code : LongWord;
res: Integer;
Begin
path := 'Policies'
fullpath := path+'\'+[i]
for i := 1 to 9 do
IF(ReqList.Values['sRM_ID'] = '') then
Begin
cmd := 'C:\XXX\bin\mkdir.exe "'+fullpath+'"';
res :=ExecuteProc(cmd, 'C:\XXX\bin', true, -1, true, nil, os, es, code);
if(res = 0) then
Begin
ReqList.values['NoErrors'] := '1';
ReqList.Values['Response_content']:= '{"valid":"1","message":"'+ReplaceString(ReplaceString(os,#13,'',false),#10,'',false)+'"}';
end
else
begin
ReqList.Values['NoErrors'] := '0';
Reqlist.Values['Response_Content'] := '{"valid":"0","message":"'+ReplaceString(ReplaceString(os,#13,'',false),#10,'',false)+'"}';
end;
END
ELSE
Begin
ReqList.Values['Response_Content'] := '{"valid":"0","message":"A folder or file with the same name already exists."}';
End;
ReqList.Values['Response_ContentType'] := 'HTML';
Once you identify the absolute path for each entry in your array, ForceDirectories will create them if they don't already exist, as bummi suggested above.
Assuming your root path is relative to the current executable path, it could be as simple as this:
const
ARRAY1: Array [1 .. 9] of String = ('NQN', 'Documents', 'Correspondences',
'Worksheets', 'Reports', 'Claims', 'Certificate of Insurance', 'Invoice',
'Monthly Reports');
var
s: string;
path: string;
fullpath: string;
begin
path := 'Policies';
for s in ARRAY1 do
begin
fullpath := ExpandFileName(IncludeTrailingPathDelimiter(path) + s);
ForceDirectories(fullpath);
end;
end;

Resources