Skip to Main Content
  • Questions
  • GetPrivateProfileString call from PLSQL

Breadcrumb

Question and Answer

Tom Kyte

Thanks for the question, Nguyen.

Asked: July 26, 2004 - 9:19 pm UTC

Last updated: September 04, 2009 - 3:53 pm UTC

Version: 8.1.7

Viewed 1000+ times

You Asked

Hi Tom,
I can't read text file in Unicode format, can you help me ?
I have problems when I read ini file (text unicode format).
In my program, I created a library :

create or replace library kernel32 as 'C:\Nist\lib\kernel32.dll';

and a function:
create or replace function pGetPrivateProfileString(p_section in varchar2,p_key in varchar2, p_default in varchar2, p_returnvalue out varchar2, p_size in number, p_FileName in varchar2) return number
as language c library kernel32 name "GetPrivateProfileString";

to read ini file.

In kernel32.dll, function GetPrivateProfileString has prototype:
DWORD GetPrivateProfileString(
LPCTSTR lpAppName,
LPCTSTR lpKeyName,
LPCTSTR lpDefault,
LPTSTR lpReturnedString,
DWORD nSize,
LPCTSTR lpFileName
);
But when I call my function, Oracle could not perform, and it gennerated errors:

declare
str_out varchar2(255);
n number;
begin
n := pGetPrivateProfileString('SAMPLE_LIST','NameOfSample',
'NameOfSample',str_out,255,
'C:\TEMP\mau chi ban\CutSampl.lst');
end;


ORA-06521: PL/SQL: Error mapping function
ORA-06522: Unable to load symbol from DLL.
ORA-06512: at Ā“TP2TP.pGetPrivateProfileStringĀ”, line 0
ORA-06512: at line 5
Can you help me to solve my problems?
thanks


and Tom said...

It can be very dangerous to call functions you did not write yourself. you have no control over the datatypes!

You want to use BINARY_INTEGER, not the Oracle Number type (very doubtful windows would be using an OCINumber :)

Also, the function is really GetPrivateProfileStringA <<=== A? why A? who knows....

Here is a full example:


tkyte@ORA8I> create or replace library kernel32 as 'C:\windows\system32\kernel32
.dll';
2 /

Library created.

tkyte@ORA8I>
tkyte@ORA8I> set echo on
tkyte@ORA8I>
tkyte@ORA8I>
tkyte@ORA8I> create or replace
2 function pGetPrivateProfileString
3 (p_section in varchar2,
4 p_key in varchar2,
5 p_default in varchar2,
6 p_returnvalue out varchar2,
7 p_size in BINARY_INTEGER,
8 p_FileName in varchar2)
9 return BINARY_INTEGER
10 as language c
11 library kernel32
12 name "GetPrivateProfileStringA";
13 /

Function created.

tkyte@ORA8I>
tkyte@ORA8I> declare
2 str_out varchar2(255);
3 n number;
4 begin
5 n := pGetPrivateProfileString
6 ('SAMPLE_LIST',
7 'NameOfSample',
8 'NameOfSampleDefault',
9 str_out,255,
10 'C:\TEMP\test.ini');
11 dbms_output.put_line( 'n = ' || n );
12 dbms_output.put_line( 'str_out = ' || str_out );
13 end;
14 /
n = 19
str_out = NameOfSampleDefault

PL/SQL procedure successfully completed.

tkyte@ORA8I>
tkyte@ORA8I> host echo [sample_list] > c:\temp\test.ini

tkyte@ORA8I> host echo NameOfSample = foobar >> c:\temp\test.ini

tkyte@ORA8I> /
n = 6
str_out = foobar

PL/SQL procedure successfully completed.

Rating

  (10 ratings)

Is this answer out of date? If it is, please let us know via a Comment

Comments

Who knows?

Oleksandr Alesinskyy, July 27, 2004 - 9:20 am UTC

>Also, the function is really GetPrivateProfileStringA <<=== A? why A? who
knows....

Because most of Windows functions that deal with strings have to versions - "A" for ANSI strings and "W" for Unicode (wide) strings. So GetPrivateProfileStringA has a counterpart GetPrivateProfileStringW. BTW, later one shall be used as Unicode file has to be read.

Tom Kyte
July 27, 2004 - 9:31 am UTC

there you go :)

thanks!

Nguyen Trung Viet, July 28, 2004 - 4:12 am UTC

Thanks!
my next question is which data type in oracle corresponds to DWORD type in C ?

Tom Kyte
July 28, 2004 - 8:16 am UTC

binary_integer -- i gave you the entire example?

Database OS

Arun Gupta, July 28, 2004 - 8:28 am UTC

Tom,
This is good. I never realized that a Windows dll function can be called from PL/SQL in this manner. I guess pointer operation won't be supported. Since the PL/SQL block would execute on the database side, I assume database has to be running on Windows. Is that right?
Thanks


Tom Kyte
July 28, 2004 - 12:50 pm UTC

the dll is invoked where the external procedure (extproc) is running -- which can actually be remote in 9i.

"pointers" are supported -- it is a pointer from the external procedure which is invoking the DLL.

Just a couple of comments.

Niall Litchfield, July 28, 2004 - 9:58 am UTC

It isn't just windows dlls that can be called this way. My understanding is that any platform that supports sharable C libraries can be used in this way.

In the particular example used here, reading a well structured text file from the OS it would seem to me that it would be easier just to refer to the text file as an external table.

A reader, July 28, 2004 - 4:06 pm UTC

it doesn't work with 9i (on win xp). metalink note 226739.1 explains as for 9i on windows platforms: "Oracle external procedure callouts do not support the _stdcall calling convention. Only the _cdecl convention is supported.".

does one have to write a "wrapper" in order to get it to work? but how to ...

Tom Kyte
July 28, 2004 - 7:44 pm UTC

a wrapper would 10000% be called for (i said as much)

"It can be very dangerous to call functions you did not write yourself. you have
no control over the datatypes!"


you write the wrapper in something that can do _cdecl, like C for example.


Would you mind to show us how to ...

A reader, August 29, 2004 - 5:02 am UTC

... code such a _stdcall2_cdecl-wrapper for your sample?

why did ORACLE stop supporting the interface it provided prior to 9i (the one you used)?

Tom Kyte
August 29, 2004 - 11:47 am UTC

what interface did we stop supporting?


but in anycase, I'm not a windows programmer at all - i was way back in the day but got a reprieve and went running back to unix, where C is normal.

so, not sure what you are asking for? there are examples shipped with the server software that should compile on your platform.

A reader, August 29, 2004 - 1:21 pm UTC

Hi Tom,
I am getting following errors

1 declare
2 str_out varchar2(255);
3 n number;
4 begin
5 n := pGetPrivateProfileString
6 ('SAMPLE_LIST',
7 'NameOfSample',
8 'NameOfSampleDefault',
9 str_out,255,
10 'C:\TEMP\test.ini');
11 dbms_output.put_line( 'n = ' || n );
12 dbms_output.put_line( 'str_out = ' || str_out );
13* end;
GAURANG@HARI >/
declare
*
ERROR at line 1:
ORA-28575: unable to open RPC connection to external procedure agent
ORA-06512: at "GAURANG.PGETPRIVATEPROFILESTRING", line 1
ORA-06512: at line 5

Tom Kyte
August 29, 2004 - 2:44 pm UTC

search for ora-28575 on this site, your listener and or tnsnames.ora configuration is not correct.

A reader, September 05, 2004 - 11:18 am UTC

Hi Tom,

getting following errors

GAURANG@HARI >declare
2 str_out varchar2(255);
3 n number;
4 begin
5 n := pGetPrivateProfileString
6 ('SAMPLE_LIST',
7 'NameOfSample',
8 'NameOfSampleDefault',
9 str_out,255,
10 'C:\TEMP\test.ini');
11 dbms_output.put_line( 'n = ' || n );
12 dbms_output.put_line( 'str_out = ' || str_out );
13 end;
14 /
declare
*
ERROR at line 1:
ORA-28595: Extproc agent : Invalid DLL Path
ORA-06512: at "GAURANG.PGETPRIVATEPROFILESTRING", line 1
ORA-06512: at line 5


My listener.ora
---------------
# listener.ora Network Configuration File: C:\oracle10g\network\admin\listener.ora
# Generated by Oracle configuration tools.

SID_LIST_LISTENER =
(SID_LIST =
(SID_DESC =
(SID_NAME = extproc)
(ORACLE_HOME = C:\oracle10g)
(PROGRAM = extproc)
)
)

LISTENER =
(DESCRIPTION_LIST =
(DESCRIPTION =
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = IPC)(KEY = EXTPROC))
)
(ADDRESS_LIST =
(ADDRESS = (PROTOCOL = TCP)(HOST = MAHARAJ)(PORT = 1521))
)
)
)


Tnanames.ora
==============
EXTPROC_CONNECTION_DATA.WORLD=
(DESCRIPTION=
(ADDRESS_LIST =
(ADDRESS=(PROTOCOL=IPC)(KEY=EXTPROC))
)
(CONNECT_DATA =
(SID=extproc)
(PRESENTATION=RO)
)
)


Thanks

Tom Kyte
September 05, 2004 - 12:23 pm UTC

[tkyte@tkyte-pc-isdn tkyte]$ oerr ora 28595
28595, 00000, "Extproc agent : Invalid DLL Path"
// *Cause: The path of DLL supplied for the extproc execution is invalid.
// *Action: Check if the DLL path is set properly using the EXTPROC_DLLS
// environment variable.
//



</code> http://www.oracle.com/pls/db92/db92.drilldown?remark=&word=EXTPROC_DLLS&book=&preference= <code>



Wrapper for reading Registry

PrazY, September 04, 2009 - 1:06 am UTC

Tom,

Is it possible to use the same wrapper for reading registry values using SP or Function?
Tom Kyte
September 04, 2009 - 3:53 pm UTC

you tell me, what is involved in reading the registry - I've shown *the approach*, you use your knowledge of

a) plsql
b) windows api calls

and you tell us?

rE: Reg Read

PrazY, September 06, 2009 - 12:53 am UTC

Sure Tom! had looked into kernel32.dll function but coudn't be able to find a function for accessing registry. Will try with advapi32.dll and let you know the result.

Just raised this question to know whether it is feasible or not :).

Thanks!

More to Explore

PL/SQL demos

Check out more PL/SQL tutorials on our LiveSQL tool.

PL/SQL docs

PL/SQL reference manual from the Oracle documentation library