How can I determine the User that initiated one of my functions that I have created in my Server Methods Unit?
in the ServerContainerUnit or WebModuleUnit (ISAPI),
DSAuthenticationManager.onUserAuthenticate procedure or TDSServer.onConnect ect...,
use TDSSessionManager.GetThreadSession.PutData('UserName',User); identify current user to DSSession,
in your Servermethods unit functions, you can use TDSSessionManager.GetThreadSession.GetData('UserName')from the DSSession what you saved onUserAuthenticate or other procedure.
Tested on DataSnap REST ISAPI, work fine.
Just use TDSSessionManager.GetThreadSession.Username if you have authentication enabled.
Related
Is there a way of doing that? The list of registered classes is in the TRegGroups instance in Classes.pas unit, but problem is that instance is declared in the implementation section of unit. Is there a way of obtaining an address of RegisterClass procedure, or RegGroups.RegisterClass method?
Using KOLDetours.pas you can intercept calls to the method and then call the original method.
You can find it here: http://code.google.com/p/asmprofiler/source/browse/trunk/SRC/KOLDetours.pas
The file contains examples of how to use it.
To answer your specific question:
You may get the address of Classes.RegisterClass simply by using #Classes.RegisterClass as it is exposed in the interface section of Classes.pas.
The address TRegGroup.RegisterClass will be a bit tricky as it is not exposed in the interface section. Using the address of Classes.RegisterClass you could read the offset of TRegGroup.RegisterClass from the compiled code and then calculate the absolute address as a function of Classes.RegisterClass's address. Ultimately, this will be fragile across different version of the compiler.
As an alternative, if you are willing to make a small modification to each package, you could create a unit containing a function named RegisterClass and ensure that the unit is included in your registration unit before Classes.pas. Your unit would then link against your new RegisterClass function which could call some notification method before calling Classes.RegisterClass.
As you have indicated that you are statically linking to the packages, this is all somewhat moot because you will not have an opportunity to connect whatever notification routine you devise. To solve that issue you will want to dynamically load your packages after you have created your splash screen and are prepared to pump messages for it.
Alternatively, you could modify your package registration unit to use InitProc to delay registration until your TApplication instance is created. This would give you an opportunity to create some visual means of indicating registration progress before the registration actually take place.
In a comment you state:
I have 22 packages. Each package has (besides others) a unit with all the units in that package placed in interface section, and a procedure with simple RegisterClass(TSomeClass) for every class in that package.
In which case the answer is obvious. Define your own function, named MyRegisterClass for instance, and call that function instead.
I can use "Callbacks" between datasnap server and clients given as an example here by Pawel Glowacki.
But when I add DSAuthenticationManager1 on the server form with simple authentication then at the client sides I can not registered callbacks.
I get this error: "Exception class TDBXError with message 'Remote error: Authentication manager rejected user credentials. This may due to invalid combination of DS user name and password'."
I added login details to SQLConnection at the client like this:
SQLConnection1.Params.Values['DSAuthenticationUser'] := Username;
SQLConnection1.Params.Values['DSAuthenticationPassword'] := Password;
So my SQLConnection1 successfully connects to server. But I can not find any way for DSAuthenticationManager1.
How can I import login params to DSAuthenticationManager1?
The TDSClientCallbackChannelManager component in Delphi-XE does not include the same properties as in Delphi-XE2. When I add this component to my project (XE2), I have Username and Password properties, which are passed to the DataSnap server's DSAuthenticationManager.OnUserAuthenticate method whenever RegisterCallback() or UnregisterCallback() are called.
Do you have the latest XE update? If username and password aren't in the latest update, then you will likely need to upgrade to XE2 in order to use TDSAuthenticationManager in the DataSnap server and TDSClientCallbackChannelManager in the client.
I thought that perhaps you could create your own class from TSDClientCallbackChannelManager and override the methods that add the username and password to the DBXConnection -- thus giving you a way to add them yourself. I tried this, but the methods that need to be overridden are not virtual. I thought perhaps I could hide the ancestor methods by promoting methods with the same names in my new class as public, whereas they were protected in the ancestor class. It generated code and linked it into my client app (evident by the blue dots next to the new lines of code), but it wouldn't call my code at run-time. It always called the ancestor methods instead (DBXConnectionProperties and ExecuteRemote).
I think your only solution is to either update to XE2, or not use the authentication manager on the server.
After much searching, it looks like I have to assign RegisterComponentsProc and RegisterPropertyEditorProc, which I have done.
However, I thought that I could call my design time Register function, i.e. <myComponentUnit>.Register();.
When I do I get stack overflow, because, well ...
procedure myComponentUnit.Regiter;
begin
RegisterPropertyEditor(TypeInfo(Integer),
TMyComponent, 'myProperty', TMyProperty);
end;
procedure RegisterPropertyEditor(PropertyType: PTypeInfo;
ComponentClass: TClass; const PropertyName: string;
EditorClass: TPropertyEditorClass);
begin
if Assigned(RegisterPropertyEditorProc) then
RegisterPropertyEditorProc(PropertyType, ComponentClass, PropertyName,
EditorClass);
end;
So, I call .Register();
which calls RegisterPropertyEditor()
which call RegisterPropertyEditorProc()
which calls RegisterPropertyEditor() <=== aaargh!!
So, what should I have in the body of my RegisterPropertyEditorProc ?
After further searching, it looks like I want to call DesignEditors.RegisterPropertyEditor() directly, but it is not in the interface section ...
There is no point in trying to register a property editor at run-time, as it is not usable at run-time to begin with. It is only usable within the IDE during design-time.
Delphi does not include the source for the DesignEditors unit; its implementation is provided solely in the DesignIDE package. That package has access to IDE internals, such as the list of registered property editors. The IDE assigns values to the RegisterComponentsProc and RegisterPropertyEditorProc callback functions. As you noticed, RegisterPropertyEditor calls RegisterPropertyEditorProc. The IDE provides its own function to handle that event.
If you want to register a property editor at run time, then your program plays the role of the IDE. You need to provide implementations for those callback functions to register the property-editor classes with your own property-editing framework. You could probably just keep everything in a simple list. Then, when you want to know what kind of editor to display for a certain type of property, consult the list to find the best match.
You're correct that you should call your units' Register procedures. But that's how you initiate the registration process, not how you implement it. That part's up to you; Delphi doesn't provide any of this for you.
10 years have ellapsed since I used COM/OLE, and I forget 90% of them.
Now we need to make a COM object to access some data from PHP/Python (this is specific thing, the php ODBC don't access the output params of a DataBase - like stored proc output), and my idea the I realize a minimal object with one method, and PHP/Python can call this to get the output...
procedure ExecSQL(Config, IP, Port, DBName, SQL, IDFieldName : variant) : output
output is [IDValue, ErrorMsg, HResult]
Please help me a very little example, how to start it?
I need only this, but I'm confused by many ActiveX/COM in the palette.
What I need to use to make a simple COM DLL, and how to register my COM object with this DLL?
Thanks:
dd
Select File\New\ActiveX Library - this creates ActiveX DLL project
Select File\New\Automation Object - this creates the type library and implementation
Using the type library editor, add methods/properties to the interface
Write implementation code
Select Run\Register ActiveX Server - this registers the COM server DLL
For COM related applications in Delphi this link is usefull http://www.techvanguards.com/
I've been trying to get a soap server up that implements (is that the correct term?) a wsdl specification made by a third party. I have used Delphi's wsdl importer. (Part of) the generated code looks like this:
miniPortType = interface(IInvokable)
['{824D172A-9C1F-D202-5B21-4C324553BCF0}']
// Cannot unwrap:
// - Input element wrapper name does not match operation's name
function miniService(const aMessage: MiniMessageType): MiniAnswerType; stdcall;
end;
When called, the server says that "No method named 'MiniMessageType' is supported by interface 'miniPortType'".
I can only get this to work by making the name of the function and name of the main element of the message the same.
I think it should be possible to have different names. At least soapUI doesn't complain. And I actually have no choice but to implement the wsdl as is. Does anybody know how I can work around this?
I'm using Delphi 2007.
Thanks, Miel.
If I recall correctly, the SOAP interface is actually defined in a "table" at the bottom of the definitions, and it is this which is used to do the conversion between Delphi types and SOAP types in the communications. I've "corrected" this sort of thing in the past by manually changing the table building calls, but you have to be careful, and may also need to mangle the SOAP text at the appropriate point to make it all fit.