Click to See Complete Forum and Search --> : shlwapi.dll: useful functions for VB programmers


Lothar Haensler
November 8th, 1999, 06:16 AM
some "Anonymous" poster in the C++ forum just posted an anwser to a question and mentioned the shlwapi.dll.
This DLL comes with IE 4 and above and contains a whole lot of functions for Path and directory handling that are very useful to VB programmers.

I wrote a class module that encapsulates some of the functions and a sample for using it:

Dim o as new stdPath

o.spec = "C:\winnt"
Debug.print "dir: " & o.spec
Debug.print "isdir? " & o.IsDir
Debug.print "empty? " & o.IsDirEmpty
Debug.print "isurl? " & o.isURL
Debug.print "isurl(file:///c:\test.htm? " & o.isURL("file:///c:\test.htm")

Debug.print "isunc? " & o.isUNC
Debug.print "isunc(file:///c:\test.htm?) " & o.isUNC("file:///c:\test.htm")
Debug.print "isunc(\\fns3\swdev_t\test) " & o.isUNC("\\fns3\swdev_t\test")

Debug.print "isnetworkpath: " & o.isNetworkPath("v:\test")

Debug.print "addBackSlash: " & o.AddBackslash("c:\test")
Debug.print "removeBackSlash: " & o.RemoveBackslash("c:\test\")

Debug.print "matchspec: c:\test\test.txt, *.txt): " & o.MatchSpec("*.txt", "c:\test\test.TXt")
Debug.print "strippath: " & o.StripPath("c:\winnt\system32\odbc32.dll")




See how easy it is to check for the existence of a file or directory...

the class module:

option Explicit

private Declare Function PathFileExists Lib "shlwapi.dll" Alias "PathFileExistsA" (byval strPath as string) as Long
private Declare Function PathIsDirectory Lib "shlwapi.dll" Alias "PathIsDirectoryA" (byval strPath as string) as Long
private Declare Function PathIsDirectoryEmpty Lib "shlwapi.dll" Alias "PathIsDirectoryEmptyA" (byval strPath as string) as Long
private Declare Function PathIsURL Lib "shlwapi.dll" Alias "PathIsURLA" (byval strPath as string) as Long
private Declare Function PathIsUNC Lib "shlwapi.dll" Alias "PathIsUNCA" (byval strPath as string) as Long
private Declare Function PathIsNetworkPath Lib "shlwapi.dll" Alias "PathIsNetworkPathA" (byval strPath as string) as Long
private Declare Function PathAddBackslash Lib "shlwapi.dll" Alias "PathAddBackslashA" (byval strPath as string) as string
private Declare Function PathRemoveBackslash Lib "shlwapi.dll" Alias "PathRemoveBackslashA" (byval strPath as string) as string
private Declare Function PathMatchSpec Lib "shlwapi.dll" Alias "PathMatchSpecA" (byval strPath as string, byval strSpec as string) as Long
private Declare Sub PathStripPath Lib "shlwapi.dll" Alias "PathStripPathA" (byval strPath as string)

Dim mstrSpec as string

public property let spec(byval strSpec as string)
mstrSpec = strSpec
End property

public property get spec() as string
spec = mstrSpec
End property

public Function FileExists(byval strSpec as string) as Boolean
FileExists = PathFileExists(strSpec) <> 0
End Function

public Function IsDir(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
IsDir = PathIsDirectory(strSpec) <> 0
End Function

public Function IsDirEmpty(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
IsDirEmpty = PathIsDirectoryEmpty(strSpec) <> 0
End Function

public Function isURL(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isURL = PathIsURL(strSpec) <> 0
End Function

public Function isUNC(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isUNC = PathIsUNC(strSpec) <> 0
End Function

public Function isNetworkPath(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isNetworkPath = PathIsNetworkPath(strSpec) <> 0
End Function

public Function AddBackslash(optional byval strSpec as string) as string
If strSpec = "" then strSpec = mstrSpec
Dim strBuff as string * 255
strBuff = strSpec & vbNullChar
Call PathAddBackslash(strBuff)
AddBackslash = Left$(strBuff, InStr(strBuff, vbNullChar) - 1)
End Function

public Function RemoveBackslash(optional byval strSpec as string) as string
If strSpec = "" then strSpec = mstrSpec
Dim strBuff as string * 255
strBuff = strSpec & vbNullChar
Call PathRemoveBackslash(strBuff)
RemoveBackslash = Left$(strBuff, InStr(strBuff, vbNullChar) - 1)
End Function

public Function MatchSpec(byval strSpec as string, optional byval strPath as string) as Boolean
If strPath = "" then strPath = mstrSpec
MatchSpec = PathMatchSpec(strPath, strSpec) <> 0
End Function


public Function StripPath(optional byval strSpec as string) as string
Dim strTemp as string * 255
If strSpec = "" then
strTemp = mstrSpec
else
strTemp = strSpec
End If
Call PathStripPath(strTemp)
StripPath = strTemp
End Function





There are many more functions in this DLL, but the sample shows how easy it is to make use of that functionality.
(the addBackSlash and RemoveBackslash functions are, of course, easier to implement in VB...).

Chris Eastwood
November 8th, 1999, 06:28 AM
Another excellent one Lothar !

Mind if I post this up too ?


Chris Eastwood

CodeGuru - the website for developers
http://codeguru.developer.com/vb

Lothar Haensler
November 8th, 1999, 06:36 AM
Hi Chris,

go ahead. I'm still in the processing of finding new useful APIs in this DLL.
I'm going to post an update pretty soon.

Chris Eastwood
November 8th, 1999, 07:38 AM
Let me know when it's ready to post & I'll get onto it tonight / tomorrow.


Chris Eastwood

CodeGuru - the website for developers
http://codeguru.developer.com/vb

Lothar Haensler
November 8th, 1999, 08:08 AM
Ok, here is a minor extension and a few bug fixes.
it could take weeks to include ALL functions.

btw, I decided to rename the class module to cstdPath.
I also included the canonicalize function.



private Sub Command1_Click()
Dim o as new cstdPath

o.spec = "C:\winnt"
Debug.print "dir: " & o.spec
Debug.print "isdir? " & o.IsDir
Debug.print "empty? " & o.IsDirEmpty
Debug.print "isurl? " & o.isURL
Debug.print "isurl(file:///c:\test.htm? " & o.isURL("file:///c:\test.htm")

Debug.print "isunc? " & o.isUNC
Debug.print "isunc(file:///c:\test.htm?) " & o.isUNC("file:///c:\test.htm")
Debug.print "isunc(\\fns3\swdev_t\test) " & o.isUNC("\\fns3\swdev_t\test")

Debug.print "isnetworkpath: " & o.isNetworkPath("v:\test")

Debug.print "addBackSlash: " & o.AddBackslash("c:\test")
Debug.print "removeBackSlash: " & o.RemoveBackslash("c:\test\")

Debug.print "matchspec: c:\test\test.txt, *.txt): " & o.MatchSpec("*.txt", "c:\test\test.TXt")
Debug.print "strippath: " & o.StripPath("c:\winnt\system32\odbc32.dll")
Debug.print "canonicalize: " & o.Canonicalize("c:\winnt\..\system32\odbc32.dll")

End Sub




the class module

option Explicit
' Class module wrapper for accessing functions in shlwapi.dll
' for path and directory manipulation
private Declare Function PathFileExists Lib "shlwapi.dll" Alias "PathFileExistsA" (byval strPath as string) as Long
private Declare Function PathIsDirectory Lib "shlwapi.dll" Alias "PathIsDirectoryA" (byval strPath as string) as Long
private Declare Function PathIsDirectoryEmpty Lib "shlwapi.dll" Alias "PathIsDirectoryEmptyA" (byval strPath as string) as Long
private Declare Function PathIsURL Lib "shlwapi.dll" Alias "PathIsURLA" (byval strPath as string) as Long
private Declare Function PathIsUNC Lib "shlwapi.dll" Alias "PathIsUNCA" (byval strPath as string) as Long
private Declare Function PathIsNetworkPath Lib "shlwapi.dll" Alias "PathIsNetworkPathA" (byval strPath as string) as Long
private Declare Function PathAddBackslash Lib "shlwapi.dll" Alias "PathAddBackslashA" (byval strPath as string) as string
private Declare Function PathRemoveBackslash Lib "shlwapi.dll" Alias "PathRemoveBackslashA" (byval strPath as string) as string
private Declare Function PathMatchSpec Lib "shlwapi.dll" Alias "PathMatchSpecA" (byval strPath as string, byval strSpec as string) as Long
private Declare Sub PathStripPath Lib "shlwapi.dll" Alias "PathStripPathA" (byval strPath as string)
private Declare Function PathCanonicalize Lib "shlwapi.dll" Alias "PathCanonicalizeA" (byval strDest as string, byval strSource as string) as Long

Dim mstrSpec as string

public property let spec(byval strSpec as string)
mstrSpec = strSpec
End property

public property get spec() as string
spec = mstrSpec
End property

public Function FileExists(byval strSpec as string) as Boolean
FileExists = PathFileExists(strSpec) <> 0
End Function

public Function IsDir(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
IsDir = PathIsDirectory(strSpec) <> 0
End Function

public Function IsDirEmpty(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
IsDirEmpty = PathIsDirectoryEmpty(strSpec) <> 0
End Function

public Function isURL(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isURL = PathIsURL(strSpec) <> 0
End Function

public Function isUNC(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isUNC = PathIsUNC(strSpec) <> 0
End Function

public Function isNetworkPath(optional byval strSpec as string) as Boolean
If strSpec = "" then strSpec = mstrSpec
isNetworkPath = PathIsNetworkPath(strSpec) <> 0
End Function

public Function AddBackslash(optional byval strSpec as string) as string
If strSpec = "" then strSpec = mstrSpec
Dim strBuff as string * 255
strBuff = strSpec & vbNullChar
Call PathAddBackslash(strBuff)
AddBackslash = Left$(strBuff, InStr(strBuff, vbNullChar) - 1)
End Function

public Function RemoveBackslash(optional byval strSpec as string) as string
If strSpec = "" then strSpec = mstrSpec
Dim strBuff as string * 255
strBuff = strSpec & vbNullChar
Call PathRemoveBackslash(strBuff)
RemoveBackslash = Left$(strBuff, InStr(strBuff, vbNullChar) - 1)
End Function

public Function MatchSpec(byval strSpec as string, optional byval strPath as string) as Boolean
If strPath = "" then strPath = mstrSpec
MatchSpec = PathMatchSpec(strPath, strSpec) <> 0
End Function


public Function StripPath(optional byval strSpec as string) as string
Dim strTemp as string * 255
strTemp = string(255, vbNullChar)
If strSpec = "" then
strTemp = mstrSpec
else
strTemp = strSpec
End If
Call PathStripPath(strTemp)
StripPath = Left(strTemp, InStr(strTemp, " ") - 1)
End Function


public Function Canonicalize(optional byval strSpec as string) as string
Dim strTemp as string * 255
If strSpec = "" then
strTemp = mstrSpec
else
strTemp = strSpec
End If
Dim strDest as string * 255
If PathCanonicalize(strDest, strTemp) <> 0 then
Canonicalize = Left(strDest, InStr(strDest, " ") - 1)
else
Canonicalize = ""
Err.Raise Number:=vbObjectError + 2001, _
Description:="failed to canonicalize path '" & strTemp & "'"
End If
End Function

Chris Eastwood
November 9th, 1999, 03:37 PM
I've added the code in both a ZIP project and a downloadable class module at :

http://codeguru.developer.com/vb/articles/1937.shtml

I've also added a couple of extra calls to the class module (StripToRoot, Compact (eg. c:\.....\test.exe) and StripExtension)

- I just can't believe that I've missed this functionality for so long !, time to rewrite lot's of old legacy code I think !

Cheers Lothar


Chris Eastwood

CodeGuru - the website for developers
http://codeguru.developer.com/vb

Lothar Haensler
November 10th, 1999, 01:45 AM
Thanks, Chris.

You know what would be really cool?
create a typelib with all the function in shlwapi.dll using MIDL.
The result would be a Typelib that could be easily added to the references of VB project.
Hit F2 to get the Typelib description via Object Browser.
Unfortunately, I do not know enough about IDL to create such a Typelib.

I think that would be better than creating an ActiveX DLL in VB...

Lothar Haensler
November 11th, 1999, 03:54 AM
I have done some homework and implemented the first step towards building a typelib.
This is the source:

[
uuid(c37f05f0-981b-11d3-99a1-00508b91db32),helpstring("shlwapi Path functions"),
lcid(0x9),
version(1.0)
]
library shlwapiPath
{
[dllname("shlwapi.dll")]
module DLLDeclarations {
[helpstring("checks for file existence"),entry("PathFileExistsA")] boolean
PathFileExists( LPSTR strFile );
};
}




Now, if you take that and run it against mktyplib /nocpp, you'll get a TLB file, that you can add to the references of your VB project.
Hit F2 and get descriptions of each function.
No class module needed, no declares, no nothing :-)
simply call the function like this:

if PathFileExists("yourfile") then
Msgbox "file exists"
end if



isn't [i]that really cool?

Chris Eastwood
November 11th, 1999, 05:03 AM
So, when are you going to add the rest ? ;-)

Chris Eastwood

CodeGuru - the website for developers
http://codeguru.developer.com/vb

Lothar Haensler
November 11th, 1999, 05:58 AM
I did already, but some functions do not make sense in a typlib.
...or, I still don't know enough about them.
e.g. PathAddBackslash does not return the new string, but rather modifies the buffer passed to that function. That makes it extremely unhandy in a VB program.


[
uuid(c37f05f0-981b-11d3-99a1-00508b91db32),helpstring("shlwapi Path functions"),
lcid(0x9),
version(1.0)
]
library shlwapiPath
{
[dllname("shlwapi.dll")]
module DLLDeclarations {
[helpstring("checks for file existence"),entry("PathFileExistsA")] boolean
FileExists([in] LPSTR strFile );

[helpstring("checks if path is a directory"), entry("PathIsDirectoryA")] boolean
IsDirectory([in] LPSTR strPath);

[helpstring("checks if directory is empty"), entry("PathIsDirectoryEmptyA") ] boolean
IsDirEmpty([in] LPSTR strPath);

[helpstring("check if path is an URL"),entry("PathIsURLA")] boolean
IsURL([in] LPSTR strPath);

[helpstring("check if path is an UNC path"),entry("PathIsUNCA")] boolean
IsUNC([in] LPSTR strPath);

[helpstring("check if path is a network path"),entry("PathIsNetworkPathA")] boolean
IsNetworkPath([in] LPSTR strPath);

[helpstring("checks it the path matches a given spec"), entry("PathMatchSpecA")] boolean
MatchSpec([in] LPSTR strPath, [in] LPSTR strSpec);

[helpstring("adds a backslash if necessary"),entry("PathAddBackslashA")]
void PathAddBackslash([in, out] LPSTR strPath);
};
}




how to use it:

MsgBox FileExists("c:\test.csv")
MsgBox IsDirectory("c:\test.csv")
MsgBox IsDirEmpty("m:\schrott")
Dim strt as string * 50
strt = "m:\schrott" & vbNullChar
Call PathAddBackslash(strt)
MsgBox rtrim(strt)