I am using the following code to make a connection with a network path to get the list of files.
The network path is defiantly correct, and it is possible for me to map a drive manually with the same credentials. Just when running this code, the error: "53" is displayed which means "The network path was not found.".
The error happens suddenly which suggests to me that even the connection is not being made.
Dim nr As New NETRESOURCE
nr.dwType = RESOURCETYPE_DISK
nr.lpRemoteName = "\\fileserver.ourserver.com\"
MessageBox.Show(WNetAddConnection2(nr, "Password", "ourserver.com\User", 0))
The other code is:
Imports System.Runtime.InteropServices
Imports System
Imports System.IO
Public Class Form1
<StructLayout(LayoutKind.Sequential)> _
Private Structure NETRESOURCE
Public dwScope As UInteger
Public dwType As UInteger
Public dwDisplayType As UInteger
Public dwUsage As UInteger
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpLocalName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpRemoteName As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpComment As String
<MarshalAs(UnmanagedType.LPTStr)> _
Public lpProvider As String
End Structure
Private Const NO_ERROR As Long = 0
Private Const RESOURCETYPE_DISK As UInteger = 1
<DllImport("mpr.dll", CharSet:=CharSet.Auto)> _
Private Shared Function WNetAddConnection2(ByRef lpNetResource As NETRESOURCE, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpPassword As String, <[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpUserName As String, ByVal dwFlags As UInteger) As UInteger
End Function
<DllImport("mpr.dll", CharSet:=CharSet.Auto)> _
Private Shared Function WNetCancelConnection2(<[In](), MarshalAs(UnmanagedType.LPTStr)> ByVal lpName As String, ByVal dwFlags As UInteger, <MarshalAs(UnmanagedType.Bool)> ByVal fForce As Boolean) As UInteger
End Function
End Class
Is there a reason you are using an interop class to list your files, you could use the .net Framework to DiriectoryInfo class to do the same.
Unsure why, but adding /IPC$ to the server path now lets me use it again.
Related
I have the following issue with my code.
Win32 handle that was passed to Icon is not valid or is the wrong type
The line of codes are as follow:
SHFILEINFO Declaration
Private Structure SHFILEINFO
Public hIcon As IntPtr ' : iconc
Public iIcon As Integer ' : icondex
Public dwAttributes As Integer ' : SFGAO_ flags
_
Public szDisplayName As String
_
Public szTypeName As String
End Structure
SHGetFileInfo Declaration
Private Declare Auto Function SHGetFileInfo Lib "shell32.dll" _
(ByVal pszPath As String, _
ByVal dwFileAttributes As Integer, _
ByRef psfi As SHFILEINFO, _
ByVal cbFileInfo As Integer, _
ByVal uFlags As Integer) As IntPtr
Private Const SHGFI_ICON = &H100
Private Const SHGFI_SMALLICON = &H1
Private Const SHGFI_LARGEICON = &H0 ' Large icon
Private Const MAX_PATH = 260
SHGetFileInfo Usage
Private Sub AddImageToImageListBox(ByVal strFileName As String)
On Error GoTo errHandler
Dim shInfo As SHFILEINFO
shInfo = New SHFILEINFO()
shInfo.szDisplayName = New String(vbNullChar, MAX_PATH)
shInfo.szTypeName = New String(vbNullChar, 80)
Dim hIcon As IntPtr
hIcon = SHGetFileInfo(strFileName, 0, shInfo, Marshal.SizeOf(shInfo), SHGFI_ICON Or SHGFI_SMALLICON)
Dim MyIcon As Drawing.Bitmap
MyIcon = Drawing.Icon.FromHandle(shInfo.hIcon).ToBitmap
imgAttachment.AddImage(MyIcon)
ilstAttachments.Items.Add(strFileName.ToString(), imgAttachment.Images.Count - 1)
Exit Sub
errHandler:
ErrMsg("AddImageToImageListBox (errHandler)")
End Sub
Runtime
Here are the values that being passed into SHGetFileInfo.
strFileName = "Copy (223) of Uncollected Card - Multiple Pages.TIF"
shInfo.dwAttributes = 0
shInfo.hIcon = 0
shInfo.iIcon = 0
shInfo.szDisplayName = ""
shInfo.szTypeName = ""
Error
When the stated values above are being passed to SHGetFileInfo, it returns 0 value thus making hIcon = 0.
When it reaches
MyIcon = Drawing.Icon.FromHandle(shInfo.hIcon).ToBitmap
The following error occurred
Win32 handle that was passed to Icon is not valid or is the wrong type
Can you guys help me to identify what is the issue?
Thank you
Try changing SHFILEINFO and SHGetFileInfo to this
Private Structure SHFILEINFO
Public hIcon As IntPtr ' : iconc
Public iIcon As Integer ' : icondex
Public dwAttributes As Integer ' : SFGAO_ flags
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=260)> _
Public szDisplayName As String
<MarshalAs(UnmanagedType.ByValTStr, SizeConst:=80)>
Public szTypeName As String
End Structure
Private Declare Ansi Function SHGetFileInfo Lib "shell32.dll" (ByVal pszPath As String, _
ByVal dwFileAttributes As Integer, ByRef psfi As SHFILEINFO, ByVal cbFileInfo As Integer, _
ByVal uFlags As Integer) As IntPtr
Also, I would lose the On Error Goto and use a Try/Catch.
I need to first map and then later unmap 2x drives using VB.NET.
When mapping the drives, I also need to pass a username and password (as not all users have admin access).
However, not only is the below not working (failing to map, so in turn failing to unmap), but I notice that I only have the option to pass a password when mapping a drive, not a username.
Can anyone help me in fixing these problems? Thanks.
Private Declare Function WNetAddConnection Lib "mpr.dll" Alias "WNetAddConnectionA" (ByVal lpszNetPath As String,
ByVal lpszPassword As String,
ByVal lpszLocalName As String) As Long
Private Declare Function WNetCancelConnection Lib "mpr.dll" Alias "WNetCancelConnectionA" (ByVal lpszName As String,
ByVal bForce As Long) As Long
Public Function MapDrive(ByVal UNCPath As String, ByVal Password As String, ByVal DriveLetter As String) As Boolean
Dim MappedResult As Long = WNetAddConnection(UNCPath, Password, DriveLetter)
Return IIf(MappedResult = 0, True, False)
End Function
Public Function UnmapDrive(ByVal DriveLetter As String) As Boolean
Dim UnmappedResult As Long = WNetCancelConnection(DriveLetter, 0)
Return IIf(UnmappedResult = 0, True, False)
End Function
You should switch to using the WNetAddConnection2/WNetCancelConnection2 functions. The former allows you to specify a username in the call. Here are the PInvoke signatures I've used successfully in the past:
Private Declare Function WNetAddConnection2 Lib "mpr.dll" Alias "WNetAddConnection2A" _
(ByRef lpNetResource As NETRESOURCE, ByVal lpPassword As String, _
ByVal lpUserName As String, ByVal dwFlags As Integer) As Integer
Private Declare Function WNetCancelConnection2 Lib "mpr.dll" Alias "WNetCancelConnection2A" _
(ByVal lpName As String, ByVal dwFlags As Integer, ByVal fForce As Integer) As Integer
Private Declare Function WNetGetLastError Lib "mpr.dll" Alias "WNetGetLastErrorA" _
(ByRef nError As Integer, ByRef lpErrorBuf As String, ByVal nErrorBufSize As Integer, _
ByRef lpNamebuf As String, ByVal nNameBufSize As Integer) As Integer
<StructLayout(LayoutKind.Sequential)> _
Public Structure NETRESOURCE
Public dwScope As Integer
Public dwType As Integer
Public dwDisplayType As Integer
Public dwUsage As Integer
Public lpLocalName As String
Public lpRemoteName As String
Public lpComment As String
Public lpProvider As String
End Structure
Private Const ForceDisconnect As Integer = 1
Private Const RESOURCETYPE_DISK As Long = &H1
GetLastError is useful for figuring out why the mapping failed (bad password, etc).
I have a program that shows previews of jpgs in small pictureboxes. The loading of these images is slow, and takes almost a second for each. That is because the images are big (8/9 mB). I would need to load them quickly, for example by loading a thumb of the picture. I would like to avoid putting all into the memory since there could be hundreds of pictures.
what is your advice on this?
THanks
You need to resize the pictures in advance.
Creating tumbnails would be equally slow because you need to read the whole file, before you can even start making the tumbnail.
What you could do is, just like windows, create a tumbnail 'data base', where you store the tumbs for each picture. And only use the full size picture if needed.
So if you have like,
picture001.jpg
picture002.jpg
picture003.jpg
Create tumbs for each one;
picture001.jpg
picture001_tumb.jpg
picture002.jpg
picture002_tumb.jpg
picture003.jpg
picture003_tumb.jpg
So in the loading of the picuters detect, if the _tumb.jpg is there, if not create and store it. Which ofcourse, needs to be done in a background worker, because you need your main app to responsive...
You can also use this code, to request the icon from the windows shell;
Imports System.Runtime.InteropServices
Imports System
Imports System.Drawing
Imports System.Drawing.Imaging
Imports System.Collections.Generic
Imports System.Text
' http://www.vbforums.com/showthread.php?617626-How-do-I-extract-a-256X256-image-out-of-an-icon&highlight=IShellItemImageFactory
Module GetShellIcon
<Flags()> _
Public Enum SIIGBF
SIIGBF_RESIZETOFIT = 0
SIIGBF_BIGGERSIZEOK = 1
SIIGBF_MEMORYONLY = 2
SIIGBF_ICONONLY = 4
SIIGBF_THUMBNAILONLY = 8
SIIGBF_INCACHEONLY = 16
End Enum
Public Enum SIGDN As UInteger
NORMALDISPLAY = 0
PARENTRELATIVEPARSING = &H80018001UI
PARENTRELATIVEFORADDRESSBAR = &H8001C001UI
DESKTOPABSOLUTEPARSING = &H80028000UI
PARENTRELATIVEEDITING = &H80031001UI
DESKTOPABSOLUTEEDITING = &H8004C000UI
FILESYSPATH = &H80058000UI
URL = &H80068000UI
End Enum
<ComImportAttribute(), GuidAttribute("bcc18b79-ba16-442f-80c4-8a59c30c463b"), InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IShellItemImageFactory
Sub GetImage(ByVal size As SIZE, ByVal flags As SIIGBF, ByRef phbm As IntPtr)
End Interface
<ComImport()> <Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")> <InterfaceType(ComInterfaceType.InterfaceIsIUnknown)> _
Public Interface IShellItem
Sub BindToHandler(ByVal pbc As IntPtr, <MarshalAs(UnmanagedType.LPStruct)> ByVal bhid As Guid, <MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, ByRef ppv As IntPtr)
Sub GetParent(ByRef ppsi As IShellItem)
Sub GetDisplayName(ByVal sigdnName As SIGDN, ByRef ppszName As IntPtr)
Sub GetAttributes(ByVal sfgaoMask As UInt32, ByRef psfgaoAttribs As UInt32)
Sub Compare(ByVal psi As IShellItem, ByVal hint As UInt32, ByRef piOrder As Integer)
End Interface
<DllImport("shell32.dll", CharSet:=CharSet.Unicode, PreserveSig:=False)> _
Public Sub SHCreateItemFromParsingName(<MarshalAs(UnmanagedType.LPWStr)> ByVal pszPath As String, ByVal pbc As IntPtr, <MarshalAs(UnmanagedType.LPStruct)> ByVal riid As Guid, <MarshalAs(UnmanagedType.Interface, IidParameterIndex:=2)> ByRef ppv As IShellItem)
End Sub
<StructLayout(LayoutKind.Sequential)> _
Public Structure SIZE
Public cx As Integer
Public cy As Integer
Public Sub New(ByVal cx As Integer, ByVal cy As Integer)
Me.cx = cx
Me.cy = cy
End Sub
End Structure
Public Function GetShellIcon(ByVal Path As String, MySIIGBF As SIIGBF, Optional ByVal Width As Integer = 256, Optional ByVal Height As Integer = 256) As Bitmap
Dim ppsi As IShellItem = Nothing
Dim hbitmap As IntPtr = IntPtr.Zero
Dim uuid As New Guid("43826d1e-e718-42ee-bc55-a1e261c37bfe")
Dim bs As Bitmap
SHCreateItemFromParsingName(Path, IntPtr.Zero, uuid, ppsi)
DirectCast(ppsi, IShellItemImageFactory).GetImage(New SIZE(Width, Height), MySIIGBF, hbitmap)
bs = System.Drawing.Bitmap.FromHbitmap(hbitmap)
bs.MakeTransparent(Color.Black)
Return bs
End Function
End Module
I got a PL/I Dll and I'm trying to import the DLL into my VB.Net Application.
The first try worked but the program did quit without comment after a few calls.
And it is not possible to call these function twice from two different threads.
I get the result from the DLL in paramone. Any Ideas why this doesn't work right and how to get it to work?
<DllImport(("PLIDLL.dll"), CallingConvention:=CallingConvention.StdCall)> _
Public Shared Sub MYFUNC(ByVal LogonString As String, _
<MarshalAs(UnmanagedType.VBByRefStr)> ByRef paramone As String, _
ByVal paramtwo As String)
End Sub
If anything is unclear please ask.
Greetings Lim
PS: I already tried to rerewrite the PL/I Code so that it returns a String instead of the ByRef value. Same issue.
The Sub in PLI:
MYFUNC: PROC(LOGONSTRING,PARAMONE,PARAMTWO) REORDER
OPTIONS(FROMALIEN NODESCRIPTOR
BYADDR LINKAGE(STDCALL));
DEFAULT RANGE(*) STATIC;
DCL LOGONSTRING CHAR(30);
DCL PARAMONE CHAR(2033);
DCL PARAMTWO CHAR (5500);
Found at least a working solution.
Module NativeMethods
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Function LoadLibrary(ByVal lpFileName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Function GetProcAddress(ByVal hModule As IntPtr, ByVal procedureName As String) As IntPtr
End Function
<DllImport("kernel32.dll", SetLastError:=True)> _
Public Function FreeLibrary(ByVal hModule As IntPtr) As IntPtr
End Function
End Module
<UnmanagedFunctionPointer(CallingConvention.StdCall)>
Private Delegate Sub MYFUNC(ByVal LogonString As String, <MarshalAs(UnmanagedType.VBByRefStr)> ByRef PARAMONE As String, ByVal PARAMTWO As String)
Public Shared Sub CallFunction(ByRef workingObject As PLIOBJECT)
Dim EntryPointer As IntPtr = NativeMethods.LoadLibrary("PLIDLL.dll")
Dim FunctionPointer As IntPtr = NativeMethods.GetProcAddress(EntryPointer, "MYFUNC")
Dim MyFUNC As MYFUNC= CType(Marshal.GetDelegateForFunctionPointer(FunctionPointer, GetType(MYFUNC)), MYFUNC)
MyFUNC(workingObject.Logonstring, workingObject.PARAMONE, workingObject.PARAMTWO)
Dim result As Boolean = NativeMethods.FreeLibrary(EntryPointer)
End Sub
How should I DLLImport things in VB.NET? An example would be:
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindowText(ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
End Function
If I put it inside a Class or somewhere else, I get "DLLimport is not defined" I am using Visual Studio 2008 Professional
You have to add Imports System.Runtime.InteropServices to the top of your source file.
Alternatively, you can fully qualify attribute name:
<System.Runtime.InteropService.DllImport("user32.dll", _
SetLastError:=True, CharSet:=CharSet.Auto)> _
Imports System.Runtime.InteropServices
I know this has already been answered, but here is an example for the people who are trying to use SQL Server Types in a vb project:
Imports System
Imports System.IO
Imports System.Runtime.InteropServices
Namespace SqlServerTypes
Public Class Utilities
<DllImport("kernel32.dll", CharSet:=CharSet.Auto, SetLastError:=True)>
Public Shared Function LoadLibrary(ByVal libname As String) As IntPtr
End Function
Public Shared Sub LoadNativeAssemblies(ByVal rootApplicationPath As String)
Dim nativeBinaryPath = If(IntPtr.Size > 4, Path.Combine(rootApplicationPath, "SqlServerTypes\x64\"), Path.Combine(rootApplicationPath, "SqlServerTypes\x86\"))
LoadNativeAssembly(nativeBinaryPath, "msvcr120.dll")
LoadNativeAssembly(nativeBinaryPath, "SqlServerSpatial140.dll")
End Sub
Private Shared Sub LoadNativeAssembly(ByVal nativeBinaryPath As String, ByVal assemblyName As String)
Dim path = System.IO.Path.Combine(nativeBinaryPath, assemblyName)
Dim ptr = LoadLibrary(path)
If ptr = IntPtr.Zero Then
Throw New Exception(String.Format("Error loading {0} (ErrorCode: {1})", assemblyName, Marshal.GetLastWin32Error()))
End If
End Sub
End Class
End Namespace
I saw in getwindowtext (user32) on pinvoke.net that you can place a MarshalAs statement to state that the StringBuffer is equivalent to LPSTR.
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Ansi)> _
Public Function GetWindowText(hwnd As IntPtr, <MarshalAs(UnManagedType.LPStr)>lpString As System.Text.StringBuilder, cch As Integer) As Integer
End Function
You can also try this
Private Declare Function GetWindowText Lib "user32.dll" (ByVal hwnd As IntPtr, ByVal lpString As StringBuilder, ByVal cch As Integer) As Integer
I always use Declare Function instead of DllImport...
Its more simply, its shorter and does the same