Hi I'm using Inno Setup (Delphi based) for my installer I am working on. All I want is to put the username in a String:
My code:
var
usrname: string;
begin
usrname := GetEnvironmentVariable('USERNAME');
end;
When I'm trying to compile my code, there is allways this error message:
Unknown identifier 'GetEnvironmentVariable'
What am I doing wrong? Im new in delphi so the correct way might be obvious.
The function you are looking for is called GetEnv in Inno Setup, so fix your code e.g. this way:
var
UserName: string;
begin
UserName := GetEnv('USERNAME');
end;
Using the environment for this task is the wrong solution, as the environment is hackable. Simply use the support function GetUserNameString.
(Also note that normally you should not need to use the username during an install, and that it might not be the one you really wanted if the installer is running elevated. But those are separate topics.)
Related
I'm using the JCL Delphi library in my project. Below is my code.
// uses JclSysUtils;
var cmd := TJclCommandLineTool.Create(parts[0]);
if cmd.Execute(params) then
begin
...
end;
As you can see, I use TJclCommandLineTool to invoke an external command line program. The problem is that the external program is always running in the current directory that I started my application. I want to know how can I pass a custom working directory to the external program. JCL's document is pretty lame and I can't find related information.
TJclCommandLineTool does not have options like this. So easiest way to do it:
//uses System.IOUtil;
var oldDir := TDirectory.GetCurrentDirectory;
try
TDirectory.SetCurrentDirectory(ANewProgramDir);
var cmd := TJclCommandLineTool.Create(parts[0]);
if cmd.Execute(params) then
begin
// ...
end;
finally
TDirectory.SetCurrentDirectory(oldDir);
end;
I am currently trying to connect to a database using an ODBC Alias to SQL Server. The problem I'm having is that when I use my TQuery object to get the information it always requests login details (nevermind whether I've specified them in the ODBC creation). I don't mind manually setting them in the code, but I can't find how to do that.
The most common solution I've found is to use the database component and go through that. However that comes with its own issues. Due to my dataset being so large and the database component converting the dataset to a Paradox table I keep getting a BDE error of 'Temporary Table Resource Limit'.
I don't get this error if I ignore the database component (which is fine) however this leaves me with the login prompt issue. Has anyone found a way to bypass this for TQuerys without swapping to other connection paths such as ADO?
I'm a bit rusty with the BDE but I don't think there's an easy way to avoid the login prompt if what you're saying is that you're not using a TDatabase component in your project.
The reason is that when you attempt to open your TQuery without a TDatabase (or TSession) component in your project, the default Session object in your app will call the routine below from within your TQuery's OpenCursor:
{ from DBTables.Pas }
function TSession.DoOpenDatabase(const DatabaseName: string; AOwner: TComponent): TDatabase;
var
TempDatabase: TDatabase;
begin
Result := nil;
LockSession;
try
TempDatabase := nil;
try
Result := DoFindDatabase(DatabaseName, AOwner);
if Result = nil then
begin
TempDatabase := TDatabase.Create(Self);
TempDatabase.DatabaseName := DatabaseName;
TempDatabase.KeepConnection := FKeepConnections;
TempDatabase.Temporary := True;
Result := TempDatabase;
end;
Result.Open;
Inc(Result.FRefCount);
except
TempDatabase.Free;
raise;
end;
finally
UnLockSession;
end;
end;
As you can see, if the session can't find an existing TDatabase component with the right name, it creates a temporary one, and it's the call to Result.Open that pops up the login prompt, without, so far as I can see, giving you any opportunity to supply the password + user name before the pop-up (the Session's OnPassword doesn't seem to get called in the course of this).
Obviously you need to check using the debugger that that's what's happening in your app, a temporary TDatabase being created, I mean.
If what I've suggested in the Update below didn't work and I were desperate to avoid using a TDatabase component, I would look into the possibility of maybe deriving a TQuery descendant, and trying to override its OpenCursor to see if I could jam in the user name/password.
Anyway, seeing as you say you're not using an explicit TDatabase, if I understand you correctly, because of the "Temporary Table ..." issue, and seeing as the Session will create a temporary one anyway, I suppose it might be worth your while investigating why the temporary one doesn't provoke the "Temporary Table" error, whereas using a TDatabase component in your app evidently does. Idapi32.Cfg configuration issue, maybe? At the moment, I can't help you with that because I can't reproduce your "Temporary Table" error, despite using my TQuery to do a SELECT on a SqlServer table to return 250,000+ rows.
Oh, that's a point: Does your table contain any BLOBs? I seem to recall there's an Idapi config parameter that lets you reduce the temporary storage space the BDE uses for BLOBs (to zero, maybe, but it's been a long time since I used the BDE "for real").
Update: The thought just occurred to me that since your query seems to work with Session dynamically creating a TDatabase object, maybe it would also work with a TDatabase which you dynamically create yourself. I just tried the following, and it works for me:
procedure TForm1.DatabaseLogin(Database: TDatabase;
LoginParams: TStrings);
begin
LoginParams.Add('user name=sa');
LoginParams.Add('password=1234');
end;
procedure TForm1.Button1Click(Sender: TObject);
var
ADatabase : TDatabase;
begin
ADatabase := TDatabase.Create(Self);
ADatabase.AliasName := 'MAT41032';
ADatabase.DatabaseName := 'MAT41032';
ADatabase.SessionName := 'Default';
ADatabase.OnLogin := DatabaseLogin;
Query1.Open;
end;
+1 for an interesting question, btw.
This refer to the post Delphi SOAP Envelope and WCF.
Could someone please post a sample code which can show me how to set soLiteralParams in THTTPRio.Converter.Options in Delphi 7. I have the following code currently.
I have drag-dropped a HTTPRIO component into the document which has created a line HTTPRIO1: THTTPRIO at the beginning of the code. I basically want to understand how I set soLiteralParams in the above component. Following is the code I am trying to execute which is giving me error.
procedure TForm1.CleanUpSOAP(const MethodName: String; var SOAPRequest: WideString);
var RIO: THTTPRIO;
begin
//The following line is giving error
// RIO.Converter.options := [soLiteralParams];
end;
In the above code I have declared a variable RIO of the type THTTPRIO, which I am not sure is correct.
Just guessing, as you provide very little information in your question.
Use the variable assigned to the component you dropped on your form. Don't declare a new local one (which you never created anyway). To set the Converter.Options in code, you'll need to add OPToSOAPDomConv to your uses clause.
implementation
uses
OPToSOAPDomConv;
// BTW, this name might not be a good one if it's the
// OnBeforeExecute event handler as that isn't
// clear from the name.
procedure TForm1.CleanUpSOAP(const MethodName: String; var SOAPRequest: WideString);
begin
// Note this clears any previous options!
HTTPRIO1.Converter.Options := [soLiteralParams];
// If you want to keep the previous options instead of replacing them
// HTTPRIO1.Converter1.Options := HTTPRIO1.Converter1.Options + [soLiteralParams];
end;
If you've dropped the component on the form, I'm not sure why you're not handling this in the Object Inspector instead, however.
If this doesn't solve the problem, edit your question and provide the exact error message you're receiving, including any memory addresses in the case of an exception being raised.
I have cracked this. The issue was that I didn't refer to OPconvert.pas file, which contained the TSOAPConvertOption enumeration. I don't know whether copying this file into the same folder as my project files and referring to this in the "uses" section is the right way, but it worked fine.
I have an installer that needs to install some visual c++ redistributables before anything else gets installed. This is because an ActiveX COM object wont register without it being installed first.
I have the code that properly installs the visual c++, but the program seems to hang for a minute (to the user) while it is installing since they have no clue what is happening. Is there any way to inform the user what i am doing without popping up an actual messagebox? Like how you can set the status in the [Run] block.
// This function will be called after the last "Next" button is pressed, but before any files get installed
procedure DoPreInstall();
var
ErrorCode: Integer;
begin
Exec(ExpandConstant('vcredist_x86_2008.exe'), '/q', '', SW_SHOW, ewWaitUntilTerminated, ErrorCode)
end;
end;
I haven't tried it but I found this: http://news.jrsoftware.org/news/innosetup.code/msg21747.html.
It might help. Another is to run the vcredist in a non-silent mode.
I am looking for a way to determine if the user already has a version of IIS installed. If he doesn't, I will go ahead and run my IIS installation script.
I know of the exception handling clause where I do :
try
IIS := CreateOleObject('IISNamespace');
except
RaiseException(ExceptionType, ‘IIS not installed. Setup will now install IIS on your machine. ’#13#13'(Error ‘’’+ExceptionParam+’’’ occured)’);
end;
but for some reason, my compiler version doesn't seem to recognise RaiseException. I also tried including
uses
SysUtils;
but the compiler won't recognize SysUtils even. Is there something like a registry key that I can look at to determine whether IIS is already installed or not?
Any help would be much appreciated.
Rishi you are using the RaiseException function with 2 parameters, but the this function only support one.
procedure RaiseException(const Msg: String);
try using this function like this
var
IIS : variant;
begin
try
IIS := CreateOleObject('IISNamespace');
except
RaiseException('IIS not installed. Setup will now install IIS on your machine');
end;
end;
IIS always installs to %windir%\system32\inetsrv so you should check if specific files exist under this directory. For example, w3wp.exe should exist in this folder for IIS 6/7.
Try:
[CustomMessages]
iis_title=Internet Information Services (IIS)
[Code]
function iis(): boolean;
begin
if not RegKeyExists(HKLM, 'SYSTEM\CurrentControlSet\Services\W3SVC\Security') then
MsgBox(FmtMessage(CustomMessage('depinstall_missing'), [CustomMessage('iis_title')]), mbError, MB_OK)
else
Result := true;
end
;