QB64.org Forum
Active Forums => QB64 Discussion => Topic started by: SpriggsySpriggs on September 26, 2020, 11:07:10 pm
-
I need help from someone on the forum who is used to dealing with WinAPI. I'm trying this code out and it keeps truncating values even though my buffer would definitely be able to hold the path for the variable. The max path in Windows 10 is 260 and no matter what I use, I see truncated strings. This code allows for more than one Environment variable and so this screenshot shows me trying two at the same time:
[ This attachment cannot be displayed inline in 'Print Page' view ]
And my code:
PRINT EnvVariable
("%userprofile% %homepath%")
variable
= variable
+ CHR$(0) size = 1024
a
= EnvironmentVariable
(_OFFSET(variable
), size
) EnvVariable = variable
I've tried this code in both 64 and 32 bit QB64. I'm using v1.4 on Windows 10.
-
I think I might have just fixed it. I'll keep testing.
-
There's http://www.qb64.org/wiki/ENVIRON$ (http://www.qb64.org/wiki/ENVIRON$).
-
There's http://www.qb64.org/wiki/ENVIRON$ (http://www.qb64.org/wiki/ENVIRON$).
@FellippeHeitor
Good grief..... I forgot all about that functionality in QB64..... Question: Does this work with User defined environment variables or ones added by programs?
Dang..... I spent all that time trying to figure out what was wrong and it exists in QB64 already. The only thing different with the WinAPI one is that it allows for multiple variables at the same time.
-
The main thing I see is a speed difference and the ENVIRON$ is not returning the username when I use the USERNAME variable. The WinAPI version does and completes listing the basic list of environment variables twice as fast as the built in ENVIRON$ function. HMMMM..... There are drawbacks to both, I reckon. One allows for multiple variables at once, one doesn't. One is accurate each time I run it, one misses the USERNAME variable (if I run ENVIRON$("USERNAME") own it works just fine.... I don't get it) . One is twice as fast. Oh well. I'll still put it in my API collection zip as a demo, I guess.
-
ENVIRON$ uses C++'s getenv() internally.
-
ENVIRON$ uses C++'s getenv() internally.
I see. It will just depend on the program whether or not I end up using the one I wrote or the one already there. It wasn't a total loss, I suppose. I learned a bit more about how to do that string buffer properly.
-
For the record, the proper way to call DoEnvironmentSubstA is like this:
DEFLNG A-Z
DECLARE DYNAMIC LIBRARY "Shell32"
FUNCTION EnvironmentVariable& ALIAS DoEnvironmentSubstA (pszSrc$, BYVAL cchSrc AS _UNSIGNED LONG)
END DECLARE
PRINT EnvVariable("%os%")
FUNCTION EnvVariable$ (template$)
DIM size AS _UNSIGNED LONG
size = 256
IF LEN(template$) > size THEN size = LEN(template$)
DO
buf$ = SPACE$(size)
LSET buf$ = template$ + CHR$(0)
result = EnvironmentVariable(buf$, size)
size = size * 2
LOOP UNTIL _SHR(result, 16)
EnvVariable$ = LEFT$(buf$, (result AND &HFFFF&) - 1)
END FUNCTION
and even then I should really be making sure `size` doesn't overflow.
ENVIRON$ is obviously the better way to do this, but note that DoEnvironmentSubstA is deprecated in favour of ExpandEnvironmentStringsA anyway. Thankfully the latter has a far more sensible calling convention, with separate input and output buffers.
EDIT And here's an example of calling the much more sensible ExpandEnvironmentStringsA:DEFLNG A-Z
DECLARE DYNAMIC LIBRARY "Kernel32"
FUNCTION EnvironmentVariable& ALIAS ExpandEnvironmentStringsA (src$, dest$, BYVAL size AS _UNSIGNED LONG)
END DECLARE
PRINT EnvVariable("%os%")
FUNCTION EnvVariable$ (template$)
templatez$ = template$ + CHR$(0)
size = 256
buf$ = SPACE$(size)
result = EnvironmentVariable(templatez$, buf$, size)
IF result = 0 THEN ERROR 5
IF result > size THEN
size = result
buf$ = SPACE$(size)
result = EnvironmentVariable(templatez$, buf$, size)
END IF
IF result = 0 OR result > size THEN ERROR 5
EnvVariable$ = LEFT$(buf$, result - 1)
END FUNCTION
-
@luke Oh well. I didn't see the newer version of that function out there when I was doing that or else I would have for sure used that one. I don't like using the deprecated ones if I can find the updated versions. When I check the MSDN documentation it says that the pszSrc variable is a pointer to a string, not a string. In your snippet you have it as a string. I guess it doesn't matter since I tested your snippet and it worked. Huh. I always thought it was strict on those things. That's cool that it didn't care.