By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
458,184 Members | 1,369 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 458,184 IT Pros & Developers. It's quick & easy.

StrPtr Question

P: n/a
dev
Hello,
How can the following code be converted to VB.Net? I am mostly interested
in how to handle the StrPtr calls in the function.

Private Declare Function PathRelativePathToW Lib "shlwapi.dll" _
(ByVal pszPath As Long, _
ByVal pszFrom As Long, _
ByVal dwAttrFrom As Long, _
ByVal pszTo As Long, _
ByVal dwAttrTo As Long) As Boolean

Public Function GetRelativePath(ByVal sFromDirectory As String, _
ByVal sToFile As String) As String

Dim sRelativePath As String
Dim bResult As Boolean

Const MAX_PATH As Long = 260

sRelativePath = Space(MAX_PATH)

' Set "Attr" to vbDirectory for directories and 0 for files
bResult = PathRelativePathToW(StrPtr(sRelativePath),
StrPtr(sFromDirectory), _
vbDirectory, StrPtr(sToFile), 0)

If bResult Then
GetRelativePath = Left(sRelativePath, InStr(sRelativePath,
Chr(0)) -1)
End If
End Function

TIA,
Steve
Nov 20 '05 #1
Share this Question
Share on Google+
16 Replies


P: n/a
Steve,
How can the following code be converted to VB.Net? I am mostly interested in how to handle the StrPtr calls in the function. StrPtr is no more! As it is no longer needed!

I would recommend something like:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal
pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Public Function GetRelativePath(ByVal sFromDirectory As String,
ByVal sToFile As String) As String
Const MAX_PATH As Integer = 260

Dim sRelativePath As New System.Text.StringBuilder(MAX_PATH)

Dim bResult As Boolean

' Set "Attr" to vbDirectory for directories and 0 for files
bResult = PathRelativePathTo(sRelativePath, sFromDirectory,
FileAttributes.Directory, sToFile, 0)

If bResult Then
Return sRelativePath.ToString()
Else
Return Nothing
End If
End Function

Passing the output string as a StringBuilder is safest as Strings themselves
are immutable. Just remember to initialize the capacity of the StringBuilder
to the maximum size of characters that may be returned.

Both String & Stringbuilder are correctly converted when defined in
parameters. String is good for input parameters, StringBuilder are good for
Output & Input/Output parameters.

Declaring dwAttrFrom & dwAttrTo as System.IO.FileAttributes simplifies the
usage of the parameters.

Declaring the function as Auto, ensures that the Unicode strings are
converted properly respective to the OS being run on. On NT based OS the
strings will stay Unicode & the W version of the function is called, on 95
based OS the strings will be converted to Ansi and the A version of the
function will be called!

BTW: Interesting function I needed it a few weeks ago! I'll have to file it
away in my grab bag of functions.

Hope this helps
Jay

"dev" <de****@nospam.com> wrote in message
news:ed**************@TK2MSFTNGP10.phx.gbl... Hello,
How can the following code be converted to VB.Net? I am mostly interested in how to handle the StrPtr calls in the function.

Private Declare Function PathRelativePathToW Lib "shlwapi.dll" _
(ByVal pszPath As Long, _
ByVal pszFrom As Long, _
ByVal dwAttrFrom As Long, _
ByVal pszTo As Long, _
ByVal dwAttrTo As Long) As Boolean

Public Function GetRelativePath(ByVal sFromDirectory As String, _
ByVal sToFile As String) As String

Dim sRelativePath As String
Dim bResult As Boolean

Const MAX_PATH As Long = 260

sRelativePath = Space(MAX_PATH)

' Set "Attr" to vbDirectory for directories and 0 for files
bResult = PathRelativePathToW(StrPtr(sRelativePath),
StrPtr(sFromDirectory), _
vbDirectory, StrPtr(sToFile), 0)

If bResult Then
GetRelativePath = Left(sRelativePath, InStr(sRelativePath,
Chr(0)) -1)
End If
End Function

TIA,
Steve

Nov 20 '05 #2

P: n/a
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
Passing the output string as a StringBuilder is safest as Strings themselves
are immutable. Just remember to initialize the capacity of the StringBuilder
to the maximum size of characters that may be returned.


When using VB.NET's 'Declare', it's not necessary to declare the
parameter as 'StringBuilder'. VB.NET will do the marshalling
automatically.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>
Nov 20 '05 #3

P: n/a
Herfried,
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete
Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.

Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP
gave requires a buffer passed in, to put the output string in. Passing a
System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified an
immutable object, which may lead to subtle runtime bugs elsewhere.

Based on the above book and other articles in MSDN Magazine on P/Invoke
using StringBuilder for output strings is the safest & easiest method to
use.

So although you can send in a System.String to an output parameter of an API
call, I would seriously not recommend it as you are running a high risk of
corrupting the runtime. Of course using any API call you are running a risk
of corrupting the runtime time, why elevate that risk?

Hope this helps
Jay

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:uw****************@TK2MSFTNGP11.phx.gbl...
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
Passing the output string as a StringBuilder is safest as Strings themselves are immutable. Just remember to initialize the capacity of the StringBuilder to the maximum size of characters that may be returned.


When using VB.NET's 'Declare', it's not necessary to declare the
parameter as 'StringBuilder'. VB.NET will do the marshalling
automatically.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>

Nov 20 '05 #4

P: n/a
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete
Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.

Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP
gave requires a buffer passed in, to put the output string in. Passing a
System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified an
immutable object, which may lead to subtle runtime bugs elsewhere.
ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.
Based on the above book and other articles in MSDN Magazine on P/Invoke
using StringBuilder for output strings is the safest & easiest method to
use.
When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare', VB.NET
will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en-us/cpref/html/frlrfSystemRuntimeInteropServicesUnmanagedTypeClas sTopic.asp>
So although you can send in a System.String to an output parameter of an API
call, I would seriously not recommend it as you are running a high risk of
corrupting the runtime. Of course using any API call you are running a risk
of corrupting the runtime time, why elevate that risk?


As mentioned above, I don't think that there is a risk in this case when
passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>
Nov 20 '05 #5

P: n/a
Herfried,
Interesting!

I missed the section in the book on the VBByRefStr, thanks for pointing
VBByRefStr out as it is a handy MarshalAs parameter to know!

Note: Adam's book states the following about
MarshalAs(UnmanagedType.VBByRefStr), after explaining how it works in VB.NET
& how to use it in C#:

"This is not recommended, however. Even in Visual Basic .NET,
you should use StringBuilder rather then String if backwards
compatibility with existing source code isn't important"

Then he follows that with:

"TIP: You should use StringBuider to represent a buffer in
Visual Basic .NET, just like you would in C#.
Using String types for this case is simply a second
option for backward compatibility."

I'm sure when I read the above section 6 months ago the above info is what
stuck with me, and VBByRefStr slipped away. ;-)

I'm not certain what "backward compatibility" he is referring to, I would
think VB6. I wish he would dig deeper into why it is not recommended! Maybe
I just have not got to that section of the book yet ;-)

Looking closer at Adam's book, he indicates that you should use the
InAttribute & OutAttribute (from System.Runtime.InteropServices) to help
minimize the amount of copying going on, as StringBuilder & String will
actually copy the buffer for the call, then copy the buffer back. I suspect
VBByRefStr is doing its own amount of copying...

I normally try to include InAttribute & OutAttribute in my Declares &
DllImports.
When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. I'll let you, now that I know its safe!

However! I will continue to recommend StringBuilder even with Declare. As to
me it is more obvious what is happening (strings are immutable) and it
allows converting back & forth from DllImport easier.
As mentioned above, I don't think that there is a risk in this case when
passing the string directly. In light of "MarshalAs(UnmanagedType.VBByRefStr)" I agree, there is no
greater risk then normal API calls.

Thanks for the info
Jay
"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl... * "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.
Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP
gave requires a buffer passed in, to put the output string in. Passing a
System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified an immutable object, which may lead to subtle runtime bugs elsewhere.
ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.
Based on the above book and other articles in MSDN Magazine on P/Invoke
using StringBuilder for output strings is the safest & easiest method to
use.


When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare', VB.NET
will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en...mRuntimeIntero
pServicesUnmanagedTypeClassTopic.asp>
So although you can send in a System.String to an output parameter of an API call, I would seriously not recommend it as you are running a high risk of corrupting the runtime. Of course using any API call you are running a risk of corrupting the runtime time, why elevate that risk?


As mentioned above, I don't think that there is a risk in this case when
passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>

Nov 20 '05 #6

P: n/a
dev
Thanks, I had Googled StrPtr and most of the answers stated the the way to
handle StrPtr in VB.Net was specific to how StrPtr was being used in the
original function., VB6 in this case.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.
Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP
gave requires a buffer passed in, to put the output string in. Passing a
System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified an immutable object, which may lead to subtle runtime bugs elsewhere.
ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.
Based on the above book and other articles in MSDN Magazine on P/Invoke
using StringBuilder for output strings is the safest & easiest method to
use.


When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare', VB.NET
will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en...mRuntimeIntero
pServicesUnmanagedTypeClassTopic.asp>
So although you can send in a System.String to an output parameter of an API call, I would seriously not recommend it as you are running a high risk of corrupting the runtime. Of course using any API call you are running a risk of corrupting the runtime time, why elevate that risk?


As mentioned above, I don't think that there is a risk in this case when
passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>

Nov 20 '05 #7

P: n/a
Dev,
Did you see my earlier post? I gave you a complete working example on how to
call the API. As StrPtr does not exist in VB.NET!

You need to use one of the following Declare statements:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal
pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal
pszPath As String, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

The second one maybe easier for VB6 developers to follow, however I prefer
the first one. Both should do the job equally well for you!

Hope this helps
Jay
"dev" <de****@nospam.com> wrote in message
news:uZ******************@TK2MSFTNGP11.phx.gbl...
Thanks, I had Googled StrPtr and most of the answers stated the the way to
handle StrPtr in VB.Net was specific to how StrPtr was being used in the
original function., VB6 in this case.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.
Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP gave requires a buffer passed in, to put the output string in. Passing a System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified
an
immutable object, which may lead to subtle runtime bugs elsewhere.
ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.
Based on the above book and other articles in MSDN Magazine on
P/Invoke using StringBuilder for output strings is the safest & easiest method to use.


When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare', VB.NET
will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en...mRuntimeIntero pServicesUnmanagedTypeClassTopic.asp>
So although you can send in a System.String to an output parameter of
an API call, I would seriously not recommend it as you are running a high
risk
of corrupting the runtime. Of course using any API call you are running a risk of corrupting the runtime time, why elevate that risk?


As mentioned above, I don't think that there is a risk in this case when
passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>


Nov 20 '05 #8

P: n/a
Cor
Hi Jay B.
That is the Jay B we know.
:-)
Cor

Nov 20 '05 #9

P: n/a
Herfried,
I believe I figured out why StringBuilder is recommended! ;-)

<MarshalAs(UnmanagedType.VBByRefStr)> can only be used with "InOut"
parameters, if you start adding InAttribute or OutAttribute to the declare
statement you need to give a MarshalAs with the 'regular' string types
<MarshalAs(UnmanagedType.LPTStr)> for example, other wise you get an
exception from the Marshaller

If you are not concerned with the InAttribute or OutAttribute then the
"default" behavior of VBByRefStr is reasonable for the Declare statement. As
it mimics what VB6 would do.

As I stated in my other post I normally include InAttribute & OutAttribute
on my Declare statements...

Hope this helps
Jay

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete Interoperability Guide" from SAMS press. Plus other MSDN Magazine articles.
Yes VB.NET will marshal the string correctly for you.

However! Remember that a System.String is immutable, the API that the OP
gave requires a buffer passed in, to put the output string in. Passing a
System.String for this buffer breaks the "immutable" intent of the
System.String class. So although it may appear to work you just modified an immutable object, which may lead to subtle runtime bugs elsewhere.
ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.
Based on the above book and other articles in MSDN Magazine on P/Invoke
using StringBuilder for output strings is the safest & easiest method to
use.


When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare', VB.NET
will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en...mRuntimeIntero
pServicesUnmanagedTypeClassTopic.asp>
So although you can send in a System.String to an output parameter of an API call, I would seriously not recommend it as you are running a high risk of corrupting the runtime. Of course using any API call you are running a risk of corrupting the runtime time, why elevate that risk?


As mentioned above, I don't think that there is a risk in this case when
passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>

Nov 20 '05 #10

P: n/a
dev
Yes, I saw it and I thank you for your example. My major point of interest
in my post was how to handle the non-existant StrPtr function in VB.Net. I
thought maybe there was another way to get a pointer to a string in VB.Net.
I am new to the VB.Net paradigm, but have programmed VB since VB3. I going
to try your example right now. Thanks again!

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:ut**************@TK2MSFTNGP11.phx.gbl...
Dev,
Did you see my earlier post? I gave you a complete working example on how to call the API. As StrPtr does not exist in VB.NET!

You need to use one of the following Declare statements:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal
pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal
pszPath As String, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

The second one maybe easier for VB6 developers to follow, however I prefer
the first one. Both should do the job equally well for you!

Hope this helps
Jay
"dev" <de****@nospam.com> wrote in message
news:uZ******************@TK2MSFTNGP11.phx.gbl...
Thanks, I had Googled StrPtr and most of the answers stated the the way to
handle StrPtr in VB.Net was specific to how StrPtr was being used in the
original function., VB6 in this case.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
> My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete
> Interoperability Guide" from SAMS press. Plus other MSDN Magazine

articles.
>
> Yes VB.NET will marshal the string correctly for you.
>
> However! Remember that a System.String is immutable, the API that the OP > gave requires a buffer passed in, to put the output string in.
Passing
a > System.String for this buffer breaks the "immutable" intent of the
> System.String class. So although it may appear to work you just modified
an
> immutable object, which may lead to subtle runtime bugs elsewhere.

ACK. But AFAIR it won't cause problems (except maybe performance
problems) when passing the string.

> Based on the above book and other articles in MSDN Magazine on P/Invoke > using StringBuilder for output strings is the safest & easiest
method
to > use.

When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way. When using VB.NET's 'Declare',
VB.NET will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>':

<http://msdn.microsoft.com/library/en...mRuntimeIntero pServicesUnmanagedTypeClassTopic.asp>

> So although you can send in a System.String to an output parameter of an
API
> call, I would seriously not recommend it as you are running a high risk
of
> corrupting the runtime. Of course using any API call you are running

a risk
> of corrupting the runtime time, why elevate that risk?

As mentioned above, I don't think that there is a risk in this case

when passing the string directly.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>



Nov 20 '05 #11

P: n/a
dev
The example works as required! Thanks.

"dev" <de****@nospam.com> wrote in message
news:OI*************@TK2MSFTNGP09.phx.gbl...
Yes, I saw it and I thank you for your example. My major point of interest in my post was how to handle the non-existant StrPtr function in VB.Net. I thought maybe there was another way to get a pointer to a string in VB.Net. I am new to the VB.Net paradigm, but have programmed VB since VB3. I going to try your example right now. Thanks again!

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:ut**************@TK2MSFTNGP11.phx.gbl...
Dev,
Did you see my earlier post? I gave you a complete working example on how
to
call the API. As StrPtr does not exist in VB.NET!

You need to use one of the following Declare statements:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal pszPath As String, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

The second one maybe easier for VB6 developers to follow, however I prefer the first one. Both should do the job equally well for you!

Hope this helps
Jay
"dev" <de****@nospam.com> wrote in message
news:uZ******************@TK2MSFTNGP11.phx.gbl...
Thanks, I had Googled StrPtr and most of the answers stated the the way
to handle StrPtr in VB.Net was specific to how StrPtr was being used in
the original function., VB6 in this case.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
> * "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
> > My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete
> > Interoperability Guide" from SAMS press. Plus other MSDN Magazine
articles.
> >
> > Yes VB.NET will marshal the string correctly for you.
> >
> > However! Remember that a System.String is immutable, the API that
the
OP
> > gave requires a buffer passed in, to put the output string in.

Passing
a
> > System.String for this buffer breaks the "immutable" intent of the
> > System.String class. So although it may appear to work you just

modified
an
> > immutable object, which may lead to subtle runtime bugs elsewhere.
>
> ACK. But AFAIR it won't cause problems (except maybe performance
> problems) when passing the string.
>
> > Based on the above book and other articles in MSDN Magazine on

P/Invoke
> > using StringBuilder for output strings is the safest & easiest

method
to
> > use.
>
> When using 'DllImport': Yes. When using 'Declare' it's not necessary > and IMHO not the "preferred" way. When using VB.NET's 'Declare',

VB.NET > will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)>': >
>

<http://msdn.microsoft.com/library/en...mRuntimeIntero
pServicesUnmanagedTypeClassTopic.asp>
>
> > So although you can send in a System.String to an output parameter of
an
API
> > call, I would seriously not recommend it as you are running a high

risk
of
> > corrupting the runtime. Of course using any API call you are

running a risk
> > of corrupting the runtime time, why elevate that risk?
>
> As mentioned above, I don't think that there is a risk in this case when > passing the string directly.
>
> --
> Herfried K. Wagner [MVP]
> <http://www.mvps.org/dotnet>



Nov 20 '05 #12

P: n/a
Dev,
Unfortunately that is on a case by case basis, as you stated.

In this case where you are passing the string to an API, you simply define
the API to accept a string, as I showed, and the Framework does all the work
for you. As Herfried & I discussed in our digression from your specific
question. VB.NET actually helps you a little over the normal framework
functions and allows you to use String for output parameters as well.

I have not really used StrPtr in VB6, so I don't know other what cases it is
used there. However if you give specific examples of StrPtr in VB6 I or
someone else will show you how to do the same thing in VB.NET. And as
Hefried & I have showed, there is probably more then one way to do it! ;-)

Hope this helps
Jay

"dev" <de****@nospam.com> wrote in message
news:OI*************@TK2MSFTNGP09.phx.gbl...
Yes, I saw it and I thank you for your example. My major point of interest in my post was how to handle the non-existant StrPtr function in VB.Net. I thought maybe there was another way to get a pointer to a string in VB.Net. I am new to the VB.Net paradigm, but have programmed VB since VB3. I going to try your example right now. Thanks again!

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:ut**************@TK2MSFTNGP11.phx.gbl...
Dev,
Did you see my earlier post? I gave you a complete working example on how
to
call the API. As StrPtr does not exist in VB.NET!

You need to use one of the following Declare statements:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal pszPath As String, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

The second one maybe easier for VB6 developers to follow, however I prefer the first one. Both should do the job equally well for you!

Hope this helps
Jay
"dev" <de****@nospam.com> wrote in message
news:uZ******************@TK2MSFTNGP11.phx.gbl...
Thanks, I had Googled StrPtr and most of the answers stated the the way
to handle StrPtr in VB.Net was specific to how StrPtr was being used in
the original function., VB6 in this case.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:ut***************@TK2MSFTNGP09.phx.gbl...
> * "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
> > My answer is based on what Adam Nathan wrote in ".NET and COM - The Complete
> > Interoperability Guide" from SAMS press. Plus other MSDN Magazine
articles.
> >
> > Yes VB.NET will marshal the string correctly for you.
> >
> > However! Remember that a System.String is immutable, the API that
the
OP
> > gave requires a buffer passed in, to put the output string in.

Passing
a
> > System.String for this buffer breaks the "immutable" intent of the
> > System.String class. So although it may appear to work you just

modified
an
> > immutable object, which may lead to subtle runtime bugs elsewhere.
>
> ACK. But AFAIR it won't cause problems (except maybe performance
> problems) when passing the string.
>
> > Based on the above book and other articles in MSDN Magazine on

P/Invoke
> > using StringBuilder for output strings is the safest & easiest

method
to
> > use.
>
> When using 'DllImport': Yes. When using 'Declare' it's not necessary > and IMHO not the "preferred" way. When using VB.NET's 'Declare',

VB.NET > will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)> ': >
>

<http://msdn.microsoft.com/library/en...mRuntimeIntero
pServicesUnmanagedTypeClassTopic.asp>
>
> > So although you can send in a System.String to an output parameter of
an
API
> > call, I would seriously not recommend it as you are running a high

risk
of
> > corrupting the runtime. Of course using any API call you are

running a risk
> > of corrupting the runtime time, why elevate that risk?
>
> As mentioned above, I don't think that there is a risk in this case when > passing the string directly.
>
> --
> Herfried K. Wagner [MVP]
> <http://www.mvps.org/dotnet>



Nov 20 '05 #13

P: n/a
* "dev" <de****@nospam.com> scripsit:
Thanks, I had Googled StrPtr and most of the answers stated the the way to
handle StrPtr in VB.Net was specific to how StrPtr was being used in the
original function., VB6 in this case.


Forget the 'StrPtr'.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>
Nov 20 '05 #14

P: n/a
Jay,

* "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit:
I missed the section in the book on the VBByRefStr, thanks for pointing
VBByRefStr out as it is a handy MarshalAs parameter to know!
;-)
Note: Adam's book states the following about
MarshalAs(UnmanagedType.VBByRefStr), after explaining how it works in VB.NET
& how to use it in C#:

"This is not recommended, however. Even in Visual Basic .NET,
you should use StringBuilder rather then String if backwards
compatibility with existing source code isn't important"
Interesting.
Then he follows that with:

"TIP: You should use StringBuider to represent a buffer in
Visual Basic .NET, just like you would in C#.
Using String types for this case is simply a second
option for backward compatibility."
Maybe 'Declare' shouldn't be used too because if's only a 2nd option for
backward compatibility? I don't think so. It's valid VB.NET syntax, if
it worked in VB6, why shouldn't VB.NET be able to cope with strings too?
I'm sure when I read the above section 6 months ago the above info is what
stuck with me, and VBByRefStr slipped away. ;-)

I'm not certain what "backward compatibility" he is referring to, I would
think VB6. I wish he would dig deeper into why it is not recommended! Maybe
I just have not got to that section of the book yet ;-)
Would be really interesting to know. If you find out why, please let
me/us know.
actually copy the buffer for the call, then copy the buffer back. I suspect
VBByRefStr is doing its own amount of copying...


ACK. That's what I suspect too.
When using 'DllImport': Yes. When using 'Declare' it's not necessary
and IMHO not the "preferred" way.


I'll let you, now that I know its safe!


I would use a 'StringBuilder' too, but I only wanted to note that
'String' "should" work too in this case.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>
Nov 20 '05 #15

P: n/a
dev
I never used any of the *Ptr functions in any version of VB since these
functions are undocumented and not guaranteed to be in the next version of
VB, as in the case of VB.Net. The only reason I asked in this case was
because I need to display a relative path to the user. The documentation I
found for PathRelativePathW included the StrPtr function for the call, which
I posted. So after Googling, I decided to ask as the opinion was the
translation from previous versions of VB to .Net was on a case by case
basis. I wanted ideas for this specific case, which were provided and I am
happy.

"Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message
news:bs************@ID-208219.news.uni-berlin.de...
* "dev" <de****@nospam.com> scripsit:
Thanks, I had Googled StrPtr and most of the answers stated the the way to handle StrPtr in VB.Net was specific to how StrPtr was being used in the
original function., VB6 in this case.


Forget the 'StrPtr'.

--
Herfried K. Wagner [MVP]
<http://www.mvps.org/dotnet>

Nov 20 '05 #16

P: n/a
dev
This was the only case I was interested in. If you ae interested, you can
Google Groups on 'StrPtr .Net +vb' and you will see the same posts I saw.
They included a hodgepodge of opinions, as always. Some used
GCHandle.Alloc and some other methods.

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:eD**************@TK2MSFTNGP09.phx.gbl...
Dev,
Unfortunately that is on a case by case basis, as you stated.

In this case where you are passing the string to an API, you simply define
the API to accept a string, as I showed, and the Framework does all the work for you. As Herfried & I discussed in our digression from your specific
question. VB.NET actually helps you a little over the normal framework
functions and allows you to use String for output parameters as well.

I have not really used StrPtr in VB6, so I don't know other what cases it is used there. However if you give specific examples of StrPtr in VB6 I or
someone else will show you how to do the same thing in VB.NET. And as
Hefried & I have showed, there is probably more then one way to do it! ;-)

Hope this helps
Jay

"dev" <de****@nospam.com> wrote in message
news:OI*************@TK2MSFTNGP09.phx.gbl...
Yes, I saw it and I thank you for your example. My major point of interest
in my post was how to handle the non-existant StrPtr function in VB.Net.

I
thought maybe there was another way to get a pointer to a string in

VB.Net.
I am new to the VB.Net paradigm, but have programmed VB since VB3. I

going
to try your example right now. Thanks again!

"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:ut**************@TK2MSFTNGP11.phx.gbl...
Dev,
Did you see my earlier post? I gave you a complete working example on how
to
call the API. As StrPtr does not exist in VB.NET!

You need to use one of the following Declare statements:

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll"

(ByVal pszPath As System.Text.StringBuilder, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

Declare Auto Function PathRelativePathTo Lib "shlwapi.dll" (ByVal pszPath As String, ByVal pszFrom As String, ByVal
dwAttrFrom As FileAttributes, ByVal pszTo As String, ByVal dwAttrTo As
FileAttributes) As Boolean

The second one maybe easier for VB6 developers to follow, however I prefer the first one. Both should do the job equally well for you!

Hope this helps
Jay
"dev" <de****@nospam.com> wrote in message
news:uZ******************@TK2MSFTNGP11.phx.gbl...
> Thanks, I had Googled StrPtr and most of the answers stated the the way
to
> handle StrPtr in VB.Net was specific to how StrPtr was being used in

the > original function., VB6 in this case.
>
> "Herfried K. Wagner [MVP]" <hi***************@gmx.at> wrote in message > news:ut***************@TK2MSFTNGP09.phx.gbl...
> > * "Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> scripsit: > > > My answer is based on what Adam Nathan wrote in ".NET and COM - The > Complete
> > > Interoperability Guide" from SAMS press. Plus other MSDN Magazine > articles.
> > >
> > > Yes VB.NET will marshal the string correctly for you.
> > >
> > > However! Remember that a System.String is immutable, the API that the
OP
> > > gave requires a buffer passed in, to put the output string in.

Passing
a
> > > System.String for this buffer breaks the "immutable" intent of
the > > > System.String class. So although it may appear to work you just
modified
> an
> > > immutable object, which may lead to subtle runtime bugs elsewhere. > >
> > ACK. But AFAIR it won't cause problems (except maybe performance
> > problems) when passing the string.
> >
> > > Based on the above book and other articles in MSDN Magazine on
P/Invoke
> > > using StringBuilder for output strings is the safest & easiest

method
to
> > > use.
> >
> > When using 'DllImport': Yes. When using 'Declare' it's not necessary > > and IMHO not the "preferred" way. When using VB.NET's 'Declare',

VB.NET
> > will automatically create the '<MarshalAs(UnmanagedType.VBByRefStr)> ':
> >
> >
>

<http://msdn.microsoft.com/library/en...mRuntimeIntero > pServicesUnmanagedTypeClassTopic.asp>
> >
> > > So although you can send in a System.String to an output parameter of
an
> API
> > > call, I would seriously not recommend it as you are running a
high risk
> of
> > > corrupting the runtime. Of course using any API call you are

running
a
> risk
> > > of corrupting the runtime time, why elevate that risk?
> >
> > As mentioned above, I don't think that there is a risk in this

case when
> > passing the string directly.
> >
> > --
> > Herfried K. Wagner [MVP]
> > <http://www.mvps.org/dotnet>
>
>



Nov 20 '05 #17

This discussion thread is closed

Replies have been disabled for this discussion.