If directory exists in a VB.NET code - vb.net

I have the following code to create a directory, the task accepts a recordcount and every time the recordcount reaches the required number, say 1000 records, a new directory is created. If the task is run a second time it will add another 1000 records to the existing directories, I want it to skip these existing directories and create a new one. I've tried adding various ifexists, but mess it up all the time, any help would be appreciated
Public Sub Main()
Dim SourceDirectory As String = "E:\Data"
Dim TargetDirectory As String = "E:\CN"
Dim FileExtensionsToProcess As String = "CON*.pdf"
Dim FileCounter As Integer = 0
Dim FolderName As Integer = 1
Dim recordcount As Integer
recordcount = CInt(Dts.Variables("RecordCount").Value)
For Each FileName As String In System.IO.Directory.GetFiles(SourceDirectory, FileExtensionsToProcess)
Dim FileOnly As String = System.IO.Path.GetFileName(FileName)
Try
If Not IO.Directory.Exists(IO.Path.Combine(TargetDirectory, FolderName.ToString())) Then
IO.Directory.CreateDirectory(IO.Path.Combine(TargetDirectory, FolderName.ToString()))
End If
IO.File.Move(FileName, IO.Path.Combine(TargetDirectory, IO.Path.Combine(FolderName.ToString(), FileOnly)))
Catch
End Try
FileCounter += 1
If (FileCounter Mod recordcount) = 0 Then
FolderName += 1
End If
Next
Dts.TaskResult = ScriptResults.Success
End Sub

Okay. The full solution is shown below and then I will explain some of it.
Public Sub Main()
Dim SourceDirectory As String = "E:\Data"
Dim TargetDirectory As String = "E:\CN"
Dim FileExtensionsToProcess As String = "CON*.pdf"
Dim FileCounter As Integer = 0
Dim FolderName As Integer = 1
Dim recordcount As Integer = CInt(Dts.Variables("RecordCount").Value)
Dim targetDir As String = SetOutputFolder(TargetDirectory, FolderName, recordcount)
For Each FileName As String In Directory.GetFiles(SourceDirectory, FileExtensionsToProcess)
Dim FileOnly As String = Path.GetFileName(FileName)
'Try - Leave this out to observe any exceptions, then add handling when you see any
' Check for file name conflicts before moving
File.Move(FileName, Path.Combine(targetDir, FileOnly))
'Catch
'End Try
FileCounter += 1
If FileCounter >= recordcount Then
FolderName += 1
targetDir = SetOutputFolder(TargetDirectory, FolderName, recordcount)
FileCounter = Directory.GetFiles(targetDir).Count
End If
Next
End Sub
Private Function SetOutputFolder(baseDir As String, ByRef folderName As Integer, ByRef recordCount As Integer) As String
Dim targetDir = Path.Combine(baseDir, folderName.ToString())
Dim filecounter = 0
While Directory.Exists(targetDir)
filecounter = Directory.GetFiles(targetDir).Count
If filecounter >= recordCount Then
folderName += 1
targetDir = Path.Combine(baseDir, folderName.ToString())
Else
Exit While
End If
End While
If Not Directory.Exists(targetDir) Then
Directory.CreateDirectory(targetDir)
End If
Return targetDir
End Function
The additional function I created solves a few problems. Note that it is passing the folder counter and the record count as references ByRef folderName As Integer, ByRef recordCount As Integer, so it can continue with correct values after getting the right directory. It will search for the target directory, starting at 1, and for each directory it finds it will check to see if it is full or not. If it is, then it will carry on, otherwise it will select that directory.
Within this it also checked if the directory exists and if not, creates it before exiting, this removes the extra If statements that are needed throughout and puts them in one place.

Related

get full string before first second third etc. split

I have a file location and I need to check if it exists.
The way I wan't to do it is like this:
Dim route As String = ("C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt")
If System.IO.File.Exists(route) Then
MsgBox("BESTAAT HET WERKT!")
Else
Dim subroute() As String = route.Split("\"c)
Dim counting As Integer = route.Split("\"c).Length - 1
For count2 As Integer = 0 To counting - 1
Dim firstbackslash As Integer = route.IndexOf("\")
Dim backslash As Integer = route.IndexOf("\", firstbackslash + 1)
Dim firstPart As String = route.Substring(0, backslash)
MsgBox(firstPart)
Next
What I try to accomplisch is that I fist check if folder "C:" exists then "C:\testing1" then "C:\testing1\testing2" etc.
But I cant find something like this on the internet nor with some messing around...
Here is an algorithm that that will give you all the paths starting from the root and building up to the final path including the filename. You can use this to check for each folder and create them as you go if they don't exist:
Sub Main()
Dim route As String = ("C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt")
Dim fi As New System.IO.FileInfo(route)
If Not fi.Exists Then
Dim fileName As String = Path.GetFileName(route)
Dim di As DirectoryInfo = fi.Directory
Dim pathStack As New Stack(Of String)()
pathStack.Push(di.Name)
While Not IsNothing(di.Parent)
di = di.Parent
pathStack.Push(di.Name)
End While
Dim curPath As String = ""
While pathStack.Count > 0
curPath = Path.Combine(curPath, pathStack.Pop)
' ... do something with "curPath" in here ...
' ... like check for existence and create it ...
Console.WriteLine(curPath)
End While
curPath = Path.Combine(curPath, fileName)
' ... do something with "curPath" in here ...
' ... this is the full path including the file on the end ...
Console.WriteLine(curPath)
End If
Console.Write("Press Enter to quit...")
Console.ReadLine()
End Sub
Output:
C:\
C:\testing1
C:\testing1\testing2
C:\testing1\testing2\testing3
C:\testing1\testing2\testing3\testing4
C:\testing1\testing2\testing3\testing4\testing5
C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt
Press Enter to quit...
Don't use string mnaipulation to work with file or folder paths. use the Path class.
One option:
Private Function GetExistingSubPath(fullPath As String) As String
If Directory.Exists(fullPath) OrElse File.Exists(fullPath) Then
Return fullPath
End If
Dim subPath = Path.GetDirectoryName(fullPath)
If subPath Is Nothing Then
Return Nothing
End If
Return GetExistingSubPath(subPath)
End Function
Sample usage:
Dim fullPath = "C:\testing1\testing2\testing3\testing4\testing5\TEXTBESTAND.txt"
Dim existingSubPath = GetExistingSubPath(fullPath)
Console.WriteLine(existingSubPath)
What I try to accomplisch is that I fist check if folder "C:" exists then "C:\testing1" then "C:\testing1\testing2" etc.
Noooooooooooo!
That's not how to do it at all! The file system is volatile: things can change between each of those checks. Moreover, file existence is only one of many things that can stop file access.
It's much better practice to try to access the file in question, and then handle the exception if it fails. Remember, because of the prior paragraph you have to be able to handle exceptions here anyway. .Exists() doesn't save you from writing that code. And each check is another round of disk access, which is about the slowest thing it's possible to do in a computer... even slower than unrolling the stack for an exception, which is the usual objection to this idea.
I fixed it, know I can check if multiple text files are at the locations I need, if there not I place the Textfiles at the location I need them. Then I can add something in it. (I need to put a Location of something else in it.)
Dim een As String = "C:\testing1\testing2\testing7\testing1\testing1\text.txt"
Dim twee As String = "C:\testing1\testing2\testing7\testing2\testing1\text.txt"
Dim drie As String = "C:\testing1\testing2\testing7\testing3\testing1\text.txt"
Dim vier As String = "C:\testing1\testing2\testing7\testing4\testing1\text.txt"
Dim Files As String() = {een, twee, drie, vier}
For Each route As String In Files
If System.IO.File.Exists(route) Then
MsgBox("BESTAAT HET WERKT!")
Else
Dim subroute() As String = route.Split("\"c)
Dim counting As Integer = route.Split("\"c).Length - 1
Dim tel As Integer = route.Substring(route.LastIndexOf("\") + 1).Count
Dim bestandnaam As String = route.Substring(route.LastIndexOf("\") + 1)
For count2 As Integer = 0 To route.Length - tel - 1
Dim firstbackslash As Integer = route.IndexOf("\", count2)
Dim backslash As Integer = route.IndexOf("\", count2)
Dim Mapnaam As String = route.Substring(0, backslash)
count2 = firstbackslash
If System.IO.Directory.Exists(Mapnaam) Then
Else
System.IO.Directory.CreateDirectory(Mapnaam)
End If
Next
If System.IO.File.Exists(route) Then
Else
Dim objStreamWriter As System.IO.StreamWriter
objStreamWriter = New System.IO.StreamWriter(route)
Dim label As String
Select Case route
Case een
label = "een"
Case twee
label = "twee"
Case drie
label = "drie"
Case vier
label = "vier"
End Select
Dim value As String = InputBox("Route invullen naar " & label)
'Dim objStreamWriter As New System.IO.StreamWriter(route)
objStreamWriter.Write(value)
objStreamWriter.Close()
'Using sw As System.IO.StreamWriter = System.IO.File.AppendText(route)
' sw.WriteLine(value)
'End Using
End If
End If
Next route

Get selected Appointment folder's email adress

I have two calendars, one is mine and the other is shared. Both are opened in outlook as below.
How can i get selected apointment calendar's email adress?
I saw AppointmentItem has GetOrganizer to find who created the appointment but I don't find any method or property about the user of the calendar in witch the appointment is...
So I tried Application.ActiveExplorer.CurrentFolder to get the selected folder and then get the AdressEntry but I can't get the folder's store because it's a shared calendar (and then folder.store returns null).
Following Dmitry's advices there, I did :
Dim appointment_item As Outlook.AppointmentItem
Dim PR_MAILBOX_OWNER_ENTRYID as String
Dim mapiFolder As Outlook.MAPIFolder
Dim folderStore As Outlook.Store
Dim mailOwnerEntryId As String
Dim entryAddress As Outlook.AddressEntry
Dim smtpAdress As String
PR_MAILBOX_OWNER_ENTRYID = "http://schemas.microsoft.com/mapi/proptag/0x661B0102"
appointment_item = Application.ActiveExplorer.Selection.Item(1)
mapiFolder = appointment_item.Parent
folderStore = mapiFolder.Store
mailOwnerEntryId = folderStore.PropertyAccessor.GetProperty(PR_MAILBOX_OWNER_ENTRYID)
entryAddress = Application.Session.GetAddressEntryFromID(mailOwnerEntryId)
smtpAdress = entryAddress.GetExchangeUser.PrimarySmtpAddress
MsgBox(smtpAdress)
The issue is i can't get .Store of a shared folder as written here in the MS Documentation.
This property returns a Store object except in the case where the Folder is a shared folder (returned by NameSpace.GetSharedDefaultFolder). In this case, one user has delegated access to a default folder to another user; a call to Folder.Store will return Null.
I finally found a way to do it, this topic helped me.
The code below, parses the shared folder storeID to get the shared folder SMTP address.
Public Sub test()
Dim smtpAddress As String
Dim selectedItem As Outlook.Folder
smtpAddress = ""
TryGetSmtpAddress(Application.ActiveExplorer.Selection.Item(1).Parent, smtpAddress)
End Sub
Public Shared Function TryGetSmtpAddress(ByVal folder As MAPIFolder, ByRef smtpAddress As String) As Boolean
smtpAddress = "default"
Dim storeId = HexToBytes(folder.StoreID)
If BitConverter.ToUInt64(storeId, 4) <> &H1A10E50510BBA138UL OrElse BitConverter.ToUInt64(storeId, 12) <> &HC2562A2B0008BBA1UL Then
Return False
End If
Dim indexDn = Array.IndexOf(storeId, CByte(&H0), 60) + 1
Dim indexV3Block = Array.IndexOf(storeId, CByte(&H0), indexDn) + 1
If BitConverter.ToUInt32(storeId, indexV3Block) <> &HF43246E9UL Then
Return False
End If
Dim offsetSmtpAddress = BitConverter.ToUInt32(storeId, indexV3Block + 12)
smtpAddress = BytesToUnicode(storeId, indexV3Block + CInt(offsetSmtpAddress))
Return True
End Function
Private Shared Function HexToBytes(ByVal input As String) As Byte()
Dim bytesLength = input.Length / 2
Dim bytes = New Byte(bytesLength - 1) {}
For i = 0 To bytesLength - 1
bytes(i) = Convert.ToByte(input.Substring(i * 2, 2), 16)
Next
Return bytes
End Function
Private Shared Function BytesToUnicode(ByVal value As Byte(), ByVal startIndex As Integer) As String
Dim charsLength = (value.Length - startIndex) / 2
Dim chars = New Char(charsLength - 1) {}
For i = 0 To charsLength - 1
Dim c = CSharpImpl.__Assign(chars(i), BitConverter.ToChar(value, startIndex + i * 2))
If c = vbNullChar Then
Return New String(chars, 0, i)
End If
Next
Return New String(chars)
End Function
Private Class CSharpImpl
<Obsolete("Please refactor calling code to use normal Visual Basic assignment")>
Shared Function __Assign(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
End Class
It may be possible to get to the top of the folder tree of a shared calendar the long way, without built-in shortcuts.
Tested on my own calendar, not a shared calendar.
Option Explicit
Sub appointment_sourceFolder()
' VBA code
Dim obj_item As Object
Dim appointment_item As AppointmentItem
Dim parentOfAppointment As Variant
Dim parentParentFolder As Folder
Dim sourceFolder As Folder
Set obj_item = ActiveExplorer.Selection.Item(1)
If obj_item.Class <> olAppointment Then Exit Sub
Set appointment_item = obj_item
' Recurring appointment leads to
' the parent of the recurring appointment item then the calendar folder.
' Single appointment leads to
' the calendar folder then the mailbox name.
Set parentOfAppointment = appointment_item.Parent
Set parentParentFolder = parentOfAppointment.Parent
Debug.Print vbCr & " parentParentFolder: " & parentParentFolder.Name
Set sourceFolder = parentParentFolder
' Error bypass for a specific purpose
On Error Resume Next
' If parentParentFolder is the shared calendar,
' walking up one folder is the mailbox.
' If parentParentFolder is the mailbox,
' walking up one folder is an error that is bypassed,
' so no change in sourceFolder.
' Assumption:
' The shared calendar is directly under the mailbox
' otherwise add more Set sourceFolder = sourceFolder.Parent
Set sourceFolder = sourceFolder.Parent
' Return to normal error handling immediately
On Error GoTo 0
Debug.Print " sourceFolder should be smtp address: " & sourceFolder
'MsgBox " sourceFolder should be smtp address: " & sourceFolder
End Sub

Parse String to Date from a filename variable

Purpose is to move files in their specified folders, from which they were in IF the date is at least a day old from today. I'm having some trouble moving the file since I don't see it archived. I'm assuming it's parsing the date from a filename. VS2005 .Net 2.0
Sub CopytoArchive(ByVal mydirpath)
'mydirpath = "C:\UTResults\"
'T:\UTResults\Press3\sv70206655\data07012015.txt is an example of txtFileList
Dim txtFileList As String() = Directory.GetFiles(mydirpath, "*.txt", SearchOption.AllDirectories) 'Search all files in the given path with .txt type
For Each txtName As String In txtFileList
Dim pressname As String = txtName.Substring(0, txtName.LastIndexOf("\")) 'take out the file extension
pressname = pressname.Substring(0, pressname.LastIndexOf("\")) 'take out the folder after the press folder for a clean "PRESS" look
pressname = pressname.Remove(0, 13)
Dim folderexists As String = Path.Combine("C:\writetest\", pressname)
Dim filename = txtName.Remove(0, 4)
filename = filename.Substring(0, filename.LastIndexOf("."))
filename = Convert.ToDateTime(filename)
If filename < Date.Now Then
If My.Computer.FileSystem.DirectoryExists(folderexists) Then
My.Computer.FileSystem.MoveFile(txtName, folderexists)
Else
My.Computer.FileSystem.CreateDirectory(folderexists)
My.Computer.FileSystem.MoveFile(txtName, folderexists)
End If
End If
Next
End Sub
Sub CopytoArchive(ByVal mydirpath As String)
'mydirpath = "C:\UTResults\"
'T:\UTResults\Press3\sv70206655\data07012015.txt is an example of txtFileList
Dim dir As New DirectoryInfo(mydirpath)
Dim fileInfos = dir.EnumerateFiles("*.txt", SearchOption.AllDirectories)
fileInfos = fileInfos.
Where(Function(fi) DateTime.ParseExact(RegEx.Replace(fi.Name, "[^0-9]", ""), "MMddyyyy", Nothing) < DateTime.Now.AddDays(-1))
'The magic is here ------^^^
For Each info In fileInfos
Dim pressname As String = _
Path.GetDirectoryName(info.DirectoryName).Replace(mydirpath, "C:\writetest\")
'Better/more efficient to just call CreateDirectory() every time
My.Computer.FileSystem.CreateDirectory(pressname)
My.Computer.FileSystem.MoveFile(info.FullName, pressname)
Next
End Sub
Date strings are usually a problem, here is basic approach:
Dim s As String = "data07012015.txt"
s = s.Substring(4)
s = s.Substring(0, s.LastIndexOf("."))
' convert to valid en date string
s = s.Insert(2, "/").Insert(5, "/")
Dim dt As Date = s
If dt < Now.AddDays(-1) Then
Stop
Else
Stop
End If

Unhide all hidden files, folders, subfolders and subfiles except access denied path using Visual Basic

My code below albe to Unhide all hidden files, folders, subfolders and subfiles. The problem is it'll stop if any access denied path. How to make the code skip access denied path and continue with other paths.
Dim MyDrive As String = "D:\"
Dim FileCounter As Integer = 0
Dim FolderCounter As Integer = 0
Dim DriveObj As New IO.DirectoryInfo(MyDrive)
Dim Files As IO.FileInfo() = DriveObj.GetFiles("*.*", IO.SearchOption.AllDirectories)
Dim Directories As IO.DirectoryInfo() = DriveObj.GetDirectories("*.*", IO.SearchOption.AllDirectories)
Dim Filename As IO.FileSystemInfo
For Each Filename In Files
On Error Resume Next
If (IO.File.GetAttributes(Filename.FullName) And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
' Show the file.
IO.File.SetAttributes(Filename.FullName, IO.FileAttributes.Normal)
FileCounter = FileCounter + 1
End If
Next
Dim DirectoryName As IO.DirectoryInfo
For Each DirectoryName In Directories
On Error Resume Next
If (IO.File.GetAttributes(DirectoryName.FullName) And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
' Show the folder.
IO.File.SetAttributes(DirectoryName.FullName, IO.FileAttributes.Normal)
FolderCounter = FolderCounter + 1
End If
Next
When I was testing code, I realised that DriveObj.GetFiles(...) and DriveObj.GetDirectories(...) are stopping when access is denied, not For loops. To fix that, you have to use recursive file and directory listing.
Private Function GetFilesRecursive(ByVal initial As String) As List(Of String)
' This list stores the results.
Dim result As New List(Of String)
' This stack stores the directories to process.
Dim stack As New Stack(Of String)
' Add the initial directory
stack.Push(initial)
' Continue processing for each stacked directory
Do While (stack.Count > 0)
' Get top directory string
Dim dir As String = stack.Pop
Try
' Add all immediate file paths
result.AddRange(Directory.GetFiles(dir, "*.*"))
' Loop through all subdirectories and add them to the stack.
Dim directoryName As String
For Each directoryName In Directory.GetDirectories(dir)
stack.Push(directoryName)
Next
Catch ex As Exception
End Try
Loop
' Return the list
Return result
End Function
Private Function GetDirectoriesRecursive(ByVal initial As String) As List(Of String)
' This list stores the results.
Dim result As New List(Of String)
' This stack stores the directories to process.
Dim stack As New Stack(Of String)
' Add the initial directory
stack.Push(initial)
' Continue processing for each stacked directory
Do While (stack.Count > 0)
' Get top directory string
Dim dir As String = stack.Pop
Try
' Add all immediate file paths
result.AddRange(Directory.GetDirectories(dir, "*.*"))
' Loop through all subdirectories and add them to the stack.
Dim directoryName As String
For Each directoryName In Directory.GetDirectories(dir)
stack.Push(directoryName)
Next
Catch ex As Exception
End Try
Loop
' Return the list
Return result
End Function
Private Sub Unhide()
Dim MyDrive As String = "D:\"
Dim FileCounter As Integer = 0
Dim FolderCounter As Integer = 0
Dim Files As List(Of String) = GetFilesRecursive(MyDrive)
Dim Directories As List(Of String) = GetDirectoriesRecursive(MyDrive)
For Each Filename In Files
If (IO.File.GetAttributes(Filename) And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
'Show the file.
IO.File.SetAttributes(Filename, IO.FileAttributes.Normal)
FileCounter = FileCounter + 1
End If
Next
For Each DirectoryName In Directories
If (IO.File.GetAttributes(DirectoryName) And IO.FileAttributes.Hidden) = IO.FileAttributes.Hidden Then
'Show the folder.
IO.File.SetAttributes(DirectoryName, IO.FileAttributes.Normal)
FolderCounter = FolderCounter + 1
End If
Next
End Sub

vb.net select random folder name

Dose anybody know how I can select an existing random directory name (C:\ drive) using vb.net and store its location in a variable.
I had to googel this one but seem to only be able to find example in relation to files, not folders
Try this out, hope this will suits your requirement,
'----------------- Global Variables
Dim xCnter = 0
Dim xRndNo = 0
Dim xSubdirectory As String
Private Sub Basement()
Dim xGenerator As System.Random = New System.Random()
xRndNo = xGenerator.Next(1, 100)
AssignRndDirectory("C:\")
msgbox(subdirectory)
End Sub
Private Sub AssignRndDirectory(xPath as string)
For Each subdirectory In Directory.GetDirectories(xPath)
if xCnter = xRndNo then Exit sub
xCnter += 1
call AssignRndDirectory(subdirectory)
Next
End Sub
[Note: This code is not tested with IDE, Tell me if anything cause errors.]
EDIT: TESTED WITH IDE
Dim xCnter = 0
Dim xRndNo = 0
Dim xSubdirectory As String
Private Sub Basement()
Dim xGenerator As System.Random = New System.Random()
xRndNo = xGenerator.Next(1, 100)
AssignRndDirectory("C:\")
MsgBox(xSubdirectory)
xCnter = 0
End Sub
Private Sub AssignRndDirectory(ByVal xPath As String)
Try
For Each Subdirectory In Directory.GetDirectories(xPath)
If xCnter = xRndNo Then Exit Sub
xSubdirectory = Subdirectory
xCnter += 1
Call AssignRndDirectory(Subdirectory)
Next
Catch ex As Exception
Exit Sub
End Try
End Sub
Just make a list of directories, and select a random item from it.
Dim rnd As New Random()
Dim path As String = "C:\"
Dim dir = New DirectoryInfo(path)
Dim subDirs = dir.GetDirectories()
Dim randomDir = subdirs(rnd.[Next](subDirs.Length))
Or, if you prefer Linq, the last line can be:
Dim randomDirectory = subdirs.Skip(rnd.[Next](subdirs.Length)).First()