File Icons and List view - vb.net

How to retrieve file icons associated with the file types and add them with the items of Listview in vb.net
I read about SHGetFileInfo but I didn't understand anything from that
please give me solution or please explain me ho system works with the .net controls in details

Having looked up SHGetFileInfo I can see why you're confused by it, but I think it might be slightly overkill for what I think you're trying to do i.e. enumerating the contents of a folder and adding items to the Listview.
If we have a form that contains a ListView and an ImageList, with the two related by having the ListView's LargeImageList property set to the ImageList, then here's how we put the contents of a folder into the ListView with the icons coming from the associated EXE file for each file.
Imports System.IO
Imports System.Drawing
Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
Dim dirInfo As DirectoryInfo
Dim fileInfo As FileInfo
Dim exePath As String
Dim exeIcon As Icon
dirInfo = New DirectoryInfo(path_to_some_folder
'We use this For...Each to iterate over the collection of files in the folder
For Each fileInfo In dirInfo.GetFiles
'We can only find associated exes by extension, so don't show any files that have no extension
If fileInfo.Extension = String.Empty Then
Else
'Use the function to get the path to the executable for the file
exePath = GetAssociatedProgram(fileInfo.Extension)
'Use ExtractAssociatedIcon to get an icon from the path
exeIcon = Drawing.Icon.ExtractAssociatedIcon(exePath)
'Add the icon if we haven't got it already, with the executable path as the key
If ImageList1.Images.ContainsKey(exePath) Then
Else
ImageList1.Images.Add(exePath, exeIcon)
End If
'Add the file to the ListView, with the executable path as the key to the ImageList's image
ListView1.Items.Add(fileInfo.Name, exePath)
End If
Next
End Sub
GetAssociatedProgram comes from developer.com
Public Function GetAssociatedProgram(ByVal FileExtension As _
String) As String
' Returns the application associated with the specified
' FileExtension
' ie, path\denenv.exe for "VB" files
Dim objExtReg As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.ClassesRoot
Dim objAppReg As Microsoft.Win32.RegistryKey = _
Microsoft.Win32.Registry.ClassesRoot
Dim strExtValue As String
Try
' Add trailing period if doesn't exist
If FileExtension.Substring(0, 1) <> "." Then _
FileExtension = "." & FileExtension
' Open registry areas containing launching app details
objExtReg = objExtReg.OpenSubKey(FileExtension.Trim)
strExtValue = objExtReg.GetValue("").ToString
objAppReg = objAppReg.OpenSubKey(strExtValue & _
"\shell\open\command")
' Parse out, tidy up and return result
Dim SplitArray() As String
SplitArray = Split(objAppReg.GetValue(Nothing).ToString, """")
If SplitArray(0).Trim.Length > 0 Then
Return SplitArray(0).Replace("%1", "")
Else
Return SplitArray(1).Replace("%1", "")
End If
Catch
Return ""
End Try
End Function
At the end of all of that, when you run this code on this folder:
alt text http://www.philippursglove.com/stackoverflow/listview1.png
you should get:
alt text http://www.philippursglove.com/stackoverflow/listview2.png

If you know the file name of the file whose icon you want, you can use the System.Drawing.Icon.ExtractAssociatedIcon function for that purpose. e.g.
Icon ico = System.Drawing.Icon.ExtractAssociatedIcon(#"C:\WINDOWS\system32\notepad.exe");
You can also refer to my answer to a related question for more implementation details.

Related

Iterate through a directory to get subfolders and certain files

I am working on a program that will move files to a database, text files to be exact. The user will have a starting directory and inside will multiple sub folders and files and so on. I want to go through each Folder and sub folder looking for the text files and add them accordingly to the database so it resembles a directory structure in a way. In the program the files are organized such as the folders are "Categories" that are displayed into a tree view.I am only adding the folder names(as Categories) that do contain text files and their subs and so forth. As well I need to figure out where to plug in the adding of the "Category". As of right now I am using a couple of listboxes for my output until I can get it all figured out.
lstfiles.Items.Add(Dir)
For Each file In System.IO.Directory.GetFiles(Dir)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
AddFile(file, Gennumber(9999))
End If
End If
Next
For Each folder In System.IO.Directory.GetDirectories(Dir)
lstfiles.Items.Add(folder)
For Each file In System.IO.Directory.GetFiles(folder)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
End If
End If
Next
Next
I have gotten so far as to iterate through the directory and get files but it returns folders that are empty. And I need to figure out where I need to put in my addcategory function. And also remember the last one that was added so they can be added as a subcategory.
I think I am making a big mess of it all, or over thinking the whole thing.
Any assistance or guidance would be appreciated.Thank you
The end result that I came up with was much different from my original posting, as it was my way of thinking of how it was going to work. I split up the two main functions. Retrieving the Folders and retrieving the files.
DirEx is the Import Directory, CatID is the Tag of the selected Treenode where the folders are going to added in.
Private Sub DirImport_GetSubDirectories(ByVal DirEx As String, ByVal CatID As Integer)
Try
Dim ClsData As New clsNoteData
'Set the DatabaseFile Property of the class
ClsData.Database = LoadedLibraryDatabase
' Get all subdirectories
Dim subdirectoryEntries() As String = Directory.GetDirectories(DirEx)
' Loop through them to see if they have any other subdirectories
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
'If the Directory is not Empty
If Not Directory.GetFileSystemEntries(subdirectory).Length = 0 Then
Dim di As DirectoryInfo = New DirectoryInfo(subdirectory)
'Creating Random Number
Dim NewCatID As Integer = GenNumber(9999)
'Call for a new Sub Category
ClsData.NewSubCategoryNode(LoadedLibraryDatabase, NewCatID, CatID, di.Name, -1)
'Get files in the current Directory
DirImport_GetFiles(subdirectory, NewCatID)
'Get the next set of Subfolders
DirImport_GetSubDirectories(subdirectory, NewCatID)
End If
Next
Catch ex As Exception
End Try
End Sub
Private Sub DirImport_GetFiles(ByVal DirEx As String, ByVal CatID As Integer)
Dim Files() As String = Directory.GetFiles(DirEx, "*.txt")
Dim file As String
For Each file In Files
Dim clsNoteData As New clsNoteData
Dim fi As FileInfo = New FileInfo(file)
clsNoteData.Database = LoadedLibraryDatabase
clsNoteData.NewNote_ID = GenNumber(99999)
clsNoteData.NewNote_CatID = CatID
clsNoteData.NewNote_Title = Path.GetFileNameWithoutExtension(file)
clsNoteData.NewNote(False, file)
Next
End sub
So here it is for anyone who may want to do something similar.

Moving Files From One Folder To Another VB.Net

I am trying to figure out how to move 5 files
settings.txt
settings2.txt
settings3.txt
settings4.txt
settings5.txt
from one folder to another.
Although I know what the file names will be and what folder Name they will be in, I don't know where that folder will be on the Users computer.
My thought process is to use a FolderBrowseDialog which the user can browse to where the Folder is, and then when OK is pressed, it will perform the File copy to the destination folder, overwriting what's there.
This is what I have so far.
Dim FolderPath As String
Dim result As Windows.Forms.DialogResult = FolderBrowserImport.ShowDialog()
If result = DialogResult.OK Then
FolderPath = FolderBrowserImport.SelectedPath & "\"
My.Computer.FileSystem.CopyFile(
FolderPath & "settings.txt", "c:\test\settings.txt", overwrite:=True)
ElseIf result = DialogResult.Cancel Then
Exit Sub
End If
Rather than run this 5 times, is there a way where it can copy all 5 files at once
I know why IdleMind recommended the approach they did, but it would probably make for a bit more readable code to just list out the file names:
Imports System.IO
...
Dim result = FolderBrowserImport.ShowDialog()
If result <> DialogResult.OK Then Exit Sub
For Each s as String in {"settings.txt", "settings2.txt", "settings3.txt", "settings4.txt", "settings5.txt" }
File.Copy( _
Path.Combine(FolderBrowserImport.SelectedPath, s), _
Path.Combine("c:\test", s), _
True _
)
Next s
You can swap this fixed array out for a list that VB prepares for you:
For Each s as String in Directory.GetFiles(FolderBrowserImport.SelectedPath, "settings*.txt", SearchOption.TopDirectoryOnly)
File.Copy(s, Path.Combine("c:\test", Path.GetFilename(s)), True)
Next s
Tips:
It's usually cleaner to do a If bad Then Exit Sub than a If good Then (big load of indented code) End If - test all your known failure conditions at the start and exit the sub if anything fails, rather than arranging a huge amount of indented code
Use Path.Combine to combine path and filenames etc; it knows how to deal with stray \ characters
Use Imports to import namespaces rather than spelling everything out all the time (System.Windows.Forms.DialogResult - a winforms app will probably have all the necessaries imported already in the partial class so you can just say DialogResult. If you get a red wiggly line, point to the adjacent lightbulb and choose to import System.WIndows/Forms etc)
Once you have the selected folder, use a For loop to build up the names of the files you're looking for. Use System.IO.File.Exists() to see if they are there. Use System.IO.Path.Combine() to properly combine your folders with the filenames.
Here's a full example (without exception handling, which should be added):
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
If FolderBrowserImport.ShowDialog() = DialogResult.OK Then
Dim FolderPath As String = FolderBrowserImport.SelectedPath
For i As Integer = 1 To 5
Dim FileName As String = "settings" & If(i = 1, "", i) & ".txt"
Dim FullPathFileName As String = System.IO.Path.Combine(FolderPath, FileName)
If System.IO.File.Exists(FullPathFileName) Then
Dim DestinationFullPathFileName = System.IO.Path.Combine("c:\test", FileName)
My.Computer.FileSystem.CopyFile(FullPathFileName, DestinationFullPathFileName, True)
Else
' possibly do something in here if the file does not exist?
MessageBox.Show("File not found: " & FullPathFileName)
End If
Next
End If
End Sub

How to read files in folders?

I am trying to get my application to check for folders in the folderbrowserdialogs selectedpath and then get those files, but it doesn't work I have tried both listed ways below. The second way gives me an error: (Expression is of type char which is not a collection type)
For Each folder In FileBrowserDialog.SelectedPath
Dim counter As _
System.Collections.ObjectModel.ReadOnlyCollection(Of String)
counter = My.Computer.FileSystem.GetFiles(folder)
Label1.Text = counter.Count.ToString
Next
For Each folder In FileBrowserDialog.SelectedPath
Dim counter As _
System.Collections.ObjectModel.ReadOnlyCollection(Of String)
For Each foundfile In folder
counter = My.Computer.FileSystem.GetFiles(foundfile)
Label1.Text = counter.Count.ToString
Next
Any help is appreciated.
FolderBrowserDialog1.SelectedPath will return the path the user selected in the dialog. You still need to write code to go get the files. There may not be a need to get the folders and then files in them. Net has ways to do that for you:
FolderBrowserDialog1.ShowDialog()
Dim myPath As String = FolderBrowserDialog1.SelectedPath
' get all files for a folder
Dim files = Directory.GetFiles(myPath)
' get all files for all sub folders
Dim files = Directory.GetFiles(myPath, "*.*",
System.IO.SearchOption.AllDirectories)
' get certain file types for folder and subs
Dim files = Directory.GetFiles(myPath, "*.jpg",
System.IO.SearchOption.AllDirectories)
You also are not going to be able to simply assign the results to a ReadOnlyCollection like that, because they are ReadOnly. The collection needs to be created/instanced with the complete list:
Dim counter As new ReadOnlyCollection(Of String)(files)

Open, Launch or Show a file for the user to read or write in vb.net

It sounds very simple but I have searched and cannot seem to find a way to open a log file which the user just created from my windows form app. The file exits I just want to open it after it is created.
I have a Dim path As String = TextBox1.Text and once the user names and clicks ok on the savefiledialog I have a msgbox that says "Done" and when you hit OK I have tried this
FileOpen(FreeFile, path, OpenMode.Input) but nothing happens. I just want it to open the log and show it to the user so they can edit or save it again or anything.
This is where I got the above code.
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.filesystem.fileopen.aspx
Searching is difficult because everyone is trying to "Open" a file and process it during runtime. I am just trying to Show a file by Launching it like someone just double clicked it.
Here is the entire Export Button click Sub. It basically writes listbox items to file.
Private Sub btnExport_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnExport.Click
Dim sfd As New SaveFileDialog
Dim path As String = TextBox1.Text
Dim arypath() As String = Split(TextBox1.Text, "\")
Dim pathDate As String
Dim foldername As String
foldername = arypath(arypath.Length - 1)
pathDate = Now.ToString("yyyy-MM-dd") & "_" & Now.ToString("hh;mm")
sfd.FileName = "FileScannerResults " & Chr(39) & foldername & Chr(39) & " " & pathDate
sfd.InitialDirectory = Environment.GetFolderPath(Environment.SpecialFolder.Personal)
sfd.Filter = "Text files (*.txt)|*.txt|CSV Files (*.csv)|*.csv"
sfd.ShowDialog()
path = sfd.FileName
Using SW As New IO.StreamWriter(path)
If CkbxFolder.Checked = True Then
SW.WriteLine("Folders")
For Each itm As String In ListBox1.Items
SW.WriteLine(itm)
Next
End If
If CkbxFiles.Checked = True Then
SW.WriteLine("Files")
For Each itm As String In ListBox2.Items
SW.WriteLine(itm)
Next
End If
End Using
MsgBox("Done...")
FileOpen(FreeFile, path, OpenMode.Input) 'Why can't I open a file for you...
End Sub
Do not use the old VB6 methods. They are still here for compatibility reason, the new code should use the more powerful methods in the System.IO namespace.
However, as said in comments, FileOpen don't show anything for you, just opens the file
You coud write
Using sr = new StreamReader(path)
Dim line = sr.ReadLine()
if !string.IsNullOrEmpty(line) Then
textBoxForLog.AppendText(line)
End If
End Using
or simply (if the file is not too big)
Dim myLogText = File.ReadAllText(path)
textBoxForLog.Text = myLogText
As alternative, you could ask the operating system to run the program associated with the file extension and show the file for you
Process.Start(path)
To get the same behavior as if the user double-clicked it, just use System.Diagnostics.Process, and pass the filename to it's Start method:
Process.Start(path)
This will open the file using whatever the default application is for that filename based on its extension, just like Explorer does when you double-click it.

Extracting Filename and Path from a running process

I'm writing a screen capture application for a client. The capture part is fine, but he wants to get the name and path of the file that the capture is of.
Using system.diagnostics.process I am able to get the process that the capture is of, and can get the full path of the EXE, but not the file that is open.
ie. Notepad is open with 'TextFile1.txt' as its document. I can get from the process the MainWindowTitle which would be 'TextFile1.txt - Notepad' but what I need is more like 'c:\users....\TextFile1.txt'
Is there a way of getting more information from the process?
I'm sure there is a way, but I can't figure it out
Any help greatly appreciated.
You can use ManagementObjectSearcher to get the command line arguments for a process, and in this notepad example, you can parse out the file name. Here's a simple console app example that writes out the full path and file name of all open files in notepad..
Imports System
Imports System.ComponentModel
Imports System.Management
Module Module1
Sub Main()
Dim cl() As String
For Each p As Process In Process.GetProcessesByName("notepad")
Try
Using searcher As New ManagementObjectSearcher("SELECT CommandLine FROM Win32_Process WHERE ProcessId = " & p.Id)
For Each mgmtObj As ManagementObject In searcher.Get()
cl = mgmtObj.Item("CommandLine").ToString().Split("""")
Console.WriteLine(cl(cl.Length - 1))
Next
End Using
Catch ex As Win32Exception
'handle error
End Try
Next
System.Threading.Thread.Sleep(1000000)
End Sub
End Module
I had to add a reference to this specific dll:
C:\WINDOWS\Microsoft.NET\Framework\v2.0.50727\System.Managment.dll
i think it is the simplest way
For Each prog As Process In Process.GetProcesses
If prog.ProcessName = "notepad" Then
ListBox1.Items.Add(prog.ProcessName)
End If
Next
I know this post is old, but since I've searched for this two days ago, I'm sure others would be interested. My code below will get you the file paths from Notepad, Wordpad, Excel, Microsoft Word, PowerPoint, Publisher, Inkscape, and any other text or graphic editor's process, as long as the filename and extension is in the title bar of the opened window.
Instead of searching, it obtains the file's target path from Windows' hidden Recent Items directory, which logs recently opened and saved files as shortcuts. I discovered this hidden directory in Windows 7. You're gonna have to check if Windows 10 or 11 has this:
C:\Users\ "username" \AppData\Roaming\Microsoft\Windows\Recent
I slapped this code together under Framework 4, running as 64bit. The COM dlls that must be referenced in order for the code to work are Microsoft Word 14.0 Object Library, Microsoft Excel 14.0 Object Library, Microsoft PowerPoint 14.0 Object Library, and Microsoft Shell Controls And Automation.
For testing, the code below needs a textbox, a listbox, a button, and 3 labels (Label1, FilenameLabel, Filepath).
Once you have this working, after submitting a process name, you will have to click the filename item in the ListBox to start the function to retrieve it's directory path.
Option Strict On
Option Explicit On
Imports System.Runtime.InteropServices
Imports Microsoft.Office.Interop.Excel
Imports Microsoft.Office.Interop.Word
Imports Microsoft.Office.Interop.PowerPoint
Imports Shell32
Public Class Form1
'function gets names of all opened Excel workbooks, adding them to the ListBox
Public Shared Function ExcelProcess(ByVal strings As String) As String
Dim Excel As Microsoft.Office.Interop.Excel.Application = CType(Marshal.GetActiveObject("Excel.Application"), Microsoft.Office.Interop.Excel.Application)
For Each Workbook As Microsoft.Office.Interop.Excel.Workbook In Excel.Workbooks
Form1.ListBox1.Items.Add(Workbook.Name.ToString() & " - " & Form1.TextBox1.Text)
Next
Return strings
End Function
'function gets names of all opened Word documents, adding them to the ListBox
Public Shared Function WordProcess(ByVal strings As String) As String
Dim Word As Microsoft.Office.Interop.Word.Application = CType(Marshal.GetActiveObject("Word.Application"), Microsoft.Office.Interop.Word.Application)
For Each Document As Microsoft.Office.Interop.Word.Document In Word.Documents
Form1.ListBox1.Items.Add(Document.Name.ToString() & " - " & Form1.TextBox1.Text)
Next
Return strings
End Function
'function gets names of all opened PowerPoint presentations, adding them to the ListBox
Public Shared Function PowerPointProcess(ByVal strings As String) As String
Dim PowerPoint As Microsoft.Office.Interop.PowerPoint.Application = CType(Marshal.GetActiveObject("PowerPoint.Application"), Microsoft.Office.Interop.PowerPoint.Application)
For Each Presentation As Microsoft.Office.Interop.PowerPoint.Presentation In PowerPoint.Presentations
Form1.ListBox1.Items.Add(Presentation.Name.ToString() & " - " & Form1.TextBox1.Text)
Next
Return strings
End Function
Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
'clears listbox to prepare for new process items
ListBox1.Items.Clear()
'gets process title from TextBox1
Dim ProcessName As String = TextBox1.Text
'prepare string's case format for
ProcessName = ProcessName.ToLower
'corrects Office process names
If ProcessName = "microsoft excel" Then
ProcessName = "excel"
Else
If ProcessName = "word" Or ProcessName = "microsoft word" Then
ProcessName = "winword"
Else
If ProcessName = "powerpoint" Or ProcessName = "microsoft powerpoint" Then
ProcessName = "powerpnt"
Else
End If
End If
End If
'get processes by name (finds only one instance of Excel or Microsoft Word)
Dim proclist() As Process = Process.GetProcessesByName(ProcessName)
'adds window titles of all processes to a ListBox
For Each prs As Process In proclist
If ProcessName = "excel" Then
'calls function to add all Excel process instances' workbook names to the ListBox
ExcelProcess(ProcessName)
Else
If ProcessName = "winword" Then
'calls function to add all Word process instances' document names to the ListBox
WordProcess(ProcessName)
Else
If ProcessName = "powerpnt" Then
'calls function to add all Word process instances' document names to the ListBox
PowerPointProcess(ProcessName)
Else
'adds all Notepad or Wordpad process instances' filenames
ListBox1.Items.Add(prs.MainWindowTitle)
End If
End If
End If
Next
End Sub
Private Sub ListBox1_MouseClick(ByVal sender As Object, ByVal e As System.Windows.Forms.MouseEventArgs) Handles ListBox1.MouseClick
Try
'add ListBox item (full window title) to string
Dim ListBoxSelection As String = String.Join(Environment.NewLine, ListBox1.SelectedItems.Cast(Of String).ToArray)
'get full process title after "-" from ListBoxSelection
Dim GetProcessTitle As String = ListBoxSelection.Split("-"c).Last()
'create string to remove from ListBoxSelection
Dim Remove As String = " - " & GetProcessTitle
'Extract filename from ListBoxSelection string, minus process full name
Dim Filename As String = ListBoxSelection.Substring(0, ListBoxSelection.Length - Remove.Length + 1)
'display filename
FilenameLabel.Text = "Filename: " & Filename
'for every file opened and saved via savefiledialogs and openfiledialogs in editing software
'Microsoft Windows always creates and modifies shortcuts of them in Recent Items directory:
'C:\Users\ "Username" \AppData\Roaming\Microsoft\Windows\Recent
'so the below function gets the target path from files's shortcuts Windows created
FilePathLabel.Text = "File Path: " & GetLnkTarget("C:\Users\" & Environment.UserName & "\AppData\Roaming\Microsoft\Windows\Recent\" & Filename & ".lnk")
Catch ex As Exception
'no file path to show if nothing was saved yet
FilePathLabel.Text = "File Path: Not saved yet."
End Try
End Sub
'gets file's shortcut's target path
Public Shared Function GetLnkTarget(ByVal lnkPath As String) As String
Dim shl = New Shell32.Shell()
lnkPath = System.IO.Path.GetFullPath(lnkPath)
Dim dir = shl.NameSpace(System.IO.Path.GetDirectoryName(lnkPath))
Dim itm = dir.Items().Item(System.IO.Path.GetFileName(lnkPath))
Dim lnk = DirectCast(itm.GetLink, Shell32.ShellLinkObject)
Return lnk.Target.Path
End Function
End Class