I use Delphi7 and I need to use some reports I have made before in SSRS 2008 within delphi.Actually I want to call them within Delphi. I have Used a WSDl importer and imported reportservice2005.asmx and delphi gave me a PAS file with list of SSRS methods but when I try to create an instance of ReportingService2010Soap with GetReportingService2010Soap Function gives me some errors!. Is there anywhere to find a Document for using this PAS file?
thank you and excuse my bad English!
The Delphi 7 WSDL Importer (wsdlimp.exe) has an update that can be downloaded from Embarcadero ID: 24535, Delphi SOAP Runtime and Importer Update
Here are 3 informative articles. Consuming ASMX web services in Delphi is pretty simple whether it's Delphi 7 or a more recent version.
1. Consuming C# Web Services with Delphi 7 Professional
2. Delphi 2010 and WCF Clients
3. Introduction to WCF Programming in Delphi
Apart from that, during development you can enclose your web service calls in a try except block like this
uses
SysUtils,
ABCService; // .pas unit generated by WSDLIMP.EXE (WSDL Importer)
procedure PerformServiceCall;
var
MyService: IMyService;
MyServiceResponse: TMyServiceResponse; // the result returned from the service call
MyServiceRequest: TMyServiceRequest; // the parameter passed with the service call
Connected: boolean;
begin
MyService := nil;
try
try
MyService := IMyService.GetMyService;
Connected := (MyService <> nil);
if Connected then
MyServiceResponse := MyService.MethodName(MyServiceRequest);
else
raise Exception.Create('Could Not Connect');
except
on E: Exception do
ShowMessage(E.ClassName + #13#10 + E.Message);
end;
finally
MyService := nil;
end;
end;
At this stage we investigate issues according to the ClassName and Message in the Exception raised, until we get no exceptions... then there are other things that we could check (like whether the service is actually up at the moment, addressing, timeouts, performance, security, etc.).
Related
I am trying to accept file uploads in a Delphi 7 Webbroker CGI.
I'm using Shiv Kumar's TMsMultipartParser, but I have a problem with Chrome. I can't access the parsed data (surprisingly, Explorer works fine).
This is my code:
with TMsMultipartFormParser.Create do
begin
Parse(Request);
lsExternalID:=ContentFields.Values['external_id'];
if (lsExternalID='') then
raise Exception.Create('No external ID');
for i := 0 to Files.Count -1 do
begin
lsFileName:=files[i].FileName;
//Rename file using external ID (not included for simplicity)
Files[i].SaveToFile(lsFilename);
end;
Response.Content := 'OK';
free;
end;
As suggested here, I tried to use http://www.mrsoft.org/Delphi/MultipartParser.pas but I can't compile it. It uses a unit called UniversalUtils that I can't find anywhere.
I know this is a very obsolete technology. Almost all references to it have already disappeared from the web (believe me, I have searched). Buy any help would be deeply appreciated.
Thanks.
I finally solved my problem, thanks to #mrabat.
This project started in Delphi 5. It was later upgraded to Delphi 7 (it can't be upgraded further, because many parts can't support Unicode strings, we use ANSI).
We were using Shiv's TMsMultipartParser because Delphi 5 didn't have any parser included.
Delphi 7 has TMultipartContentParser in unit ReqMulti.pas, and it works perfectly.
For anyone that need an example, I'll post my working code:
with TMultipartContentParser.Create(Request) do
begin
lsExternalID:=ContentFields.Values['external_id'];
if (lsExternalID='') then
raise Exception.Create('No external ID');
for i := 0 to Request.Files.Count -1 do
begin
lsFileName:=Request.Files[i].FileName;
//Rename file using external ID (not included for simplicity)
TMemoryStream(Request.Files[i].Stream).SaveToFile(lsFilename);
end;
Response.Content := 'OK';
Free;
end;
I wrote something similar once here:
https://github.com/stijnsanders/xxm/blob/master/Delphi/common/xxmParams.pas#L159
but that may be tightly coupled with SplitHeaderValue that parses the header lines, and TStreamNozzle that throttles incoming data. (and TXxmReqPar... objects, and IXxmContext...)
(Of course you're warmly welcomed to accept file uploads with xxm...)
I have a Windows service that restarts windows in specific events but i have a problem with it. I don't want to restart windows when it is installing programs using windows installer.
So how i can fine out whether Windows installer is busy installing something or not.
any Delphi or Command line Function is acceptable.
Will you please help me ?
I found these 2 classess but I don't know how to use them.
Class1 class2
Based on this article, which is quite outdated I've tried to implement both suggested options. The second one worked for me on Windows 7 SP1. The principle is to query the MSIServer service status and check, if this service is running and that accepts the SERVICE_ACCEPT_STOP control code. Here's a function wrapper for that:
uses
WinSvc;
function IsWindowsInstallerBusy: Boolean;
var
Service: SC_HANDLE;
ServiceMgr: SC_HANDLE;
ServiceStatus: SERVICE_STATUS;
begin
Result := False;
ServiceMgr := OpenSCManager(nil, nil, SC_MANAGER_CONNECT);
if ServiceMgr <> 0 then
try
Service := OpenService(ServiceMgr, 'MSIServer', SERVICE_QUERY_STATUS);
if Service <> 0 then
try
if QueryServiceStatus(Service, ServiceStatus) then
begin
Result := (ServiceStatus.dwCurrentState = SERVICE_RUNNING) and
((ServiceStatus.dwControlsAccepted and SERVICE_ACCEPT_STOP) = 0);
end
else
raise Exception.CreateFmt('Cannot query service status. Code: %d',
[GetLastError]);
finally
CloseServiceHandle(Service);
end
else
raise Exception.CreateFmt('Cannot open service. Code: %d',
[GetLastError]);
finally
CloseServiceHandle(ServiceMgr);
end
else
raise Exception.CreateFmt('Cannot connect to the service control ' +
'manager. Code: %d', [GetLastError]);
end;
Windows Installer provides a mutex to tell you if an installation is in process. I would use this over the SCManager API calls because it is thread safe. Heath Stewart (MSFT MSI Expert) wrote about it here and his advice should be given higher credibility then that of the Windows Installer team.
I'm just guessing here because you did not provide enough information...
(Some details about the goal and circumstances would have been nice.)
1) If you wish to restart the windows only when a specific installer is not running, you should enumerate running processes and if you find the installer you want to be aware of simply don't restart your system.
2) If you wish for a more generalised solution you still have a choice: The .msi typed installers are using msiexec.exe. If you wish to be aware of an installer of this type, you can search the list of the running processes for that.
Resources:
About process enumeration read the MSDN documentation on the topic.
About doing it from delphi read this tutorial
In Delphi 2009 I'm finding that any time I do perform both a connection to Oracle (via OCI.dll) and a call to a web service method I get an exception in ntdll.dll when closing my application in the IDE.
For the connection to Oracle I tried using both DOA (Direct Oracle Access) 4.1.1.0 and ODAC components (latest trial version);
For the web service method call (just a simple "function HelloWorld: string") I am using Delphi stock capabilities, after importing the WSDL from the web service.
If I use ODAC components in "direct" mode, that is not using OCI.dll, no exception occurs on closing.
If I call a web service method only (without connecting to Oracle), no exception occurs on closing (even if I use either DOA or ODAC components).
If I connect to Oracle (via OCI.dll) only (without calling a web service method), everything goes fine too (no matter if I use either DOA or ODAC components).
The very same code runs perfect when executed both in Delphi 7 and Delphi XE2: no exception occurs on application closing.
Some information:
Delphi 2009 (stock and Update 3 version)
OS: Windows 7 32 bit
Oracle Instant Client 10.2.0.4 and Oracle Instant Client 10.2.0.5
I start suspecting that it might be an issue related to heap corruption in Delphi 2009 on application closing...
Any help please?
Steps to reproduce (from the comment):
Create a new VCL Forms Application
Place a TOracleSession DOA component (named OracleSession1) on the Form
Place a TButton on the Form (named Button1)
Place this event handler for the button click event:
Here is the code:
procedure TForm1.Button1Click(Sender: TObject);
var
MyWebService3Soap: WebService3Soap;
s: string;
begin
OracleSession1.LogonDatabase := 'SomeLogonDB';
OracleSession1.LogonUsername := 'SomeUsername';
OracleSession1.LogonPassword := 'SomePassword';
OracleSession1.Connected := True;
ShowMessage('Connected');
MyWebService3Soap := GetWebService3Soap();
s := MyWebService3Soap.HelloWorld(); // Just returns a string such as "Hello World"
ShowMessage(s);
end;
The "WebService3Soap" interface is the one automatically generated by Delphi 2009 WSDL Importer. Here is the meaningful part:
WebService3Soap = interface(IInvokable)
['{F6F12FA6-3881-8BB5-AD71-2408B47692CD}']
function HelloWorld: string; stdcall;
end;
function GetWebService3Soap(UseWSDL: Boolean=System.False; Addr: string=''; HTTPRIO: THTTPRIO = nil): WebService3Soap;
initialization
InvRegistry.RegisterInterface(TypeInfo(WebService3Soap), 'http://mytest.it/Test3', 'utf-8');
InvRegistry.RegisterDefaultSOAPAction(TypeInfo(WebService3Soap), 'http://mytest.it/Test3/HelloWorld');
InvRegistry.RegisterInvokeOptions(TypeInfo(WebService3Soap), ioDocument);
end.
Run the application inside the IDE, press the button (close the 2 following ShowMessages) and then close the form.
Given the hint that it might be a "DLL hell" issue, I was able to run a test both on Windows XP and on Vista: everything went fine. So I started thinking that this issue had somehow to be related to Delphi 2009 on Windows 7.
I was right and I found that there is an issue In Delphi 2009 with debugging on Windows 7.
Fortunately a patch is available:
ID: 27476, Hotfix 2 for Delphi 2009 and C++Builder 2009
Applying the patch solved!
TADOConnection is failing to connect in the application initialization section of Delphi ISAPI App (TISAPIApplication):
Application is built with Delphi XE SPI, running Win 7 64/IIS 7.5 and WinServer 2008 RS2 - it cannot connect with ADO in the global ISAPI application context. (Example code is using MS-SQLServer OLEDB - but we also fail using Sybase ASE provider.)
The following code fails when conn.Open is called - TADOConnection.open never returns - ISAPI app hangs in la-la land, no exception raised:
library ISAPIBareBones;
uses
ActiveX,
ADODB,
(...)
var
conn: TADOConnection;
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
coinitialize(nil);
conn := TADOConnection.Create(Application);
conn.ConnectionString := 'Provider=SQLOLEDB.1;xxx';
//Fails here:
try
conn.Open;
except on e:exception do
logException(e)
end;
Application.WebModuleClass := WebModuleClass;
Application.Run;
end.
The same code within a specific request handler (Delphi webAction) runs fine.
We suspect a problem with execution privileges in IIS at the ISAPI application level. But as far as we can tell, the entire IIS application stack from the webServer itself down to the specific virtual directory and the ISAPI dll itself are all running under the same credentials with same execution privileges.
Meanwhile, my workaround has been to initialize the database infrastructure from within an http response call (an ISAPI thread), and then simply check that it's initialized on each subsequent call. This works, but encumbers me with some constraints that I'd prefer not to deal with.
How can I make ADO database connections in a TISAPIApplication instance, before handling incoming requests.
The begin ... end or an initialization part of a dll is the Delphi equivalent to dllmain in C++. So the same restrictions apply including:
Don't call CoInitialize
Don't call COM functions
This implies that you cannot create an ADO connection.
Do you know all the things that happen when you call TADOConnection.Create(Application);?
So what you're trying to do isn't going to work. And even if it did, you should not do it. Here's some better explanations:
http://msdn.microsoft.com/en-us/library/ms682583%28VS.85%29.aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/dn633971(v=vs.85).aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/01/27/63401.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2004/01/28/63880.aspx
http://blogs.msdn.com/b/oldnewthing/archive/2014/08/21/10551659.aspx
MSDN suggests creating the database connection in GetExtensionVersion. This is how your isapi dll is initialized. It is not just for reporting the extension version. So that is the way to go. Create your own GetExtensionVersion function that initializes your database and then call the previous Delphi function.
library Project1;
uses
Winapi.ActiveX,
System.Win.ComObj,
Web.WebBroker,
Web.Win.ISAPIApp,
Web.Win.ISAPIThreadPool,
Winapi.Isapi2,
Winapi.Windows,
WebModuleUnit1 in 'WebModuleUnit1.pas' {WebModule1: TWebModule};
{$R *.res}
function GetExtensionVersion(var Ver: THSE_VERSION_INFO): BOOL; stdcall;
begin
Result := Web.Win.ISAPIApp.GetExtensionVersion(Ver);
// create your ado connection here
end;
exports
GetExtensionVersion,
HttpExtensionProc,
TerminateExtension;
begin
CoInitFlags := COINIT_MULTITHREADED;
Application.Initialize;
Application.WebModuleClass := WebModuleClass;
Application.Run;
end.
I think the problem is that the code you run runs in the dll's main procedure. This part of the initialization is very restrictive e.g. you may not load any dll nor you are
allowed to call CoInitialize (see http://msdn.microsoft.com/en-us/library/ms678543%28v=vs.85%29.aspx) .
Your ActiveX alls there will cause some troubles which are most likely the reason for your
exception.
We currently use WmiSet from Online Admin to run Wmi Queries and query registry settings on remote machines.
The problem is that it only supports Delphi up to RAD Studio 2007.
We are currently in the process of upgrading to Delphi XE and need to know if anybody knows of — or has — a more recent version of the WmiSet components or anything similar.
We have tried to contact the vendor but so far there have not been any replies on any of our queries.
Pieter, some time ago i start a project called Delphi Wmi Class Generator this project creates full documented Object Pascal classes (compatible with delphi 7 to XE) to access the WMI.
check this code which uses the TWin32_BIOS class (created by the application) to access the
Win32_BIOS wmi class in a remote machine.
uses
SysUtils,
uWmiDelphiClass in '..\..\uWmiDelphiClass.pas',
uWin32_BIOS in '..\..\root_CIMV2\uWin32_BIOS.pas';
var
RemoteBiosInfo : TWin32_BIOS;
i : integer;
begin
try
RemoteBiosInfo:=TWin32_BIOS.Create(False);
try
RemoteBiosInfo.WmiServer:='192.168.217.128';
RemoteBiosInfo.WmiUser :='Administrator';
RemoteBiosInfo.WmiPass :='password';
RemoteBiosInfo.LoadWmiData;
if RemoteBiosInfo.WmiConnected then
begin
Writeln('Serial Number '+RemoteBiosInfo.SerialNumber);
Writeln('BuildNumber '+RemoteBiosInfo.BuildNumber);
if RemoteBiosInfo.BIOSVersion.Count>0 then
Writeln('Version '+RemoteBiosInfo.BIOSVersion[0]);
Writeln('Identification Code '+RemoteBiosInfo.IdentificationCode);
Writeln('Manufacturer '+RemoteBiosInfo.Manufacturer);
Writeln('SoftwareElementID '+RemoteBiosInfo.SoftwareElementID);
Writeln('Release Date '+DateToStr(RemoteBiosInfo.ReleaseDate));
Writeln('Install Date '+DateToStr(RemoteBiosInfo.InstallDate));
Writeln('Target S.O '+GetTargetOperatingSystemAsString(RemoteBiosInfo.TargetOperatingSystem));
Writeln('Soft. element state '+GetSoftwareElementStateAsString(RemoteBiosInfo.SoftwareElementState));
Writeln('');
Writeln('Bios Characteristics');
Writeln('--------------------');
for i:=Low(RemoteBiosInfo.BiosCharacteristics) to High(RemoteBiosInfo.BiosCharacteristics) do
Writeln(GetBiosCharacteristicsAsString(RemoteBiosInfo.BiosCharacteristics[i]));
end
else
Writeln('No connected');
finally
RemoteBiosInfo.Free;
end;
except
on E:Exception do
Writeln(E.Classname, ': ', E.Message);
end;
Readln;
end.
converting the WMISet library to Unicode Delphi is not too difficult. I've done the conversion to Delphi 2009 and 2010, and the compiler points you towards those lines of code that need changing. If I find the time I'll prepare a "diff" between the original code and the changed one for UniCode Delphi and upload it.
Regards,
Olaf