Delphi XE Datasnap: Server methods missings when DSServerModule is load dynamically - delphi

I have Datasnap Server (DBX) that scans at startup a directory, loads the BPLs (containing the DSServerModules) and then registers them in order make them available from remote.
It all works fine for functions and procedures that use primitive types (such as integer, string and so on) but from client I cannot see any method that has "structured" variables.
For example I tried to add a function that returns a TJSONValue (as I saw on an example) but the method is not visible from client.
Strangely enough, the same function is available (and works) if the DSServerModule is added statically to the project).
Any Guess?
I didn't attach any code because it is part of a quite big project.
If need I'll provide a small example.
Cheers,
Mirko

Related

Intraweb - web application - users sessions

Today I started to write my first web application and I can't pass one step.
Everything works almost fine... I can connect to the server and open website. Problem is when I open browser and type the same address on the second pc, then I get te same data as on the first one.
Detailed...
Application has two forms, first is for login, and second one is for receiving data.
When I login on the first pc and second form shows up, and then I open browser and put the address of the server on the second pc, I see the second form after login from first pc.
What I should do in this case? I tried to find the solution in the net, but I couldn't :(
If you are using any Delphi IDE after XE3 (including) and using the IntraWeb edition that comes with Delphi you must upgrade in order to have it working correctly. It is free, and more information can be obtained here:
http://atozed.com/IntraWeb/Download/FreeKeyRequest.EN.aspx|
After upgrading (if this is your case) I suggest you to take a look at one of the IntraWeb demos, here:
https://iwdemos.codeplex.com/SourceControl/latest
There is a demo named Features that shows you exactly how to create a multi form application. To be honest, I work with IntraWeb for a long time and I've never seen that. Unless you are using some global var to hold your "current" active form. Have in mind that IntraWeb is a fully multithreaded application and global vars should not be used, unless you have some mechanism protecting concurrent access (but you should get rid of them and use ServerController properties instead).
Thnks for your quick reply.
I work with Delphi from some time, but I never used Intraweb, I worked with ComPort and IP works for I/O devices. I have XE7 and I upgraded Intraweb to 14.0.52.
I can't find a good file exchange server to put my application for sharing with you. If I find somethin I will post it below.
You can check the code and other settings of my simply project. I put the web application inside the link below, it is without the .exe file.
https://www.dropbox.com/s/75zurcew0zr363x/Project1.rar?dl=0
Thanks for your help.

How Do I Load Assemblies Only From Trusted Source using Ninject?

I have an ILog interface that has multiple implementations. One will be writing to a database, one on Windows Event Log, another on an xml file, some on text files for different vendors.
Implementations of this interface are dynamically loaded using Ninject. With the growing number and the recent news on hacks and malwares sleeping on some networks, I would like to know if there is a way to filter the assemblies to only the trusted ones?
We are trying to prevent someone from just creating their own implementation of our interfaces and dropping the dll into the bin folder then they get access to the flow of our information.
Please note that we load assemblies that follows the ILog interface.
It is rather useless to try preventing this. If piece of malware can already write to the application folder, all your attempts to 'filter out' illegal dlls will always fail. The attacker can for instance simply replace the .exe and will run in the context of the user and can do everything that your application can do.

Get the Description of a Service?

How may I get the description of a Windows Service like below?
I tried by using the Windows Registry, but the majority of Services appear to not have a description, or the description value is stored in a dll - so this seems to be the wrong approach.
Example:
Windows Time Service (W32Time), the description in the registry is shown as
#%SystemRoot%\system32\w32time.dll,-201
Yet the actual description as seen in Services.msc is:
Maintains date and time synchronization on all clients and servers in
the network. If this service is stopped, date and time synchronization
will be unavailable. If this service is disabled, any services that
explicitly depend on it will fail to start.
-
I have been searching on the MSDN website and came across this:
SERVICE_DESCRIPTION structure
lpDescription
The description of the service. If this member is NULL, the
description remains unchanged. If this value is an empty string (""),
the current description is deleted.
The service description must not exceed the size of a registry value
of type REG_SZ.
This member can specify a localized string using the following format:
#[path]dllname,-strID
The string with identifier strID is loaded from dllname; the path is
optional. For more information, see RegLoadMUIString....
-
pszOutBuf [out, optional]
A pointer to a buffer that receives the string.
Strings of the following form receive special handling:
#[path]\dllname,-strID
The string with identifier strID is loaded from dllname; the path is
optional. If the pszDirectory parameter is not NULL, the directory is
prepended to the path specified in the registry data. Note that
dllname can contain environment variables to be expanded.
Which I think would suggest why viewing the Registry showed the W32Time description as #%SystemRoot%\system32\w32time.dll,-201
If I understand correctly I need to read the dll name in memory and retrieve the strID where the Service description is stored?
This is all confusing for me, I would be grateful if someone could help.
All I need is to get the description of a Service, it surely cannot be as complicated as this can it?
Thanks :)
In all versions of Delphi, the the JEDI JCL contains everything you need to get friendly descriptions of services, and anything else to do with the Service Control APIs.
THe class TJclSCManager in the unit JclSvcCtrl.pas contains a property Services, which includes name and description of each service registered, and lets you also do things like start, stop, enable, and disable services too.
Update: The other answer here from ldsandon points out that the Delphi RTL apparently includes this already in XE2, in the unit WinSvc. See answer below about QueryServiceConfig2. Thanks ldsandon for pointing this fact out.
Call QueryServiceConfig2 (you will find also a C example there).
Whatever you need to do with services should be done through the Service Manager API. Registry data should be treated as "private" to the OS.
Using WMI is another way to use the Windows API directly, for example with the help of the (free) API code generator
WMI Delphi Code Creator
The WMI Delphi Code Creator tool allows you to generate Object Pascal
and C++ code to access the WMI (Windows Management Instrumentation)
classes, events and methods.
Are you using Unicode? The remarks for the RegLoadMUIString function say that only the Unicode version is supported.
The RegLoadMUIString function is supported only for Unicode. Although
both Unicode (W) and ANSI (A) versions of this function are declared,
the RegLoadMUIStringA function returns ERROR_CALL_NOT_IMPLEMENTED.
Applications should explicitly call RegLoadMUIStringW or specify
Unicode as the character set in platform invoke (PInvoke) calls.
Have you tried calling RegLoadMUIStringW directly?
You also can check the GLibWMI library. Free (and source included) library for work with WMI. Include a component named TServiceInfo.
Also is included a demo for work wirh services.
With this component you can access at Win32_Service Class; You can check the properties and structure here.
Regards

Auto-Detect Application "Type"

I build four different "types" of applications with my framework:
1) Windows Services
2) Normal Applications
3) Service Applications (a normal application with the functionality of a Windows Service but with a local GUI console and an ability to auto-upgrade)
4) Remote GUI Consoles
Now I can detect, through code, if the application is a Windows Service. But currently to detect between the others I use DEFINES that need to be added to the project file. I would like find an alternate way that does not rely on DEFINES if possible. My initial thoughts are to use the Comments field of the project's version info.
Any ideas?
Edit: I am after a general technique that works regardless of how I "type" my applications. At the moment I use DEFINES from the project configuration, which works, but makes the code slightly messier than using "if" code switches, and because it is stored in the .dproj file, can be hidden from view.
Solution: From David's suggestion I initially used the conditional defines (and any other information such as whether the application was running as a Windows Service) to map all applications to one of the 4 application types, stored in a globally accessible object. Unless linking files that made no sense to include with a particular application type, I replaced almost all of my conditional compilation flags with code, which significantly improved the readability of the code. There are a few other "tweaks" I implemented, but that was the basic implementation.
Depending how you are using the Application global variable you can detect if you application is a Service, a VCL or a console App checking the type of this global variable. for consoles app you can use the System.IsConsole variable.
function ApplicationIsService(Component:TComponent):Boolean;
begin
Result:=Component.ClassName='TServiceApplication';
end;
function ApplicationIsVcl(Component:TComponent):Boolean;
begin
Result:=Component.ClassName='TApplication';
end;
and you can use like this
if ApplicationIsVcl(Application) then
//do something
else
if ApplicationIsService(Application) then
//do something else
else
if IsConsole then
//do another thing
It sounds like each project has a single app type so it seems logical to differentiate in either the .dpr file or the .dproj files.
Call a function to set a private global variable from the .dpr file.
Or use a conditional defined in the .dproj as you do now.
If it was me I'd stick to a conditional but use the trick of converting it into a Delphi enum with a shared helper method to make it read better.

how to use DDE server

Can I get a little code example to use DDE as a server? I know how to use the client part, but can't figure setting up my app to act as a server and receive data.
Have a look in your Delphi installation for a folder called DDEDemo. It's a DDE project that Delphi use to ship with (I'm not 100% sure it's still included, but have a look). The demo includes a DDE client and server.
Edit - Try this link for some example code.
It is so easy to use the DDE server that you don't even need sample code. You can do it just at designtime inside the Delphi form designer:
To create a server that sends out data:
Drop a TDDEServerConv and
TDDEServerItem on your form or data
module.
Connect the server item to
the server conversation (set
DDEServerItem1.ServerConv=DdeServerConv1
using object inspector, there is a
drop down list, but double clicking
it is enough).
Set the DDEServerItem.Text value to some valid text value (ie 'A')
To receive data, you might want to have macros that are executed by the DDE client that pass data to the server. For this you use the DdeServerConv.OnExecuteMacro event. Try dumping the parameter Msg:TStrings to a memo like this:
Memo1.Lines.Assign(Msg);
Now save and run your project.
To test it in excel type in:
=Project1|DdeServerConv1!DdeServerItem1
The excel dde client syntax parts are Application name followed by vertical bar, conversation name, followed by exclamation mark, then item name.
And you will see the value (A, or whatever you put into the Text property in the item) appear in Excel.
That's a working single item DDE server without any code written by you.
I generally find that I create the conversations and the items at runtime, instead of at designtime, in a real world scenario that is more useful for me.
For older (non unicode) Delphi versions there is also a full featured commercial product called Django that helps a lot with DDE work.
I think also you might be looking for information on how to write a "DDE Poke" command handler on the delphi side. I don't have a demo for that. I tried it, and the obvious things didn' quite work right for me (the item on your server has an OnPoke event, I wrote a simple client, called PokeData, and it didn't work).

Resources