Please help to view the sample

Y

yxq

Hello,
I want to get the string resource from DLL file, the code work well for
Vista x86, but it will not work on Vista x64, why? can anyone help to view
the code below? thank you very much.

//////////////////////////////////////////////////////////////////////////////////

Public Class GetResourceStringFromFile

Private Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" (ByVal lpLibFileName As String) As Integer
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As Integer, ByVal uID As Integer, ByVal lpBuffer As String,
ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal
hLibModule As Integer) As Integer

Public Shared Function GetResourceStringFromFile(ByVal sModule As
String, ByVal idString As Integer) As String
Dim hModule As Integer
Dim nChars As Integer
Dim Buffer As New
Microsoft.VisualBasic.Compatibility.VB6.FixedLengthString(260)
Dim ReturnValue As String = ""

Try
hModule = LoadLibrary(sModule)
If hModule Then
nChars = LoadString(hModule, idString, Buffer.Value,
260)
If nChars > 0 Then
ReturnValue =
Microsoft.VisualBasic.Left(Buffer.Value, nChars)
End If

FreeLibrary(hModule)
End If
Catch ex As Exception
End Try
Return ""
End Function

End Class
 
A

Armin Zingler

yxq said:
Hello,
I want to get the string resource from DLL file, the code work well
for Vista x86, but it will not work on Vista x64, why? can anyone
help to view the code below? thank you very much.

//////////////////////////////////////////////////////////////////////////////////

Public Class GetResourceStringFromFile

Private Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" (ByVal lpLibFileName As String) As Integer
Private Declare Function LoadString Lib "user32" Alias
"LoadStringA" (ByVal hInstance As Integer, ByVal uID As Integer,
ByVal lpBuffer As String, ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal
hLibModule As Integer) As Integer


Handles must be declared as IntPtr. IntPtr is plattform specific and
automatically the correct size, ie. 32 or 64 bit depending on the plattform.
Whereas Integer = Int32.

Watch the declarations:

HMODULE LoadLibrary(
LPCTSTR lpFileName
);


int LoadString( HINSTANCE hInstance,
UINT uID,
LPTSTR lpBuffer,
int nBufferMax
);

BOOL FreeLibrary(
HMODULE hModule
);



Type translation:

int -> IntPtr
UINT = unsigned int -> IntPtr
HMODULE = HINSTANCE = HANDLE = PVOID = void* -> IntPtr
BOOL = int -> IntPtr


Example:

Private Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" (ByVal lpLibFileName As String) As IntPtr



See also:
http://msdn2.microsoft.com/en-us/library/ms241064.aspx
http://msdn2.microsoft.com/en-us/library/8ck8e1y2.aspx


To the community: How is "As Boolean" treated? Shouldn't it be IntPtr? I've
always translated BOOL to Boolean, but this seems to be wrong.



Armin
 
A

Armin Zingler

Haven't looked at the rest of the code...

Also, use a Stringbuilder if you get a string back from an unmanaged [API]
function. Note that Strings are "immutable" in .Net. No need to use
VB6.FixedLengthString anyways.
See http://msdn2.microsoft.com/en-us/library/sd10k43k.aspx,
especially http://msdn2.microsoft.com/en-us/library/s9ts558h.aspx (head line
"Fixed-Length String Buffers").
(but don't rely on the declarations there...)
So, in LoadString, declare "ByVal lpBuffer As StringBuilder". Before calling
the function, fill the stringbuilder.

Also exchange the variable types in the function according to the types you
used in the Declares.


Armin
 
Y

yxq

Thank you for your help, but i have changed to the code below, it works well
on x86, but will not work on x64(only get a few dll's string), thank you.

/////////////////////////////////////////////////////////////////////////////////
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As Integer
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As String,
ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
Integer) As Integer

Public Function GetResourceStringFromFile(ByVal sModule As String, ByVal
idString As Integer) As String

Dim Buffer As String = Space(&H1000)
Dim hModule As Integer

Try
hModule = LoadLibrary(sModule)
If hModule Then
Dim n As Int32 = LoadString(hModule, idString, Buffer,
Buffer.Length)
If n > 0 Then
Return Left(Buffer, n)
End If
End If
Catch ex As Exception
End Try
Return ""
End Function
 
A

Armin Zingler

yxq said:
Thank you for your help, but i have changed to the code below, it works
well on x86, but will not work on x64(only get a few dll's string), thank
you.

/////////////////////////////////////////////////////////////////////////////////
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As Integer
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As
String, ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule
As Integer) As Integer


You should change not only some types. Correct them all. For example, the
return value of LoadLibrary must be Intptr. As I wrote, handles must be
Intptr.

I was wrong with the type translation table. Correction:

int -> Integer/Int32
UINT = unsigned int -> VB 2005: UInteger/UInt32, VB 2003: Integer/Int32
HMODULE = HINSTANCE = HANDLE = PVOID = void* -> IntPtr
BOOL -> Boolean


->

Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr

Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As
StringBuilder, ByVal nBufferMax As Integer) As Integer

Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule
As IntPtr) As Boolean


Armin
 
H

Herfried K. Wagner [MVP]

Armin Zingler said:
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr

Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As
StringBuilder, ByVal nBufferMax As Integer) As Integer

Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule
As IntPtr) As Boolean

.... and you can even get rid of the alias and declare the function as 'Auto'
('Declare Auto Function...').
 
A

Armin Zingler

Herfried K. Wagner said:
... and you can even get rid of the alias and declare the function
as 'Auto' ('Declare Auto Function...').


I didn't look at it at all. Had to find out whether "int" is Intptr or
Int32. :)


Armin
 
Y

yxq

Thank you, but i tried all your suggestions, but did not work yet.
If add the "Auto" to the API, it will not work on x64(include x86).
Modifid the Integer to Intptr, not effect.

Could you please help me to test on OS-64bit? i want to get the string in
Shell32.dll(ResID is -22985), it can return "Folder Options".
I used the code below. It work well on x86, but will not work on x64.

//////////////////////////////////////////////////////////////////////////
MessageBox.Show(GetResourceStringFromFile("C:\Windows\System32\shell32.dll",
22985))

Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As String,
ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
IntPtr) As Integer

Public Function GetResourceStringFromFile(ByVal sModule As String, ByVal
idString As Integer) As String

Dim Buffer As String = Space(&H1000)
Dim hModule As Integer

Try
hModule = LoadLibrary(sModule)
If hModule Then
Dim n As Int32 = LoadString(hModule, idString, Buffer,
Buffer.Length)
If n > 0 Then
Return Left(Buffer, n)
End If
End If
Catch ex As Exception
End Try
Return ""
End Function
 
A

Armin Zingler

yxq said:
Thank you, but i tried all your suggestions, but did not work yet.
If add the "Auto" to the API, it will not work on x64(include x86).
Modifid the Integer to Intptr, not effect.

Could you please help me to test on OS-64bit?

If you send me one?
i want to get the
string in Shell32.dll(ResID is -22985), it can return "Folder
Options".
I used the code below. It work well on x86, but will not work on
x64.

//////////////////////////////////////////////////////////////////////////
MessageBox.Show(GetResourceStringFromFile("C:\Windows\System32\shell32.dll",
22985))

Private Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" (ByVal lpLibFileName As String) As IntPtr
Private Declare Function LoadString Lib "user32" Alias
"LoadStringA" (ByVal hInstance As IntPtr, ByVal uID As UInteger,
ByVal lpBuffer As String, ByVal nBufferMax As Integer) As Integer


Still wrong declaration. Use a Stringbuilder for lpBuffer. See this thread
for explanation.


Armin
 
H

Herfried K. Wagner [MVP]

Armin,

Armin Zingler said:
Still wrong declaration. Use a Stringbuilder for lpBuffer. See this thread
for explanation.

Are you sure a 'StringBuilder' is really necessary here? IIRC when using
'Declare' (opposed to 'DllImport') the marshalling is performed
automatically.
 
T

Tom Shelton

Armin,



Are you sure a 'StringBuilder' is really necessary here? IIRC when using
'Declare' (opposed to 'DllImport') the marshalling is performed
automatically.

Yes it is marshalled automatically, and so isn't strictly necessary - but
recommended to reduce the amount of work that the VB marshaller has to do to
accomadate the immutable nature of System.String. In C# it is strictly
necessary, because the marshaller won't do the extra work. Personally, I
think it is just a good habbit to use System.Text.StringBuilder for non-const
buffers to p/invoke calls.
 
A

Armin Zingler

yxq said:
Sorry, i do not know how to use Stringbuilder, could you please give
me a full code?


C'mon, before doing such things you should read the documentation. That's
where I have the information from, too. I've never written a 64 bit
application, so what do you think I have done?

Main topic about interop:
http://msdn2.microsoft.com/en-us/library/ms172270.aspx

Among these chapters an example using a Stringbuilder:
http://msdn2.microsoft.com/en-us/library/x3txb6xc.aspx



Armin
 
A

Armin Zingler

Herfried K. Wagner said:
Armin,



Are you sure a 'StringBuilder' is really necessary here? IIRC when
using 'Declare' (opposed to 'DllImport') the marshalling is
performed
automatically.


That's new to me. I have always only heared (and read) that a Stringbuilder
_must_ be used because Strings are immutable - and preached it on my own all
the time without any opposition ever. Never heared of an exception. But you
may be right, I haven't tested it.


Armin
 
Y

yxq

Have modified the code below, but yet will not work on Vista-x64(most will
not work but a few work well).

/////////////////////////////////////////////////////////////////////
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As Integer
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As Integer, ByVal lpBuffer As
System.Text.StringBuilder, ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
Integer) As Integer

Public Function GetResourceStringFromFile(ByVal sModule As String, ByVal
idString As Integer) As String
Dim SB As New System.Text.StringBuilder(300)
Dim hModule As Integer

Try
hModule = LoadLibrary(sModule)
If hModule Then
Dim n As Integer = LoadString(hModule, idString, SB,
SB.Capacity)
If n > 0 Then
Return SB.ToString
End If
End If
Catch ex As Exception
End Try
Return ""
End Function
 
A

Armin Zingler

yxq said:
Have modified the code below, but yet will not work on
Vista-x64(most will not work but a few work well).

/////////////////////////////////////////////////////////////////////
Private Declare Function LoadLibrary Lib "kernel32" Alias
"LoadLibraryA" (ByVal lpLibFileName As String) As Integer


Hello? *knock* *knock* Why still Integer? :) You must change it as
suggested (more than once), otherwise it will definitely not work. Ok, once
again:


Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr

Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As
StringBuilder, ByVal nBufferMax As Integer) As Integer

Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule
As IntPtr) As Boolean



Armin
 
Y

yxq

Yes, have tested your code, but same result(work well on Vista-x86, will not
work on Vista-x64)

//////////////////////////////////////////////////////////////////////////////////////////////////
Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As
System.Text.StringBuilder, ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
IntPtr) As Boolean


Public Function GetResourceStringFromFile(ByVal sModule As String, ByVal
idString As Integer) As String
Dim SB As New System.Text.StringBuilder(300)
Dim hModule As Integer

Try
hModule = LoadLibrary(sModule)
If hModule Then
Dim n As Integer = LoadString(hModule, idString, SB,
SB.Capacity)
If n > 0 Then
Return SB.ToString
End If
End If
Catch ex As Exception
End Try
Return ""
End Function


Private Sub Button3_Click(ByVal sender As System.Object, ByVal e As
System.EventArgs) Handles Button3.Click
Dim a As String
For i As Integer = 0 To 5000
a = GetResourceStringFromFile("C:\windows\system32\shell32.dll",
i)
If a <> "" Then
l.Items.Add(i & " " & a)
End If
Next
MessageBox.Show("done")
End Sub
 
A

Armin Zingler

yxq said:
Yes, have tested your code, but same result(work well on Vista-x86,
will not work on Vista-x64)


First, you should always switch Option Strict On:


Public Function GetResourceStringFromFile( _
ByVal sModule As String, ByVal idString As UInteger) As String

Dim SB As New System.Text.StringBuilder(300)
Dim hModule As IntPtr

Try
hModule = LoadLibrary(sModule)
If hModule <> IntPtr.Zero Then
Dim n As Integer = LoadString(hModule, idString, SB, SB.Capacity)
If n > 0 Then
Return SB.ToString
End If
End If
Catch ex As Exception
End Try
Return ""
End Function


Though, I don't know what the problem is. Did you single-step through the
code? What is the value of hModule? If it's zero, what does
GetLastWin32Error return? What is n's value? Do you get an exception?


Armin
 
Y

yxq

Hello Armin Zingler,
Wow, the code work well on Vista64 now!!!! Thank you thank you very
much.....

//////////////////////////////////////////////////////////////////////////////
Option Strict On

Module Module1

Private Declare Function LoadLibrary Lib "kernel32" Alias "LoadLibraryA"
(ByVal lpLibFileName As String) As IntPtr
Private Declare Function LoadString Lib "user32" Alias "LoadStringA"
(ByVal hInstance As IntPtr, ByVal uID As UInteger, ByVal lpBuffer As
System.Text.StringBuilder, ByVal nBufferMax As Integer) As Integer
Private Declare Function FreeLibrary Lib "kernel32" (ByVal hLibModule As
IntPtr) As Boolean

Public Function GetResourceStringFromFile(ByVal sModule As String, ByVal
idString As UInteger) As String
Dim SB As New System.Text.StringBuilder(300)
Dim hModule As IntPtr

Try
hModule = LoadLibrary(sModule)
If hModule <> IntPtr.Zero Then
Dim n As Integer = LoadString(hModule, idString, SB,
SB.Capacity)
If n > 0 Then
Return SB.ToString
End If
End If
Catch ex As Exception
End Try
Return ""
End Function

End Module
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top