VB.NET Display file icons from Network Paths with calling Shell - vb.net

I have this program that shows files with its icons using a ListView and it works a little bit fine but there's a problem, some files(.exe, .docx etc...) don't show their right icon like this. how do I fix that?
This is how I call the Shell:
' declare the Win32 API function SHGetFileInfo'
Public 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
' declare some constants that SHGetFileInfo requires'
Public Const SHGFI_ICON As Integer = &H100
Public Const SHGFI_SMALLICON As Integer = &H1
' define the SHFILEINFO structure'
Structure SHFILEINFO
Public hIcon As IntPtr
Public iIcon As Integer
Public dwAttributes As Integer
<Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=260)> _
Public szDisplayName As String
<Runtime.InteropServices.MarshalAs(Runtime.InteropServices.UnmanagedType.ByValTStr, SizeConst:=80)> _
Public szTypeName As String
End Structure
Function RetrieveShellIcon(ByVal argPath As String) As Image
Dim mShellFileInfo As SHFILEINFO
Dim mSmallImage As IntPtr
Dim mIcon As System.Drawing.Icon
Dim mCompositeImage As Image
mShellFileInfo = New SHFILEINFO
mShellFileInfo.szDisplayName = New String(Chr(0), 260)
mShellFileInfo.szTypeName = New String(Chr(0), 80)
mSmallImage = SHGetFileInfo(argPath, 0, mShellFileInfo, System.Runtime.InteropServices.Marshal.SizeOf(mShellFileInfo), SHGFI_ICON Or SHGFI_SMALLICON)
' create the icon from the icon handle'
Try
mIcon = System.Drawing.Icon.FromHandle(mShellFileInfo.hIcon)
mCompositeImage = mIcon.ToBitmap
Catch ex As Exception
' create a blank black bitmap to return'
mCompositeImage = New Bitmap(16, 16)
End Try
' return the composited image'
Return mCompositeImage
End Function
Function GetIcon(ByVal argFilePath As String) As Image
Dim mFileExtension As String = System.IO.Path.GetExtension(argFilePath)
' add the image if it doesn't exist'
If cIcons.ContainsKey(mFileExtension) = False Then
cIcons.Add(mFileExtension, RetrieveShellIcon(argFilePath))
End If
' return the image'
Return cIcons(mFileExtension)
End Function
and this is how I show file icons in my `ListView.
Sub lv1items()
Dim lvi As ListViewItem
Dim di As New DirectoryInfo(Form2.TextBox1.Text)
Dim exts As New List(Of String)
ImageList1.Images.Clear()
If di.Exists = False Then
MessageBox.Show("Source path is not found", "Directory Not Found", MessageBoxButtons.OK, MessageBoxIcon.Error)
Else
For Each fi As FileInfo In di.EnumerateFiles("*.*")
lvi = New ListViewItem
lvi.Text = fi.Name
lvi.SubItems.Add(((fi.Length / 1024)).ToString("0.00"))
lvi.SubItems.Add(fi.CreationTime.ToShortDateString)
If exts.Contains(fi.Extension) = False Then
Dim mShellIconManager As New Form1
For Each mFilePath As String In My.Computer.FileSystem.GetFiles(Form2.TextBox1.Text)
ImageList1.Images.Add(fi.Extension, GetIcon(mFilePath))
exts.Add(fi.Extension)
Next
End If
lvi.ImageKey = fi.Extension
ListView1.Items.Add(lvi)
Next
End If
End Sub

That appears to be a weird limitation of the .net implication
its really just making a call to shell32.dll
You should call the function in shell32 directly
something like this should work
<DllImport("shell32.dll")>
Private Shared Function ExtractAssociatedIcon(hInst As IntPtr, lpIconPath As StringBuilder, ByRef lpiIcon As UShort) As IntPtr
End Function
_
Dim handle As IntPtr = SafeNativeMethods.ExtractAssociatedIcon(New HandleRef(Nothing, IntPtr.Zero), iconPath, index)
If handle <> IntPtr.Zero Then
Return Icon.FromHandle(handle)
End If
The syntax might not be exactly correct, also there is a good blog post about how to pull that information from the registry (which won't always give you the correct answer, but its faster)
Building a Better ExtractIcon (he uses the SHGetFileInfo API in shell32.dll if that blog ever dies it will give people a place to start looking)

Related

How do I play multiple sounds at once? VB .NET

I am trying to play multiple sounds at once.
I have tried:
Private Declare Function mciSendString Lib "winmm.dll" Alias "mciSendStringA" _
(ByVal lpstrCommand As String, ByVal lpstrReturnString As String, _
ByVal uReturnLength As Integer, ByVal hwndCallback As Integer) As Integer
'The Sub i am wanting to play the sound in
mciSendString("close myWAV", Nothing, 0, 0)
Dim fileName1 As String = My.Computer.FileSystem.CurrentDirectory + "\Sound\Sound file1.wav"
mciSendString(String.Format("open ""{0}"" type mpegvideo alias myWAV", fileName1), Nothing, 0, 0)
mciSendString("play myWAV", Nothing, 0, 0)
This does nothing at all, is it wrong?
I have also tried:
Dim SoundPlayer(2) As System.Media.SoundPlayer
SoundPlayer(1) = New Media.SoundPlayer(My.Resources.Sound_File_1)
SoundPlayer(2) = New Media.SoundPlayer(My.Resources.Sound_File_2)
SoundPlayer(1).Play
SoundPlayer(2).Play
This plays the second sound but not the first, so it plays sound 1 and then plays sound 2 but does it so fast you dont hear sound 1. So that doesn't work. I have also tried;
My.Computer.Audio.Play(My.Resources.Sound_File_1, AudioPlayMode.Background)
My.Computer.Audio.Play(My.Resources.Sound_File_2, AudioPlayMode.Background)
That does the same as my previous attempt... I have also tried using directX, but this wouldn't work...
Imports Microsoft.DirectX.DirectSound
And directX seems a bit overboard for just trying to play 2 or 3 sounds at once.
I have also tried NAudio, which #Jeremy Thompson recomended (https://markheath.net/post/mixing-and-looping-with-naudio), I conveted it from C# to VB, using https://converter.telerik.com/ But it's not happy with a few parts of the code and i dont know why, here it is:
Public Class LoopStream
Inherits WaveStream
Private sourceStream As WaveStream
Public Sub New(ByVal sourceStream As WaveStream)
Me.sourceStream = sourceStream
Me.EnableLooping = True
End Sub
Public Property EnableLooping As Boolean
Public Overrides ReadOnly Property WaveFormat As WaveFormat
Get
Return sourceStream.WaveFormat
End Get
End Property
Public Overrides ReadOnly Property Length As Long
Get
Return sourceStream.Length
End Get
End Property
Public Overrides Property Position As Long
Get
Return sourceStream.Position
End Get
Set(ByVal value As Long)
sourceStream.Position = value
End Set
End Property
Public Overrides Function Read(ByVal buffer As Byte(), ByVal offset As Integer, ByVal count As Integer) As Integer
Dim totalBytesRead As Integer = 0
While totalBytesRead < count
Dim bytesRead As Integer = sourceStream.Read(buffer, offset + totalBytesRead, count - totalBytesRead)
If bytesRead = 0 Then
If sourceStream.Position = 0 OrElse Not EnableLooping Then
Exit While
End If
sourceStream.Position = 0
End If
totalBytesRead += bytesRead
End While
Return totalBytesRead
End Function
End Class
I have also tried this, but "System.Windows.Controls.MediaElement()" Doesnt exist?
Dim m1 As New System.Windows.Controls.MediaElement()
Dim m2 As New System.Windows.Controls.MediaElement()
m1.Source = New Uri(filename1)
m2.Source = New Uri(filename2)
m1.Play()
m2.Play()
Am i doing something wrong with one or more of these methods, or is their a different way to do it that i haven't tried?
Try to use the MediaElement
https://learn.microsoft.com/de-de/dotnet/api/system.windows.controls.mediaelement
it is Easy to use:
Dim m1 As New System.Windows.Controls.MediaElement()
Dim m2 As New System.Windows.Controls.MediaElement()
m1.Source = New Uri(filename1)
m2.Source = New Uri(filename2)
m1.Play()
m2.Play()
Update:
If you use .NET Framework <= 4.8 => Cannot Import System.Windows.Controls
If you use .NET CORE you have to add <UseWPF>true</UseWPF> to your .csproj - file

How to convert all pages of doc file to seperate images

The following is the code i m using to convert doc file to image.this works well for a file that contains only one page but if there are more than one page in doc file then it converts only first page of file to image.Can some one suggest me how to convert all pages of doc file to seperate images.
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim objWord As New Microsoft.Office.Interop.Word.Application
Dim objDoc As Microsoft.Office.Interop.Word.Document
Const CF_ENHMETAFILE As Integer = 14
objDoc = objWord.Documents.Open("F:\Study\Constructor.docx")
objWord.Activedocument.Select()
objWord.Selection.CopyAsPicture()
Dim ip As IntPtr
Dim metaFile As System.Drawing.Imaging.Metafile
Dim bRet As Boolean
bRet = ClipboardAPI.OpenClipboard(Me.Handle)
If bRet = True Then
'Verify the clipboard contains data available
'as an enhanced metafile.
bRet = ClipboardAPI.IsClipboardFormatAvailable(CF_ENHMETAFILE) <> 0
End If
If bRet = True Then
'Store the clipboard's contents in the IntPtr.
ip = ClipboardAPI.GetClipboardData(CF_ENHMETAFILE)
End If
'Verify the IntPrt contains data before proceeding. Passing
'an empty IntPtr to System.Drawing.Imaging.Metafile results
'in an exception.
If Not IntPtr.Zero.Equals(ip) Then
metaFile = New System.Drawing.Imaging.Metafile(ip, True)
ClipboardAPI.CloseClipboard()
Dim image As System.Drawing.Image = metaFile
'Me.PictureBox1.Image = metaFile
Dim objImageWriter As Image = New Bitmap(image.Width, image.Height)
Dim objGraphics As Graphics = Graphics.FromImage(objImageWriter)
objGraphics.Clear(Color.White)
'objGraphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
objGraphics.DrawImage(image, 0, 0, image.Width, image.Height)
image.Dispose()
objGraphics.Dispose()
Dim ep As Imaging.EncoderParameters = New Imaging.EncoderParameters
ep.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100)
Dim codecs() As Imaging.ImageCodecInfo = Imaging.ImageCodecInfo.GetImageEncoders()
Dim iciInfo As Imaging.ImageCodecInfo
Dim item As Imaging.ImageCodecInfo
For Each item In codecs
If (item.MimeType = "image/jpeg") Then iciInfo = item
Next
objImageWriter.Save("F:\Study\test1.jpg", iciInfo, ep)
objImageWriter.Dispose()
End If
Public Class ClipboardAPI
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="OpenClipboard", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function OpenClipboard(ByVal hWnd As IntPtr) As Boolean
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="EmptyClipboard", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function EmptyClipboard() As Boolean
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="SetClipboardData", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function SetClipboardData(ByVal uFormat As Integer, ByVal ByValhWnd As IntPtr) As IntPtr
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="CloseClipboard", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function CloseClipboard() As Boolean
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="GetClipboardData", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function GetClipboardData(ByVal uFormat As Integer) As IntPtr
End Function
<Runtime.InteropServices.DllImport("user32.dll", EntryPoint:="IsClipboardFormatAvailable", SetLastError:=True, ExactSpelling:=True, CallingConvention:=System.Runtime.InteropServices.CallingConvention.StdCall)> _
Public Shared Function IsClipboardFormatAvailable(ByVal uFormat As Integer) As Short
End Function
End Class
The problem is that the line "objWord.Activedocument.Select()" references the entire document rather than the document's individual pages. I've added a bit to your code to snap an image of each page's contents:
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
Dim objWord As New Microsoft.Office.Interop.Word.Application
Dim objDoc As Microsoft.Office.Interop.Word.Document
Const CF_ENHMETAFILE As Integer = 14
objDoc = objWord.Documents.Open("F:\Study\Constructor.docx")
objDoc.Repaginate()
For i As Integer = 1 To objDoc.ActiveWindow.Panes(1).Pages.Count
If i = 1 Then
With objWord.ActiveDocument
.GoTo(WdGoToItem.wdGoToPage, WdGoToDirection.wdGoToAbsolute, 1)
.Bookmarks("\Page").Range.Select()
End With
Else
With objWord.Selection
.GoTo(What:=WdGoToItem.wdGoToPage, Which:=WdGoToDirection.wdGoToNext)
.Bookmarks("\Page").Range.Select()
End With
End If
objWord.Selection.CopyAsPicture()
Dim ip As IntPtr
Dim metaFile As System.Drawing.Imaging.Metafile
Dim bRet As Boolean
bRet = ClipboardAPI.OpenClipboard(Me.Handle)
If bRet = True Then
'Verify the clipboard contains data available
'as an enhanced metafile.
bRet = ClipboardAPI.IsClipboardFormatAvailable(CF_ENHMETAFILE) <> 0
End If
If bRet = True Then
'Store the clipboard's contents in the IntPtr.
ip = ClipboardAPI.GetClipboardData(CF_ENHMETAFILE)
End If
'Verify the IntPrt contains data before proceeding. Passing
'an empty IntPtr to System.Drawing.Imaging.Metafile results
'in an exception.
If Not IntPtr.Zero.Equals(ip) Then
metaFile = New System.Drawing.Imaging.Metafile(ip, True)
ClipboardAPI.CloseClipboard()
Dim image As System.Drawing.Image = metaFile
'Me.PictureBox1.Image = metaFile
Dim objImageWriter As Image = New Bitmap(image.Width, image.Height)
Dim objGraphics As Graphics = Graphics.FromImage(objImageWriter)
objGraphics.Clear(Color.White)
'objGraphics.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
objGraphics.DrawImage(image, 0, 0, image.Width, image.Height)
image.Dispose()
objGraphics.Dispose()
Dim ep As Imaging.EncoderParameters = New Imaging.EncoderParameters
ep.Param(0) = New System.Drawing.Imaging.EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100)
Dim codecs() As Imaging.ImageCodecInfo = Imaging.ImageCodecInfo.GetImageEncoders()
Dim iciInfo As Imaging.ImageCodecInfo
Dim item As Imaging.ImageCodecInfo
For Each item In codecs
If (item.MimeType = "image/jpeg") Then iciInfo = item
Next
objImageWriter.Save("F:\Study\test" & i.ToString & ".jpg", iciInfo, ep)
objImageWriter.Dispose()
End If
Next
End Sub
Summary of the additional code changes:
I added "objDoc.Repaginate()" to get accurate page references. Word does not really make use of pages ordinarily, it is constantly querying the system's print driver to decide where it needs to break text up into pages. This ensures that we have an accurate page count in accordance with the current machine.
I enclosed your image logic in this for-loop: "For i As Integer = 1 To objDoc.ActiveWindow.Panes(1).Pages.Count". The if-else directly following that line will select the first page in the first iteration, and then any subsequent additional pages thereafter. Everything else that follows is unchanged except for the save-filename.
Lastly, I just concatenated the page number into the image's save-path for obvious reasons...
I tested this on my own computer and it worked as intended, I hope this helps!
...Just an off-topic sidenote, I don't know if the code disposing of the Word handles just wasn't included in your question or if it's actually missing, but you may want to make sure you add that; Interop class loves to leave running office processes in the background even after the program has closed if they aren't disposed of properly, this example was leaving them open on my computer.

Replicate Windows Unhide folders and files function

I'm re-visiting a tool that I wrote in VB.Net for my helpdesk team a while back and want to add a couple of checkboxes to replicate the same function that Windows uses to show hidden files and folders / re-hide, as well as protected operating system files.
I know I can do this by editing a registry entry and restarting explorer.exe, but that closes all open Explorer Windows and I don't want that.
Does anyone know how Windows is able to do this by a simple click of a checkbox and how I may be able to code it in VB.net?
Any input on this is greatly appreciated in advance.
EDIT: So it looks like I have found a refresh method that works to refresh Windows Explorer / File Explorer which can be applied to Drarig's answer below but I am having trouble converting it to VB.net as the original example is in C#.
'Original at http://stackoverflow.com/questions/2488727/refresh-windows-explorer-in-win7
Private Sub refreshExplorer(ByVal explorerType As String)
Dim CLSID_ShellApplication As Guid = Guid.Parse("13709620-C279-11CE-A49E-444553540000")
Dim shellApplicationType As Type = Type.GetTypeFromCLSID(CLSID_ShellApplication, True)
Dim shellApplication As Object = Activator.CreateInstance(shellApplicationType)
Dim windows As Object = shellApplicationType.InvokeMember("Windows", Reflection.BindingFlags.InvokeMethod, Nothing, shellApplication, New Object() {})
Dim windowsType As Type = windows.GetType()
Dim count As Object = windowsType.InvokeMember("Count", Reflection.BindingFlags.GetProperty, Nothing, windows, Nothing)
For i As Integer = 0 To CType(count, Integer)
Dim item As Object = windowsType.InvokeMember("Item", Reflection.BindingFlags.InvokeMethod, Nothing, windows, New Object() {i})
Dim itemType As Type = item.GetType()
'Only fresh Windows explorer Windows
Dim itemName As String = CType(itemType.InvokeMember("Name", Reflection.BindingFlags.GetProperty, Nothing, item, Nothing), String)
If itemName = explorerType Then
itemType.InvokeMember("Refresh", Reflection.BindingFlags.InvokeMethod, Nothing, item, Nothing)
End If
Next
End Sub
I am getting an exception Object reference not set to an instance of an object when I set itemType as Type = item.GetType() above. I can't figure out which object isn't being created. When I step through the code it looks like windowsType contains an object for windows. Does anyone have any idea on this? Once this is worked out I can then apply it to Drarig's solution below.
Alright I wish I could have got this to you sooner, but busy lately at work. I took a little time today to figure this out as I love digging into something I have not done before. This is the whole class from a new project; didn't have time to wrap it up in a separate class. I am sure this will get you what you need. It was a little harder than I thought as getting the correct handle and then send the command, but I got it. I hope you find it useful.
P.S. Some of the things you can leave out, specifically the boolean used for loading, this was so I can pull the current value back on load and either check/uncheck the CheckBox.
Note: This is tried and tested on Windows 7, 8 and 10
Imports Microsoft.Win32
Imports System.Reflection
Imports System.Runtime.InteropServices
Public Class Form1
<Flags()> _
Public Enum KeyboardFlag As UInteger
KEYBOARDF_5 = &H74
End Enum
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function GetWindow(ByVal hl As Long, ByVal vm As Long) As IntPtr
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function PostMessage(ByVal hWnd As IntPtr, ByVal Msg As UInteger, ByVal wParam As IntPtr, ByVal lParam As IntPtr) As Boolean
End Function
<DllImport("user32.dll", SetLastError:=True, CharSet:=CharSet.Auto)> _
Private Shared Function FindWindow(ByVal lpClassName As String, ByVal lpWindowName As String) As IntPtr
End Function
Private blnLoading As Boolean = False
Private Sub CheckBox1_CheckedChanged(sender As Object, e As EventArgs) Handles CheckBox1.CheckedChanged
Form1.HideFilesExtension(Me.CheckBox1.Checked)
If Not blnLoading Then NotifyFileAssociationChanged()
RefreshExplorer()
End Sub
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
Dim name As String = "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey(name, False)
blnLoading = True
Me.CheckBox1.Checked = CBool(key.GetValue("Hidden"))
key.Close()
blnLoading = False
End Sub
Private Shared Sub HideFilesExtension(ByVal Hide As Boolean)
Dim name As String = "Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Dim key As RegistryKey = Registry.CurrentUser.OpenSubKey(name, True)
key.SetValue("Hidden", If(Hide, 1, 0))
key.Close()
End Sub
Public Shared Sub RefreshExplorer()
Dim clsid As New Guid("13709620-C279-11CE-A49E-444553540000")
Dim typeFromCLSID As Type = Type.GetTypeFromCLSID(clsid, True)
Dim objectValue As Object = Activator.CreateInstance(typeFromCLSID)
Dim obj4 As Object = typeFromCLSID.InvokeMember("Windows", BindingFlags.InvokeMethod, Nothing, objectValue, New Object(0 - 1) {})
Dim type1 As Type = obj4.GetType
Dim obj2 As Object = type1.InvokeMember("Count", BindingFlags.GetProperty, Nothing, obj4, Nothing)
If (CInt(obj2) <> 0) Then
Dim num2 As Integer = (CInt(obj2) - 1)
Dim i As Integer = 0
Do While (i <= num2)
Dim obj5 As Object = type1.InvokeMember("Item", BindingFlags.InvokeMethod, Nothing, obj4, New Object() {i})
Dim type3 As Type = obj5.GetType
Dim str As String = CStr(type3.InvokeMember("Name", BindingFlags.GetProperty, Nothing, obj5, Nothing))
If (str = "File Explorer") Then
type3.InvokeMember("Refresh", BindingFlags.InvokeMethod, Nothing, obj5, Nothing)
End If
i += 1
Loop
End If
End Sub
Public Shared Sub NotifyFileAssociationChanged()
'Find the actual window...
Dim hwnd As IntPtr = FindWindow("Progman", "Program Manager")
'Get the window handle and refresh option...
Dim j = GetWindow(hwnd, 3)
'Finally post the message...
PostMessage(j, 256, KeyboardFlag.KEYBOARDF_5, 3)
End Sub
End Class
Here's a solution for everything excepting the refreshing of the explorer.
I've translated the code, but I'm unable to find how to refresh the explorer/desktop without restarting it.
Const keyName As String = "HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\Advanced"
Const Hidden As String = "Hidden"
Const SHidden As String = "ShowSuperHidden"
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Dim St As Integer = GetRegValue(Hidden)
If St = 2 Then
SetRegValue(Hidden, 1)
SetRegValue(SHidden, 1)
Else
SetRegValue(Hidden, 2)
SetRegValue(SHidden, 0)
End If
End Sub
Private Function GetRegValue(valueName As String) As Integer
Return CInt(My.Computer.Registry.GetValue(keyName, valueName, 0))
End Function
Private Sub SetRegValue(valueName As String, value As Integer)
My.Computer.Registry.SetValue(keyName, valueName, value, Microsoft.Win32.RegistryValueKind.DWord)
End Sub
I have a few ideas to refresh the desktop :
Send a key to a running process. I tried this (source) :
Dim pp As Process() = Process.GetProcessesByName("explorer")
If pp.Length > 0 Then
For Each p In pp
AppActivate(p.Id)
SendKeys.SendWait("{F5}")
Next
End If
Refresh using SHChangeNotify (source),
Refresh broadcasting a WM_SETTINGCHANGE message (source),
etc.
I think you'll be forced to manually refresh or restart the explorer.

Create a text file and write to it

I want to create a text file and write some text into this file, but my code cannot create the text file.
Error message:
UnauthorizedAccessExcepion was unhandled by user code
Access to the path 'c:\save.txt' is denied.
My code:
Dim fileLoc As String = "c:\save.txt"
Dim fs As FileStream = Nothing
If (Not File.Exists(fileLoc)) Then
fs = File.Create(fileLoc)
Using fs
End Using
End If
If File.Exists(fileLoc) Then
Using sw As StreamWriter = New StreamWriter(fileLoc)
a = "Test: " + TextBox1.Text
c = "=============================================="
sw.Write(a)
sw.Write(c)
End Using
End If
In more recent version of Windows, the root of the C: drive is read-only by default. Try putting the file in another folder.
If you're getting a little obsessive and want to write to the C drive directory directly, you can use this:
Imports System.Security.Principal
Module VistaSecurity
'Declare API
Private Declare Ansi Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Private Const BCM_FIRST As Int32 = &H1600
Private Const BCM_SETSHIELD As Int32 = (BCM_FIRST + &HC)
Public Function IsVistaOrHigher() As Boolean
Return Environment.OSVersion.Version.Major < 6
End Function
' Checks if the process is elevated
Public Function IsAdmin() As Boolean
Dim id As WindowsIdentity = WindowsIdentity.GetCurrent()
Dim p As WindowsPrincipal = New WindowsPrincipal(id)
Return p.IsInRole(WindowsBuiltInRole.Administrator)
End Function
' Add a shield icon to a button
Public Sub AddShieldToButton(ByRef b As Button)
b.FlatStyle = FlatStyle.System
SendMessage(b.Handle, BCM_SETSHIELD, 0, &HFFFFFFFF)
End Sub
' Restart the current process with administrator credentials
Public Sub RestartElevated()
Dim startInfo As ProcessStartInfo = New ProcessStartInfo()
startInfo.UseShellExecute = True
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.FileName = Application.ExecutablePath
startInfo.Verb = "runas"
Try
Dim p As Process = Process.Start(startInfo)
Catch ex As Exception
Return 'If cancelled, do nothing
End Try
Application.Exit()
End Sub
End Module

Getting file listings

I am wanting to retrieve all the files in some directories. Here is my original code:
Private Function Search(path As String, Recursive As Boolean) As Boolean
Dim dirInfo As New IO.DirectoryInfo(path)
Dim fileObject As FileSystemInfo
If Recursive = True Then
For Each fileObject In dirInfo.GetFileSystemInfos()
If fileObject.Attributes = FileAttributes.Directory Then
Search(fileObject.FullName, Recursive)
Else
lstFiles.Items.Add(fileObject.FullName)
End If
Next
Else
For Each fileObject In dirInfo.GetFileSystemInfos()
lstFiles.Items.Add(fileObject.FullName)
Next
End If
Return True
End Function
This code works well, yet it returns some directories and I am wanting to only return files.
I tried this code:
Private Sub Search(ByVal path As String, ByVal Recursive As Boolean)
if not Directory.Exists(path) then Exit Sub
Dim initDirInfo As New DirectoryInfo(path)
For Each oFileInfo In initDirInfo.GetFiles
lstfiles.items.add(oFileInfo.Name)
Next
If Recursive Then
For Each oDirInfo In initDirInfo.GetDirectories
Search(oDirInfo.FullName, True)
Next
End If
End Sub
However, i get the following error:
Access to the path 'C:\Users\Simon\AppData\Local\Application Data\' is denied.
Can someone help me with my original code, or help me access these directories with my new code?
thanks
EDIT:
I have added this module to get it working:
Imports System.Security.Principal
Module VistaSecurity
'Declare API
Private Declare Ansi Function SendMessage Lib "user32.dll" Alias "SendMessageA" (ByVal hwnd As Integer, ByVal wMsg As Integer, ByVal wParam As Integer, ByVal lParam As String) As Integer
Private Const BCM_FIRST As Int32 = &H1600
Private Const BCM_SETSHIELD As Int32 = (BCM_FIRST + &HC)
Public Function IsVistaOrHigher() As Boolean
Return Environment.OSVersion.Version.Major < 6
End Function
' Checks if the process is elevated
Public Function IsAdmin() As Boolean
Dim id As WindowsIdentity = WindowsIdentity.GetCurrent()
Dim p As WindowsPrincipal = New WindowsPrincipal(id)
Return p.IsInRole(WindowsBuiltInRole.Administrator)
End Function
' Add a shield icon to a button
Public Sub AddShieldToButton(ByRef b As Button)
b.FlatStyle = FlatStyle.System
SendMessage(b.Handle, BCM_SETSHIELD, 0, &HFFFFFFFF)
End Sub
' Restart the current process with administrator credentials
Public Sub RestartElevated()
Dim startInfo As ProcessStartInfo = New ProcessStartInfo()
startInfo.UseShellExecute = True
startInfo.WorkingDirectory = Environment.CurrentDirectory
startInfo.FileName = Application.ExecutablePath
startInfo.Verb = "runas"
Try
Dim p As Process = Process.Start(startInfo)
Catch ex As Exception
Return 'If cancelled, do nothing
End Try
Application.Exit()
End Sub
End Module
The access denied errors are occurring at Windows Libraries I think. I don't think there is any way to list the file in these libraries as they aren't actually folders.