[lnkForumImage]
TotalShareware - Download Free Software

Confronta i prezzi di migliaia di prodotti.
Asp Forum
 Home | Login | Register | Search 


 

Kevin Provance

3/7/2011 7:20:00 AM

I've stumbled across an area I've not worked with. I have an API that
requires, according to the C documentation a LPCWSTR (wide string?)

I'm going to guess the everyday regular ANSI string won't cut it (and after
attempting to use it with the API and getting the "The system could not find
the environment option that was entered" LastDLLError that this might be the
case.

Would MultiByteToWideChar accomplish turning my string into what I need it
to be?


15 Answers

Tom Shelton

3/7/2011 8:45:00 AM

0

Kevin Provance was thinking very hard :
> I've stumbled across an area I've not worked with. I have an API that
> requires, according to the C documentation a LPCWSTR (wide string?)
>
> I'm going to guess the everyday regular ANSI string won't cut it (and after
> attempting to use it with the API and getting the "The system could not find
> the environment option that was entered" LastDLLError that this might be the
> case.
>
> Would MultiByteToWideChar accomplish turning my string into what I need it to
> be?

Generally, when calling these sort of api's from VB, you can declare
the parameter as long and then user StrPtr to get the buffer address or
you can pass them as an array of bytes.

The other option, is of course to wrap the api call in a typelib, then
you can pass it as a string directly.

Is this a windows api? Or is it part of a 3rd party?

--
Tom Shelton


(nobody)

3/7/2011 11:11:00 AM

0

"Kevin Provance" <kcp@pck.ooo> wrote in message
news:il20uo$dpk$1@news.eternal-september.org...
> I've stumbled across an area I've not worked with. I have an API that
> requires, according to the C documentation a LPCWSTR (wide string?)
>
> I'm going to guess the everyday regular ANSI string won't cut it (and
> after attempting to use it with the API and getting the "The system could
> not find the environment option that was entered" LastDLLError that this
> might be the case.
>
> Would MultiByteToWideChar accomplish turning my string into what I need it
> to be?

The W in LPCWSTR means that the parameter is always in Unicode. You declare
it in VB as "ByVal s As Long", and here are various ways to call it:

StrPtr(s)
ByVal StrPtr(s)
StrPtr("Hello")
ByVal StrPtr("Hello")

There is no need to convert the string because it's already in Unicode. If
you have already tried the above, then the problem maybe elsewhere. It would
be helpful if you post the declaration.


Kevin Provance

3/7/2011 8:55:00 PM

0


"Nobody" <nobody@nobody.com> wrote in message
news:il2eg3$tur$1@speranza.aioe.org...
>
> The W in LPCWSTR means that the parameter is always in Unicode. You
> declare it in VB as "ByVal s As Long", and here are various ways to call
> it:
>
> StrPtr(s)
> ByVal StrPtr(s)
> StrPtr("Hello")
> ByVal StrPtr("Hello")
>
> There is no need to convert the string because it's already in Unicode. If
> you have already tried the above, then the problem maybe elsewhere. It
> would be helpful if you post the declaration.

From mscoree.h

HRESULT GetRequestedRuntimeInfo (
[in] LPCWSTR pExe,
[in] LPCWSTR pwszVersion,
[in] LPCWSTR pConfigurationFile,
[in] DWORD startupFlags,
[in] DWORD runtimeInfoFlags,
[out] LPWSTR pDirectory,
[in] DWORD dwDirectory,
[out] DWORD *dwDirectoryLength,
[out] LPWSTR pVersion,
[in] DWORD cchBuffer,
[out] DWORD *dwlength
);

I haven't had time to try the StrPtr stuff out today as work intrudes. This
is just hobbyist stuff I was playing with.


(nobody)

3/7/2011 10:42:00 PM

0

"Kevin Provance" <kcp@pck.ooo> wrote in message
news:il3gm9$4t3$1@news.eternal-september.org...
>
> "Nobody" <nobody@nobody.com> wrote in message
> news:il2eg3$tur$1@speranza.aioe.org...
>>
>> The W in LPCWSTR means that the parameter is always in Unicode. You
>> declare it in VB as "ByVal s As Long", and here are various ways to call
>> it:
>>
>> StrPtr(s)
>> ByVal StrPtr(s)
>> StrPtr("Hello")
>> ByVal StrPtr("Hello")
>>
>> There is no need to convert the string because it's already in Unicode.
>> If you have already tried the above, then the problem maybe elsewhere. It
>> would be helpful if you post the declaration.
>
> From mscoree.h
>
> HRESULT GetRequestedRuntimeInfo (
> [in] LPCWSTR pExe,
> [in] LPCWSTR pwszVersion,
> [in] LPCWSTR pConfigurationFile,
> [in] DWORD startupFlags,
> [in] DWORD runtimeInfoFlags,
> [out] LPWSTR pDirectory,
> [in] DWORD dwDirectory,
> [out] DWORD *dwDirectoryLength,
> [out] LPWSTR pVersion,
> [in] DWORD cchBuffer,
> [out] DWORD *dwlength
> );
>
> I haven't had time to try the StrPtr stuff out today as work intrudes.
> This is just hobbyist stuff I was playing with.

That function is deprecated according to MSDN:

http://msdn.microsoft.com/en-us/library/ms2...

The remarks section shows it's not reliable to get the latest version
information. The recommended way is through the registry. See the second
table in this article titled "Recommended Deployment Detection":

http://support.microsoft.com...

Anyway, here is a sample that shows how to use this function, and the output
on my machine:

Output on XP+SP2(not a clean install, has at least 3.5 installed):

ret = 0, LastDllError = 203
pDirectory = C:\WINDOWS\Microsoft.NET\FrameworkpVersion = v2.0.50727
dwDirectoryLength = 36
dwlength = 11

Note 1: When a function returns success, LastDllError is "don't care". Some
API function set the default to failure code, then don't bother to reset it
on success.
Note 2: I got the same info when running in the IDE or the EXE.
Note 3: I am not sure how to fill startupFlags parameter, so I left it at 0.

Sample code:

Option Explicit

Private Enum STARTUP_FLAGS
STARTUP_CONCURRENT_GC = &H1
STARTUP_LOADER_OPTIMIZATION_MASK = &H6
STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN = &H2
STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN = &H4
STARTUP_LOADER_OPTIMIZATION_MULTI_DOMAIN_HOST = &H6

STARTUP_LOADER_SAFEMODE = &H10
STARTUP_LOADER_SETPREFERENCE = &H100

STARTUP_SERVER_GC = &H1000
STARTUP_HOARD_GC_VM = &H2000

STARTUP_SINGLE_VERSION_HOSTING_INTERFACE = &H4000
STARTUP_LEGACY_IMPERSONATION = &H10000
STARTUP_DISABLE_COMMITTHREADSTACK = &H20000
STARTUP_ALWAYSFLOW_IMPERSONATION = &H40000
STARTUP_TRIM_GC_COMMIT = &H80000
STARTUP_ETW = &H100000
STARTUP_ARM = &H400000
End Enum

Private Enum RUNTIME_INFO_FLAGS
RUNTIME_INFO_UPGRADE_VERSION = &H1
RUNTIME_INFO_REQUEST_IA64 = &H2
RUNTIME_INFO_REQUEST_AMD64 = &H4
RUNTIME_INFO_REQUEST_X86 = &H8
RUNTIME_INFO_DONT_RETURN_DIRECTORY = &H10
RUNTIME_INFO_DONT_RETURN_VERSION = &H20
RUNTIME_INFO_DONT_SHOW_ERROR_DIALOG = &H40
End Enum

Private Declare Function GetRequestedRuntimeInfo Lib "MSCorEE.dll" ( _
ByVal pExe As Long, _
ByVal pwszVersion As Long, _
ByVal pConfigurationFile As Long, _
ByVal startupFlags As Long, _
ByVal runtimeInfoFlags As Long, _
ByVal pDirectory As Long, _
ByVal dwDirectory As Long, _
ByRef dwDirectoryLength As Long, _
ByVal pVersion As Long, _
ByVal cchBuffer As Long, _
ByRef dwlength As Long) As Long

Private Declare Sub OutputDebugString Lib "kernel32" Alias _
"OutputDebugStringA" (ByVal lpOutputString As String)

Private Sub Form_Load()
Dim ret As Long
Dim pExe As String
Dim pwszVersion As String
Dim pConfigurationFile As String
Dim startupFlags As Long
Dim runtimeInfoFlags As Long
Dim pDirectory As String
Dim dwDirectory As Long
Dim dwDirectoryLength As Long
Dim pVersion As String
Dim cchBuffer As Long
Dim dwlength As Long

pDirectory = String(2000, 0)
dwDirectory = Len(pDirectory)
pVersion = String(2000, 0)
cchBuffer = Len(pVersion)

ret = GetRequestedRuntimeInfo( _
0, _
0, _
0, _
0, _
RUNTIME_INFO_UPGRADE_VERSION, _
StrPtr(pDirectory), _
dwDirectory, _
dwDirectoryLength, _
StrPtr(pVersion), _
cchBuffer, _
dwlength)

DebugPrint "ret = " & ret & ", LastDllError = " & Err.LastDllError
pDirectory = TrimNull(pDirectory)
pVersion = TrimNull(pVersion)
DebugPrint "pDirectory = " & pDirectory
DebugPrint "pVersion = " & pVersion
DebugPrint "dwDirectoryLength = " & dwDirectoryLength
DebugPrint "dwlength = " & dwlength
End Sub

Private Function TrimNull(ByRef s As String) As String
Dim i As Long

i = InStr(s, ChrW(0))
If i = 0 Then
TrimNull = s
Else
TrimNull = Left(s, i - 1)
End If
End Function

Public Sub DebugPrint(ByRef s As String)
Debug.Print s
OutputDebugString s & vbCrLf
End Sub





Mayayana

3/7/2011 10:55:00 PM

0

|
| From mscoree.h
|

You realize that's .Net? I guess you probably
want to make a program that insults people if
they have .Net installed? :)

If you want to find
the .Net version you could also look here:

HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP
That's the place where it's recorded, at least up
to v. 3.5.



Karl E. Peterson

3/7/2011 11:30:00 PM

0

Kevin Provance pretended :
> [in] LPCWSTR pExe,
> [in] LPCWSTR pwszVersion,
> [in] LPCWSTR pConfigurationFile,

Just pass "ByVal lpWhatever As Long", where
lpWhatever=StrPtr(Whatever), for those.

> [out] LPWSTR pDirectory,

And for that, do an "lpDirectory As Long", then dereference it with
something like:

Public Function PointerToStringW(ByVal lpStringW As Long) As String
Dim Buffer() As Byte
Dim nLen As Long

If lpStringW Then
nLen = lstrlenW(lpStringW) * 2
If nLen Then
ReDim Buffer(0 To (nLen - 1)) As Byte
CopyMemory Buffer(0), ByVal lpStringW, nLen
PointerToStringW = Buffer
End If
End If
End Function

--
..NET: It's About Trust!
http://vfre...


Kevin Provance

3/8/2011 1:36:00 AM

0


"Mayayana" <mayayana@invalid.nospam> wrote in message
news:il3np8$tmm$1@news.eternal-september.org...
> |
> | From mscoree.h
> |
>
> You realize that's .Net? I guess you probably
> want to make a program that insults people if
> they have .Net installed? :)

Yes, I know. I was waiting for someone to point out the obvious conundrum.
I'm working on improving my web based installer, which should be able to
detect the Fx and it's version. There are lots of different ways to figure
this out, obviously. The one I am translating works with multiple checks to
make an accurate determination, using both registry and return values from
the mscoree.dll. It's actually a section of code from one of the various
WINE archives. After VB, it gets converted to Pascal (as I'm sure Nobody
has probably figured out by now <g>)

As for the depreciation statement...well, you know, MSFT has been saying
that about INI functions for years, and yet they remain. Should there be a
5.0 Fx, I'll deal with updating the code them...or see what those clever
WINE guys are doing. <g>


Mayayana

3/8/2011 1:51:00 AM

0

| I'm working on improving my web based installer, which should be able to
| detect the Fx and it's version.

Well I'll be.... I never thought I'd see you
go to .Net.

Here's a fun script for you. I
use it to tell any .Net installers that the
runtime is already installed -- just in case
I accidentally try software written by a .Net
clown who neglects to mention the dependency
and then rigs their installer to go online
without asking to get the .Net runtime installer.
("Woops. Hold on. I just need to put 1 GB of
crap on your system. Won't be but a minute.")

This script shows the values used.

Ret = MsgBox("Click YES to add spoof settings and NO to remove them."), 36
Set SH = CreateObject("WScript.Shell")

If (Ret = 6) Then
s1 = "HKLM\SOFTWARE\Microsoft\.NETFramework\policy\v1.0"
SH.RegWrite s1, "3705", "REG_SZ"

s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322\Install"
SH.RegWrite s1, 1, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322\SP"
SH.RegWrite s1, 3, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322\MSI"
SH.RegWrite s1, 3, "REG_DWORD"

s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727\Install"
SH.RegWrite s1, 1, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727\SP"
SH.RegWrite s1, 3, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v2.0.50727\MSI"
SH.RegWrite s1, 3, "REG_DWORD"

s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\Install"
SH.RegWrite s1, 1, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\SP"
SH.RegWrite s1, 3, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\MSI"
SH.RegWrite s1, 3, "REG_DWORD"

s1 = "HKLM\SOFTWARE\Microsoft\NET Framework
Setup\NDP\v3.0\Setup\InstallSuccess"
SH.RegWrite s1, 1, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup\SP"
SH.RegWrite s1, 3, "REG_DWORD"
s1 = "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup\MSI"
SH.RegWrite s1, 3, "REG_DWORD"

Else
SH.RegDelete "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.0\Setup\"
SH.RegDelete "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v3.5\"
SH.RegDelete "HKLM\SOFTWARE\Microsoft\NET Framework
Setup\NDP\v2.0.50727\"
SH.RegDelete "HKLM\SOFTWARE\Microsoft\NET Framework Setup\NDP\v1.1.4322\"
SH.RegDelete "HKLM\SOFTWARE\Microsoft\.NETFramework\policy\"
End If

Set SH = Nothing


Kevin Provance

3/8/2011 2:03:00 AM

0


"Mayayana" <mayayana@invalid.nospam> wrote in message
news:il4222$q89$1@news.eternal-september.org...
>| I'm working on improving my web based installer, which should be able to
> | detect the Fx and it's version.
>
> Well I'll be.... I never thought I'd see you
> go to .Net.

::sigh::

I'm not going to the Fx, silly sod! <g> Hell, I tried out the 2010 VS for
fun one night and got rid of it the same night. It was a nightmare. When
VB finally kicks, IF it kicks, I'll go PowerBasic or FreePascal or Delphi.

I'm writing an all purpose installer, so others can use it too. Detecting
and automatically downloading various runtime packages is part of it. In
addition to the Fx, there are VC runtimes, MSI, XML, and even VB - while not
necessary these days, may once again be necessary in the future, and maybe
other packages that the demand arises for. I just so happen to be working
on the Fx part currently.

Thanks for the script tho. You need to add the 4.0 Fx.

Hint:

szNetfx40ClientRegKeyName = 'Software\Microsoft\NET Framework
Setup\NDP\v4\Client';
szNetfx40FullRegKeyName = 'Software\Microsoft\NET Framework
Setup\NDP\v4\Full';


Mayayana

3/8/2011 4:31:00 PM

0

| Thanks for the script tho. You need to add the 4.0 Fx.
|
| Hint:
|
| szNetfx40ClientRegKeyName = 'Software\Microsoft\NET Framework
| Setup\NDP\v4\Client';
| szNetfx40FullRegKeyName = 'Software\Microsoft\NET Framework
| Setup\NDP\v4\Full';
|

Thanks. I'll add that. The v. 4 runtime is
an astonishing 1-2 GB of bloated slop, so
that should give me plenty of time to cancel
any unexpected download... But one can't be
too careful. :)