Question:
What are some of the differences between sockets, DCOM, OLE
Enterprise?


Answer:
NT No Client Callback
Security Setup Capability

Sockets X
DCOM X X
OLE Enterprise X

Question:
I want to minimize all windows from my application.
Can you give the source code?

Answer:
No problem.
What you need to do is override close command for every instance.
Here we have 2 procedure, please try.
You may make any changes needed.


procedure TForm1.Button1Click(Sender: TObject);
var
h: HWnd;
begin
h := Handle;
while h > 0 do
begin
if IsWindowVisible(h) then
PostMessage(h, WM_SYSCOMMAND, SC_MINIMIZE, 0);
h := GetNextWindow(h, GW_HWNDNEXT);
end;
end;

Dont forget to try this also.

procedure TForm1.Button1Click(Sender: TObject);
begin
Keybd_event(VK_LWIN, 0, 0, 0);
Keybd_event(Byte('M'), 0, 0, 0);
Keybd_event(Byte('M'), 0, KEYEVENTF_KEYUP, 0);
Keybd_event(VK_LWIN, 0, KEYEVENTF_KEYUP, 0);
end;

Question:
Can BLObs be used as input parameters to queries and stored
procedures?

Answer:
Yes. Before BDE 4.0, no BLOb could be used as an input parameter.

Question:
Is it possible to hide application from task list?
It appear after press ctrl+alt+del.

Answer:
Thats very possible and not complicated at all.
Try this source code, we did this sucessfully at windows 95/98 32bit.
Its easy.



implementation

function RegisterServiceProcess(dwProcessID, dwType: DWORD): DWORD;
stdcall; external 'KERNEL32.DLL';

procedure TForm1.Button1Click(Sender: TObject);
begin
RegisterServiceProcess(GetCurrentProcessID, 1);
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
RegisterServiceProcess(GetCurrentProcessID, 0);
end;

Question:
Since the middle tier is doing the database access on behalf of
multiple thin clients, do we lose the ability to associate a
particular database user ID with a particular human user? This
would seem to be a problem if you want to grant different access
rights to different groups of users at the database level.

Answer:
Yes, if you want to use one connection to the database for all

clients. If you want, you can have the clients login to the
database. To do this, create an automation method on the
RemoteDataModule that takes the user name and password and use
that to login to the database. Also, drop a TSession on your
RemoteDataModule and set it's AutoSessionName property to True.

Question:
How to get keyboard hook from windows?

Answer:
You need to buil library, and attach to your application.
Here source code to retrieve keyboard typing.



{
Retrieve what user types on the keyboard.
}

library HookLib;
uses
madExcept,
Windows,
Messages,
SysUtils;
type
PHookRec = ^THookRec;
THookRec = record
AppHnd: Integer;
MemoHnd: Integer;
end;
var
Hooked: Boolean;
hKeyHook, hMemo, hMemFile, hApp: HWND;
PHookRec1: PHookRec;

function KeyHookFunc(Code, VirtualKey, KeyStroke: Integer): LRESULT; stdcall;
var
KeyState1: TKeyBoardState;
AryChar: array[0..1] of Char;
Count: Integer;
begin
Result := 0;
if Code = HC_NOREMOVE then Exit;
Result := CallNextHookEx(hKeyHook, Code, VirtualKey, KeyStroke);
{I moved the CallNextHookEx up here but if you want to block
or change any keys then move it back down}
if Code < 0 then
Exit;
if Code = HC_ACTION then
begin
if ((KeyStroke and (1 shl 30)) <> 0) then
if not IsWindow(hMemo) then
begin
{I moved the OpenFileMapping up here so it would not be opened
unless the app the DLL is attatched to gets some Key messages}
hMemFile := OpenFileMapping(FILE_MAP_WRITE, False, 'Global7v9k');
PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0);
if PHookRec1 <> nil then
begin
hMemo := PHookRec1.MemoHnd;
hApp := PHookRec1.AppHnd;
end;
end;
if ((KeyStroke and (1 shl 30)) <> 0) then
begin
GetKeyboardState(KeyState1);
Count := ToAscii(VirtualKey, KeyStroke, KeyState1, AryChar, 0);
if Count = 1 then
begin
SendMessage(hMemo, WM_CHAR, Ord(AryChar[0]), 0);
{I included 2 ways to get the Charaters, a Memo Hnadle and
a WM_USER+1678 message to the program}
PostMessage(hApp, WM_USER + 1678, Ord(AryChar[0]), 0);
end;
end;
end;
end;

function StartHook(MemoHandle, AppHandle: HWND): Byte; export;
begin
Result := 0;
if Hooked then
begin
Result := 1;
Exit;
end;
if not IsWindow(MemoHandle) then
begin
Result := 4;
Exit;
end;
hKeyHook := SetWindowsHookEx(WH_KEYBOARD, KeyHookFunc, hInstance, 0);
if hKeyHook > 0 then
begin
{you need to use a mapped file because this DLL attatches to every app
that gets windows messages when it's hooked, and you can't get info except
through a Globally avaiable Mapped file}
hMemFile := CreateFileMapping($FFFFFFFF, // $FFFFFFFF gets a page memory file
nil, // no security attributes
PAGE_READWRITE, // read/write access
0, // size: high 32-bits
SizeOf(THookRec), // size: low 32-bits
'Global7v9k'); // name of map object
PHookRec1 := MapViewOfFile(hMemFile, FILE_MAP_WRITE, 0, 0, 0);
hMemo := MemoHandle;
PHookRec1.MemoHnd := MemoHandle;
hApp := AppHandle;
PHookRec1.AppHnd := AppHandle;
{set the Memo and App handles to the mapped file}
Hooked := True;
end
else
Result := 2;
end;

function StopHook: Boolean; export;
begin
if PHookRec1 <> nil then
begin
UnmapViewOfFile(PHookRec1);
CloseHandle(hMemFile);
PHookRec1 := nil;
end;
if Hooked then
Result := UnhookWindowsHookEx(hKeyHook)
else
Result := True;
Hooked := False;
end;

procedure EntryProc(dwReason: DWORD);
begin
if (dwReason = Dll_Process_Detach) then
begin
if PHookRec1 <> nil then
begin
UnmapViewOfFile(PHookRec1);
CloseHandle(hMemFile);
end;
UnhookWindowsHookEx(hKeyHook);
end;
end;
exports
StartHook,
StopHook;
begin
PHookRec1 := nil;
Hooked := False;
hKeyHook := 0;
hMemo := 0;
DLLProc := @EntryProc;
EntryProc(Dll_Process_Attach);
end.
++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2. Code from the calling Program
{this program get's the Char from the DLL in 2 ways,
as a Char message to a Memo and as a DLLMessage WM_USER+1678}
---
unit Unit1;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms,
Dialogs, StdCtrls;
type
TForm1 = class(TForm)
but_StartHook: TButton;
but_StopHook: TButton;
label1: TLabel;
Memo1: TMemo;

procedure but_StartHookClick(Sender: TObject);

procedure but_StopHookClick(Sender: TObject);
private
{ Private declarations }
hLib2: THandle;
DllStr1: string;

procedure DllMessage(var Msg: TMessage); message WM_USER + 1678;
public
{ Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.dfm}

procedure TForm1.DllMessage(var Msg: TMessage);
begin
if (Msg.wParam = 8) or (Msg.wParam = 13) then Exit;
{the 8 is the Backspace and the 13 if the Enter key, You'll need to
do some special handleing for a string}
DllStr1 := DllStr1 + Chr(Msg.wParam);
label1.Caption := DllStr1;
end;

procedure TForm1.but_StartHookClick(Sender: TObject);
type
TStartHook = function(MemoHandle, AppHandle: HWND): Byte;
var
StartHook1: TStartHook;
SHresult: Byte;
begin
hLib2 := LoadLibrary('HookLib.dll');
@StartHook1 := GetProcAddress(hLib2, 'StartHook');
if @StartHook1 = nil then Exit;
SHresult := StartHook1(Memo1.Handle, Handle);
if SHresult = 0 then ShowMessage('the Key Hook was Started, good');
if SHresult = 1 then ShowMessage('the Key Hook was already Started');
if SHresult = 2 then ShowMessage('the Key Hook can NOT be Started, bad');
if SHresult = 4 then ShowMessage('MemoHandle is incorrect');
end;

procedure TForm1.but_StopHookClick(Sender: TObject);
type
TStopHook = function: Boolean;
var
StopHook1: TStopHook;
hLib21: THandle;
begin
@StopHook1 := GetProcAddress(hLib2, 'StopHook');
if @StopHook1 = nil then
begin
ShowMessage('Stop Hook DLL Mem Addy not found');
Exit;
end;
if StopHook1 then
ShowMessage('Hook was stoped');
FreeLibrary(hLib2);
{for some reason in Win XP you need to call FreeLibrary twice
maybe because you get 2 functions from the DLL? ?}
FreeLibrary(hLib2);
end;
end.

Question:
What restrictions are there on the MSACCESS driver?

Answer:

BCD (binary coded decimal) support is not available.
Key violation tables cannot be created with DbiAddIndex.
(All other DbiAddIndex functionality is supported.)
QBE, heterogeneous queries, and queries using the local SQL
engine are not supported.

In the SDK, DbiDoRestructure and DbiRegenIndex are not
available.
Opening a table when TTable.Exclusive is set to True
prevents the user from opening that table again, even in
same session.

Question:
How is the UserName and Password passed to the remote
datamodule?


Answer:
On the RemoteDataModule, drop a TDatabase and add an
automation procedure (use Edit | Add To Interface) for
login. Make sure that the HandleShared property is True
on the TDatabase.

procedure Login(UserName, Password: WideString);
begin
{ DB = TDatabase }

{ Something unique between clients }
DB.DatabaseName := UserName + 'DB';
DB.Params.Values['USER NAME'] := UserName;
DB.Params.Values['PASSWORD'] := Password;
DB.Open;
end;

After you have created the automation method on the
RemoteDataModule (using Edit | Add To Interface), you can
call that method using;

RemoteServer1.AppServer.Login('USERNAME','PASSWORD');

Question:
Can I use the MSACCESS driver to create multi-threaded
applications?

Answer:
Yes and No. DAO 3.0 is not thread safe so all applications using
DAO (including Borland's MSACCESS driver) must access the
database through the main process' thread. The application can
still use threads as long as the threads do not do any database
operations with the MSACCESS driver.

Question:
How do I locate the application servers available in the
registry of the machine?

Answer:
Read the registry key under HKEY_CLASSES_ROOT\CLSID\* looking
for keys that have a subkey "Borland DataBroker". These
entries are application servers. Here's an example that
loads application server names to a Listbox.

procedure TForm1.FormCreate(Sender: TObject);
var

uses Registry;
I: integer;
TempList: TStringList;
begin
TempList := TStringList.Create;
try
with TRegistry.Create do
try
RootKey := HKEY_CLASSES_ROOT;
if OpenKey('CLSID', False) then
GetKeyNames(TempList);
CloseKey;
for I := 1 to TempList.Count - 1 do
if KeyExists('CLSID\' + TempList[I]
+ '\Borland DataBroker') then
begin
if OpenKey('CLSID\' + TempList[I] + '\ProgID', False)
then begin
Listbox1.Items.Add(ReadString(''));
CloseKey;
end;
end;
finally
Free;
end;
finally
TempList.Free;
end;
end;

Question:
What other software do I need to access Microsoft Access
databases and tables?

Answer:
You must have Microsoft's DAO version 3.0 drivers installed.
BDE 4.00 and 4.01 does not support DAO 3.5 (Access 97). If you
upgrade Access 95 to Access 97, DAO 3.0 still resides on your
machine, so the driver will function correctly. If you install

Access 97 with no prior version of Access 95, the driver will
not function.

Question:
Is it possible to close active application with another application?
How?

Answer:
Yes, it is very possible to do that. Here the source code.

Procedure CloseApp();
Begin
// this program use to close another application


// offcourse you need to lnow HInstance for application you want to close
interface
uses WinTypes;
procedure CloseAppFromInst(HInst: THandle);
implementation

uses WinProcs, Messages;

{ Callback function that has each top-level window passed to it. }
{ Return true to continue enumerating, false to stop. }

function EnumWindowsProc(Handle: HWND; Info: Pointer): boolean;
{$IFDEF WIN32} stdcall; {$ELSE} export; {$ENDIF}
begin
Result := TRUE; { continue enumeration }

{ Does this app have the same instance as what we are looking for? }

{$IFDEF WIN32}
if GetWindowLong(Handle, GWL_HINSTANCE) = LongInt(Info) then begin
{$ELSE}
if GetWindowWord(Handle, GWW_HINSTANCE) = LongInt(Info) then begin
{$ENDIF}
PostMessage(Handle, WM_CLOSE, 0, 0); { Close the app }
Result := FALSE; { stop enumerating windows, we are done. }
end;
end;


Question:
What is the difference between single and multiple instance
application servers in a multi-tier application?

Answer:
This can best be thought of from the point of view of the
application server and how many clients can it support.
One multi-instance server can support multiple clients.
A single instance server can only support one client.

Multi-instance servers create multiple data modules in one
instance of the server. Single instance servers are launched
for each client.

Question:
Is it possible to use alternate security databases other
than the one specified in the registry?

Answer:
With BDE 4.00, there is no setting for the security database;
you must tuse the default database. With BDE 4.01, a new
driver parameter "SYSTEM DATABASE" was added. It is located
on the MSACCESS driver page in the BDE Administrator tool.

Question:
What files and DLLs are necessary to run a server application on
the middle tier?


Answer:
See "Files and components for Borland MIDAS" at
"http://www.borland.com/midas/papers/components.html" Files and Components Paper


4/2/99 11:06:03 AM

Question:
"Can't delete or change record. Since related record exists in
table ='xxx', referential integrity rules would be violate"
error: What causes this error and how do I get around the
problem?

Answer:
The problem is that referential integrity is currently not
supported with the MSACCESS driver. Borland recognizes this as a
problem and is working on a solution. Currently, the only
workaround is to remove referential integrity from the MSACCESS
tables. You can see this behavior with Access 95 by changing the

RI value in the master table to the same value and trying to
post. Access 97 has fixed this problem.

7/15/98 3:23:06 PM

Question:
After using the right-click to create the provider function, how
can I re-execute the context menu option to "Export from Table"?


Answer:
Once you have exported a provider interface, the context menu
option is no longer visible. To re-display the context menu
option you must delete the associated property in the Type
Library Editor and press the Type Library Editors Refresh

button. You should also delete the "Get_XXX" entry in the
RemoteDataModule source.

7/16/98 4:31:28 PM

Question:
"Syntax error in query. Incomplete query clause" error:
I get this error when I run a query against a table with a
space in the table name. I have double quotes around the name
but it still does not work. What am I doing wrong?

Answer:
You need to change the double quotes " " to brackets [ ]
Example:

SELECT * FROM "MY TABLE NAME" needs to change to
SELECT * FROM [MY TABLE NAME]


7/15/98 3:23:06 PM

Question:
Do I need a form in the application server?

Answer:
Yes. It doesn't need to be visible, but you do need one.
To make the form not visible, set
Application.ShowMainForm := False in the project file.

Example project source:

begin
?Application.ShowMainForm := False;?
Application.Initialize;
Application.CreateForm(TForm1, Form1);
Application.Run;
end.

Question:
"General SQL Error -2147221164 Table: Alias: "
error: I get this error when I try and open a MSACCESS
database. What is the problem?

Answer:
This problem seems to be closely related to a DAO DLL versioning
problem. The easiest way to resolve this is to un-install Office
97 from Control Panel | Add/Remove Programs. There is information
related to this problem in Microsoft's knowledge base


http://www.microsoft.com/kb/articles/q141/2/94.htm

7/15/98 3:23:06 PM

CLICK TO REGISTER