|
web
newsgroups
|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
Does String mashal default to UnmanagedType.LPTStrAnyway, I've been using the following and it works OK. Public Declare Auto Function SHGetFolderPath Lib "shell32.dll" (ByVal hWnd As Integer, _ ByVal nFolder As Integer, ByVal nToken As Integer, _ ByVal dwFlags As Integer, _ <MarshalAs(UnmanagedType.LPTStr)> ByVal lpszPath As String) As Boolean Tried this because I saw some place (not in the doc) that UnmanagedType.LPTStr was the default for String. This works too. Public Declare Auto Function SHGetFolderPath Lib "shell32.dll" (ByVal hWnd As Integer, _ ByVal nFolder As Integer, ByVal nToken As Integer, _ ByVal dwFlags As Integer, _ ByVal lpszPath As String) As Boolean Is that correct. I.e., in VB, String mashal defaults to UnmanagedType.LPTStr so UnmanagedType.LPTStr need not be included?? This is how it's used: Dim lPath As String = Space(260) If Library.Shell.SHGetFolderPath(0, k, 0, 0, lPath) = 0 Then lPath = lPath.Trim lPath = lPath.Substring(0, lPath.Length - 1) GetSpecialPath = lPath End If Finally, is that the correct way to do it or should I use StringBuilder. If it's not the correct way, why not? It appears to work OK. Thanks in advance On 2005-07-02, **Developer** <REMOVEdevelo***@a-znet.com> wrote:
> Been reading some of the Marshal doc and am a little confused. <snip>> > Anyway, I've been using the following and it works OK. > > For buffers populated by the called function, you really should use> Finally, is that the correct way to do it or should I use StringBuilder. > StringBuilder. > If it's not the correct way, why not? It appears to work OK. Here are a couple of reasons:1) Strings in .NET are immutable. By passing a type of string to the marshaller, you are causing it to do extra work. Basically, the marshaller, must copy data to a buffer, call the function, and then copy the buffer back to your string. When you use a StringBuilder, it just passes the buffer. You probably won't notice the performance hit unless your in a long loop or something... But, still why cause the marshaller to work harder then it needs to :) 2) This technique of using a string as a modifiable buffer will not work in other languages - for example C#. Not that you probably care, but if you have to do work in that language suddenly and try to declare the function the way you did, you might spend needless time debuggin why it didn't work. Of course, I have to ask... Do you really need this function? Have yous seen System.Environment.GetFolderPath? -- Tom Shelton [MVP] > If I didn't use that function I would not have needed to ask and would not > Of course, I have to ask... Do you really need this function? Have > yous seen System.Environment.GetFolderPath? > > -- > Tom Shelton [MVP] have the learned what you just told me. I like to try things since that often bring to the front good things to know. Thanks a lot Using StringBuilder do I need to set the Capacity or length or fill it with
anything before the call? Thanks again Show quoteHide quote "Tom Shelton" <tshel***@YOUKNOWTHEDRILLcomcast.net> wrote in message news:uFKfWdsfFHA.3124@TK2MSFTNGP12.phx.gbl... > On 2005-07-02, **Developer** <REMOVEdevelo***@a-znet.com> wrote: >> Been reading some of the Marshal doc and am a little confused. >> >> Anyway, I've been using the following and it works OK. >> > > <snip> > >> >> Finally, is that the correct way to do it or should I use StringBuilder. >> > > For buffers populated by the called function, you really should use > StringBuilder. > >> If it's not the correct way, why not? It appears to work OK. > > Here are a couple of reasons: > > 1) Strings in .NET are immutable. By passing a type of string to the > marshaller, you are causing it to do extra work. Basically, the > marshaller, must copy data to a buffer, call the function, and then copy > the buffer back to your string. When you use a StringBuilder, it just > passes the buffer. You probably won't notice the performance hit unless > your in a long loop or something... But, still why cause the marshaller > to work harder then it needs to :) > > 2) This technique of using a string as a modifiable buffer will not work > in other languages - for example C#. Not that you probably care, but if > you have to do work in that language suddenly and try to declare the > function the way you did, you might spend needless time debuggin why it > didn't work. > > Of course, I have to ask... Do you really need this function? Have > yous seen System.Environment.GetFolderPath? > > -- > Tom Shelton [MVP] This is what I've done and it appears to work:
Dim lPath As New System.Text.StringBuilder(Library.Kernel.MAX_PATH) 'Dim lPath As String = Space(260) If Library.Shell.SHGetFolderPath(0, k, 0, 0, lPath) = 0 Then Show quoteHide quote " **Developer**" <REMOVEdevelo***@a-znet.com> wrote in message news:ehRpyiwfFHA.1044@tk2msftngp13.phx.gbl... > > > Using StringBuilder do I need to set the Capacity or length or fill it > with anything before the call? > > > Thanks again > > "Tom Shelton" <tshel***@YOUKNOWTHEDRILLcomcast.net> wrote in message > news:uFKfWdsfFHA.3124@TK2MSFTNGP12.phx.gbl... >> On 2005-07-02, **Developer** <REMOVEdevelo***@a-znet.com> wrote: >>> Been reading some of the Marshal doc and am a little confused. >>> >>> Anyway, I've been using the following and it works OK. >>> >> >> <snip> >> >>> >>> Finally, is that the correct way to do it or should I use StringBuilder. >>> >> >> For buffers populated by the called function, you really should use >> StringBuilder. >> >>> If it's not the correct way, why not? It appears to work OK. >> >> Here are a couple of reasons: >> >> 1) Strings in .NET are immutable. By passing a type of string to the >> marshaller, you are causing it to do extra work. Basically, the >> marshaller, must copy data to a buffer, call the function, and then copy >> the buffer back to your string. When you use a StringBuilder, it just >> passes the buffer. You probably won't notice the performance hit unless >> your in a long loop or something... But, still why cause the marshaller >> to work harder then it needs to :) >> >> 2) This technique of using a string as a modifiable buffer will not work >> in other languages - for example C#. Not that you probably care, but if >> you have to do work in that language suddenly and try to declare the >> function the way you did, you might spend needless time debuggin why it >> didn't work. >> >> Of course, I have to ask... Do you really need this function? Have >> yous seen System.Environment.GetFolderPath? >> >> -- >> Tom Shelton [MVP] > > **Developer**
In addition to the other comments, the default for VB.NET is UnmanagedType.VBByRefStr, which allows the string itself (which is immutable) to be modified by the API call. This allows consistency with VB6 and "simplifies" things. However as Tom suggests, I normally use StringBuilder, as StringBuilder is mutable, while String is immutable. Also <MarshalAs(UnmanagedType.VBByRefStr)> can only be used with "InOut" parameters, if you start adding InAttribute or OutAttribute to the declare statement parameters 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. I normally include InAttribute & OutAttribute on my Declare statements... Hope this helps Jay Show quoteHide quote " **Developer**" <REMOVEdevelo***@a-znet.com> wrote in message news:OYPDGhqfFHA.3316@TK2MSFTNGP14.phx.gbl... | Been reading some of the Marshal doc and am a little confused. | | Anyway, I've been using the following and it works OK. | | Public Declare Auto Function SHGetFolderPath Lib "shell32.dll" (ByVal hWnd | As Integer, _ | | ByVal nFolder As Integer, ByVal nToken As Integer, _ | | ByVal dwFlags As Integer, _ | | <MarshalAs(UnmanagedType.LPTStr)> ByVal lpszPath As String) As Boolean | | | | Tried this because I saw some place (not in the doc) that | UnmanagedType.LPTStr was the default for String. This works too. | | Public Declare Auto Function SHGetFolderPath Lib "shell32.dll" (ByVal hWnd | As Integer, _ | | ByVal nFolder As Integer, ByVal nToken As Integer, _ | | ByVal dwFlags As Integer, _ | | ByVal lpszPath As String) As Boolean | | Is that correct. I.e., in VB, String mashal defaults to | UnmanagedType.LPTStr so UnmanagedType.LPTStr need not be included?? | | | | This is how it's used: | | Dim lPath As String = Space(260) | | If Library.Shell.SHGetFolderPath(0, k, 0, 0, lPath) = 0 Then | | lPath = lPath.Trim | | lPath = lPath.Substring(0, lPath.Length - 1) | | GetSpecialPath = lPath | | End If | | | | Finally, is that the correct way to do it or should I use StringBuilder. | | If it's not the correct way, why not? It appears to work OK. | | | | Thanks in advance | | | | | | > <MarshalAs(UnmanagedType.VBByRefStr)> can only be used with "InOut" Can't follow this. Seems to say VBByRefStr requires InOut.> parameters, if you start adding InAttribute or OutAttribute to the declare > statement parameters 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. > Then says In or Out requires LPTStr or something similar. What am I reading wrong? Thanks **Developer**,
| Can't follow this. Seems to say VBByRefStr requires InOut. That is exactly what I stated: VBByRefStr requires (can only be used for) InOut parameters. InOut parameters are parameters that do not have an InAttribute or an OutAttribute attached to them. InOut parameters are parameters that are marshaled to the unmanaged world & then marshaled back to the .NET world. In parameters only need to be marshaled to the unmanaged world (they are values that go into the API, are not returned.). They have the System.Runtime.InteropServices.InAttribute attached to them. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeInteropServicesInAttributeClassTopic.asp Out parameters only need to be marshaled to the .NET world (they are values that are returned from an API). They have the System.Runtime.InteropServices.OutAttribute attached to them. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/cpref/html/frlrfSystemRuntimeInteropServicesOutAttributeClassTopic.asp If you read the Win32 API itself, the description of the parameters indicate if they are In, Out, or InOut. http://msdn.microsoft.com/library/default.asp?url=/library/en-us/shellcc/platform/shell/reference/functions/shgetfolderpath.asp | Then says In or Out requires LPTStr or something similar. Correct, as VB will attempt to put VBByRefStr if you don't include LPTStr. VBByRefStr with InAttribute or OutAttribute is incompatible. InAttribute & OutAttribute allow you to "optimize" the API call as they allow you to indicate that a parameter only needs to be marshaled in a single direction, allowing the API itself to be quicker. In the case of SHGetFolderPath , the lpszPath is used to return a String, it should (*should*) have the OutAttribute on it as it is a return value. OutAttribute means you need StringBuilder as String with LPTStr is immutable. For an example of declaring the API see: http://www.pinvoke.net/default.aspx/shell32/SHGetFolderPath.html Using the Declare syntax: Private Declare Auto Function SHGetFolderPath Lib "shell32.dll" ( _ ByVal hwndOwner As IntPtr, _ ByVal nFolder As Int32, _ ByVal hToken As IntPtr, _ ByVal dwFlags As Int32, _ <Out()> ByVal pszPath As StringBuilder _ ) As Int32 InAttribute is implicit on ByVal value types. String & StringBuiler are reference types so you need to state if they are In only or Out only, otherwise InOut is assumed. I find both the www.pinvoke.net web site & Adam Nathan's book ".NET and COM - The Complete Interoperability Guide" from SAMS press to be invaluable when using Declare statements & P/Invoke. Hope this helps Jay Hope this helps Jay Show quoteHide quote " **Developer**" <REMOVEdevelo***@a-znet.com> wrote in message news:%23HrTOiOgFHA.3788@tk2msftngp13.phx.gbl... | | > <MarshalAs(UnmanagedType.VBByRefStr)> can only be used with "InOut" | > parameters, if you start adding InAttribute or OutAttribute to the declare | > statement parameters 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. | > | Can't follow this. Seems to say VBByRefStr requires InOut. | Then says In or Out requires LPTStr or something similar. | | What am I reading wrong? | | | | Thanks | |
(newbie warning) vb.net, stdregprov, deletekey - Invalid cast
Loop thru all subfolders and list all files under each Two quick Questions Transparent Color in an Icon questions about VB.NET, and uses in education Is there code to convert a c# module to VB? Need a Strategy to store the Single Quotes in the Database Error: Cast From String to type Integer not valid Loading two separate instance of the same assembly score object property values against a decision rule created from from database table record values |
|||||||||||||||||||||||