Still celebrating National IT Professionals Day with 3 months of free Premium Membership. Use Code ITDAY17

x
?
Solved

ExpandEnvironmentStringsForUser

Posted on 2004-09-09
18
Medium Priority
?
465 Views
Last Modified: 2010-04-05
Has anyone got an example of using this API in Delphi? I'm trying to convert a registry returned string into a full normal file path. But it contains env variables that need to be expanded. This API seems the best way, but I'm not sure how to write a function that I can pass this string to and get an expanded string back. Thanks
0
Comment
Question by:Narusegawa
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
  • 7
  • 5
  • 3
  • +1
18 Comments
 
LVL 12

Expert Comment

by:esoftbg
ID: 12017677
Can you give an example about that ?
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12017705
It seems a little bit unclear for me ....
0
 
LVL 12

Expert Comment

by:esoftbg
ID: 12017740
What is this API ? What is the registry returned string ? What is an expanded string ?
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Narusegawa
ID: 12017741
I found the API at  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/policy/policy/user_profiles_functions.asp

I have "%USERPROFILE%\My Documents\My Themes\Cursors\Premium 1.5\Premium_link.cur" as a string and I need this converting to a fully qualified file path. However for future and multi-user ease of use I will need to take into account any possible variables like %variable_name% that a user may have set up in there system.

The API, according to the document in the link, will convert these for me. However I have no idea how to do this. I've seen examples of other API called in Delphi but they are use DWord and PChars which I'm NOT very experienced with at all.
0
 
LVL 2

Accepted Solution

by:
gary_williams earned 1000 total points
ID: 12017785
type
  TBuffer = array[0..MAX_PATH] of Char;

function ExpandEnvironmentString(const S: String): String;
var
  Buffer: TBuffer;
begin
  ExpandEnvironmentStrings(PChar(S), Buffer, SizeOf(Buffer));
  Result := Buffer;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetEnvironmentVariable('A', 'Blah');
  ShowMessage(ExpandEnvironmentString('%A% %A%')); // BlahBlah
end;
0
 

Author Comment

by:Narusegawa
ID: 12017839
Perfect! That works a treat! Is that pretty much the same way to call other API functions in userenv.dll for example?

All this just to get around the hyperlink cursor not working properly in Windows XP! crHandPoint doesn't work. So had to get the cursor path from registry, then use this to expand it properly, then load it manually into a global variable to be used.
0
 
LVL 4

Expert Comment

by:Evarest
ID: 12017847
Gary has it, but it can be a bit shorted out :-)

procedure TForm1.Button1Click(Sender: TObject);
var
 Buffer: array[0..MAX_PATH] of Char;
begin
 ExpandEnvironmentStrings(PChar(Edit1.Text), Buffer, MAX_PATH);
 Edit2.Text :=Buffer;
end;

which essentially does the same. I don't know why gary_williams uses SetEnvironmentVariable though...

Evarest
0
 
LVL 4

Expert Comment

by:Evarest
ID: 12017874
My apologies: I created a "huge" memoryleak ;-)

Solution:

procedure TForm1.Button1Click(Sender: TObject);
var
 Buffer: array[0..MAX_PATH] of Char;
begin
 ExpandEnvironmentStrings(PChar(Edit1.Text), Buffer, MAX_PATH);
 Edit2.Text :=Buffer;
 Finalize(Buffer); // <-- changed
end;

Evarest
0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12017886
Other Windows API functions that require a buffer tend to be callable in the same way, however I believe there are some variations.
0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12017914
The poster asked for an example of how to write a function that called ExpandEnvironmentStrings, so I provided a "button click" procedure that demonstrated its us; I called SetEnvironmentVariable just to prove that it works.
0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12017959
The call to Finalize is not needed.
0
 

Author Comment

by:Narusegawa
ID: 12018039
What is the MAX_PATH thing for?

Thanks both of you! You solved a problem I was about to write a huge function to get around. I thought I was gonna have to parse for any %name% in the path and then check each one for a env variable and then strreplace each one.

Is there a document somewhere where you find all this API stuff? Preferably for the begginer/intermediate level. I been using Delphi for years but mostly it's database stuff not API/DLL.
0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12018084
MAX_PATH is a Windows constant representing the maximum length for any path on the system.  Generally I define TBuffer to be at least as long as this.  For simplicity, I use TBuffer in all functions that call API functions requiring a buffer for short-to-medium-length strings.
0
 
LVL 4

Expert Comment

by:Evarest
ID: 12018197
"The call to Finalize is not needed."

Oops, beg to differ :-)

Set the call in a TTimerOnTimer and set interval to 50 msec. Wait some seconds and see the RAM your program uses fill (however slowly)...

To Narusegawa:
You can find info on all API calls at msdn.microsoft.com or a more limited version in the helpfiles of Delphi: Start|Programs|...|Delphi7|Help|MS SDK Help Files|Win32 SDK Reference

NOTE: always depending on raw api can limit you application OS support.

Evarest

0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12018308
"Finalize" is documented to operate on "dynamically allocated variables".

A fixed-size array is not a dynamically allocated variable.

I would venture a guess this is not a true memory leak, but an artifact of how the memory use is being measured.
0
 
LVL 4

Expert Comment

by:Evarest
ID: 12018347
It seems you're correct... One needs to be able to admit one's mistakes :-)

Evarest
0
 
LVL 2

Expert Comment

by:gary_williams
ID: 12018448
I notice the memory usage tends to increase regardless of the presence or absense of the call to Finalize (when the function using the buffer is called from a short-period timer).  Who knows where that extra bloat is coming from.
0
 
LVL 4

Expert Comment

by:Evarest
ID: 12018470
It's sometimes just horrible... WMI is also an example of poor memorymanagement. You just can't use it in any timer or monitoring system, as i eats up your memory...

Evarest
0

Featured Post

How to Use the Help Bell

Need to boost the visibility of your question for solutions? Use the Experts Exchange Help Bell to confirm priority levels and contact subject-matter experts for question attention.  Check out this how-to article for more information.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Objective: - This article will help user in how to convert their numeric value become words. How to use 1. You can copy this code in your Unit as function 2. than you can perform your function by type this code The Code   (CODE) The Im…
Introduction Raise your hands if you were as upset with FireMonkey as I was when I discovered that there was no TListview.  I use TListView in almost all of my applications I've written, and I was not going to compromise by resorting to TStringGrid…
In this video, Percona Solution Engineer Dimitri Vanoverbeke discusses why you want to use at least three nodes in a database cluster. To discuss how Percona Consulting can help with your design and architecture needs for your database and infras…
In this video, Percona Solution Engineer Rick Golba discuss how (and why) you implement high availability in a database environment. To discuss how Percona Consulting can help with your design and architecture needs for your database and infrastr…
Suggested Courses

704 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question