Identify some files in Specialized.StringCollection - vb.net

I read the *.fileExt files using:
Dim tempList As New Specialized.StringCollection
         tempList.AddRange(My.Computer.FileSystem.GetFiles(path, subFolders, "*" & fileExt).ToArray)
When processing I find some files that were deleted and are invisible from the file explorer but that are read by .GetFiles, they have their original name preceded by: "~$"
Example: "C:.......\~$OriginalFileName.fileExt"
I tried to exclude files that have "~$" at the beginning of the name, but it's not a good solution since I can create and save a file with "~$" at the beginning of the name, then the code would avoid a file that was never deleted.
I want to continue using .AddRange and exclude deleted files, I see two options:
Prevent .GetFiles from taking those files.
Identify them in tempList to avoid processing them.
I can't get any of the two to work.
I guess there is a simple way to identify if a file is deleted or not... an attribute or flag that identifies it as "deleted"... but I don't know how to do it. It's possible? How I should proceed?

Some programs create a backup file while a file is being edited, and those files are named starting with "~$" and have the hidden attribute set. Sometimes those files get orphaned, perhaps because of a program crash, but you don't notice them because they are hidden.
To avoid getting hidden files, you can select only files which do not have the hidden attribute, something like this:
Option Strict On
Option Infer On
Imports System.IO
Module Module1
Sub Main()
Dim srcDir = "C:\temp\testfiles"
Dim fileExt = ".txt"
Dim tempList As New Specialized.StringCollection()
Dim selectedFiles = (New DirectoryInfo(srcDir)).GetFileSystemInfos("*" & fileExt).
Where(Function(fi) Not (fi.Attributes And FileAttributes.Hidden) = FileAttributes.Hidden).
Select(Function(fi) fi.FullName)
tempList.AddRange(selectedFiles.ToArray())
For Each s In tempList
Console.WriteLine(s)
Next
Console.ReadLine()
End Sub
End Module
I created some files in a directory, and one of them I named starting with "~$" and set its hidden attribute:
C:\temp\testfiles>dir
Directory of C:\temp\testfiles
21/10/2019 15:48 0 one.txt
21/10/2019 15:49 0 two.txt
21/10/2019 15:48 0 ~$one.txt
3 File(s) 0 bytes
C:\temp\testfiles>dir /a:h
Directory of C:\temp\testfiles
21/10/2019 15:49 0 ~$three.txt
1 File(s) 0 bytes
and got this output from the program:
C:\temp\testfiles\one.txt
C:\temp\testfiles\two.txt
C:\temp\testfiles\~$one.txt
N.B. You are probably making things difficult for yourself by using a Specialized.StringCollection() instead of a List(Of String).

This can help you:
tempList As New Specialized.StringCollection
tempList.AddRange((From sFile As String In My.Computer.FileSystem.GetFiles(path, subFolders, "*" & fileExt).ToList.AsEnumerable
Where sFile IsNot Nothing
Where sFile.IndexOf("~$") = -1).ToArray)

Related

Merge pdf files with VBA and Foxit

I use Foxit Phantompdf, the complete version and ACCESS.
In our program, we have to save multiple pdf files, some of them should be merged in single files when saved.
Here is the code I use;
Dim phApp As PhantomPDF.Application
Dim n1 As String
Dim n2 As String
n1 = "c:\Temp\F3769-190136-GROUPE OCÉAN.pdf"
n2 = "c:\Temp\f3769-190136-GROUPE OCÉAN- facture.pdf"
Set phApp = CreateObject("PhantomPDF.Application")
Dim phCreator As PhantomPDF.Creator
Set phCreator = phApp.Creator
***'Call phCreator.CombineFiles("c:\Temp\F3769-190136-GROUPE OCÉAN.pdf|c:\Temp\f3769-190136-GROUPE OCÉAN- facture.pdf", "c:\Temp\F3769-190136-GROUPE OCÉAN.pdf", COMBINE_ADD_CONTENTS)***
Call phCreator.CombineFiles("""c:\Temp\" & n1 & "|'" & n2 & """" & ", " & """c:\Temp\F3769-190136-GROUPE OCÉAN.pdf"""" &", COMBINE_ADD_CONTENTS)
phApp.Exit
When I try it with the complete files names (in bold) the code works perfectly.
However, when I try to use variables, I get a
"Argument not optional"
error.
Can somebody help me ?
Thanks
Your string definitions in call line is incorrect.
You have defined n1 and n2 with the c:\temp already, and in your string conversion you add this again. I do not know if this is the route cause to your issue.
Furthermore I do not know the actual needed syntax for this phcreator.combine()
But is it not possible using only:
call pHcreator.combine(n1 & "|" & n2, …
The 'Argument not option' might imply you should add another input to your pHcreator, I would guess it could have something to do with FOXIT's combine function page settings. Try adding a input variable integer at the end of the function maybe?
But the fact that it works when writing strings in clear text would maybe suggest that the string manipulations is not correct?
I'm not a vba professional, but interested in the outcome, working myself with Foxit and also want to combine with vba. I'm currently not using version 9 som I seem to be out of luck, and only upgrading it I know what I want to do is possible.
I tried it, but got the same error message. So I took advantage of the fact that the function works when the file names are in plain text. I copied the files to be merged in a temporary folder and rename them. The renamed files are the then used in the merge function. It works perfectly, but Foxit adds a table of content page, and I don't know, yet, how to remove it. Here is my solution:
Private Sub Command4_Click()
Dim addi As String 'file to be merged to main file
Dim princi As String 'main file
Dim phApp As PhantomPDF.Application
'A temporary folder, in this case c:\t2, should be present
'In this example c:\Temp is the working folder
addi = "c:\Temp\filetomerge.pdf" 'full path of file to be merged
princi = "c:\Temp\mainfile.pdf" 'full path of main file
'fadd,pdf and fmain.pdf are the temporay files used in Foxit's function
FileCopy addi, "c:\t2\fadd.pdf" 'temporary file to be merged in temporary folder
FileCopy princi, "c:\t2\fmain.pdf" 'temporary main file in temporary folder
'Merge action
Set phApp = CreateObject("PhantomPDF.Application")
Dim phCreator As PhantomPDF.Creator
Set phCreator = phApp.Creator
Call phCreator.CombineFiles("c:\t2\fmain.pdf|c:\t2\fadd.pdf", "c:\t2\fmain.pdf", COMBINE_ADD_CONTENTS)
phApp.Exit
'Save merged file in working folder under main file name
Kill princi
FileCopy "c:\t2\fmain.pdf", princi
'delete temporary files
Kill "c:\t2\fadd.pdf"
Kill "c:\t2\fmain.pdf"
End Sub

How to transfer a file from one directory to another that is the newest file

I am trying to transfer a file from one directory to another that is the current and latest file in that folder, however I cannot use Robocopy to do this, since it fails when the server is logged out. Is there another way I can do this in Vb.net?
Thank you.
you can use File.Copy(Source,Destination,Overwrite?) to overwrite the file with a newer one, or
If File.Exists(destination) Then File.Delete(destination);
' Move the file.
File.Move(source, destination);
to move the file... I pesonally prefer:
File.Copy(Source,Destination,true)
File.Delete(Source)
To move the file and overwrite it if it exists :)... less code
Here's the code to move the latest file to another directory
Dim SourceDirectory As String = "C:\sourcedirectory\"
Dim SaveDirectory As String = "C:\targetdirectory\"
Dim LatestFile as IO.FileInfo = Nothing
'Let's scan the directory and iterate through each file...
Dim DirInfo As New IO.DirectoryInfo(SourceDirectory)
For Each file As IO.FileInfo In DirInfo.GetFiles()
If LatestFile Is Nothing Then
'This is the first time we run any permutations, so let's assign this file as "the latest" until we find one that's newer
LatestFile = file
ElseIf file.CreationTime > LatestFile.CreationTime Then
'Changes the "Latest file" if this file was created after the previous one.
'You can also change the check to .LastAccessTime and .LastWriteTime depending on how you want to define "the newest"...
LatestFile = file
End If
Next
'Now we move the file, but first, check to see if we actually did find any file in the source directory
If NewestFile IsNot Nothing Then
NewestFile.CopyTo(SaveDirectory & NewestFile.Name,true) 'will copy and overwrite existing file
'Now we can delete the old one
NewestFile.Delete()
Else
'Could not find the newest file, or directory might be empty...
End If
'Done!
Hope that Helps

File check and update

I want to make updater for some files (Like a SVN). So all files are around 250MB and downloading them and comparing with exist files will be too long. I thought to make system, that compares just information about files.For example: get number of bytes from file "a" on hdd and file "a" on a cloud, then compare the numbers and update if needed file on hdd.
So I tried to make it like I said before, but failed. I have some code, but I can't make it done:
Private Sub scan()
Dim path As String = TextBox1.Text
Dim files() As FileInfo
Dim dirinfo As New DirectoryInfo(path)
files = dirinfo.GetFiles("*", IO.SearchOption.AllDirectories)
For Each file In files
ListBox1.Items.Add(file.Name & "," & file.Length)
Next
End Sub
I just have a file list in my program and in the cloud, but i can't use it for comparing. Is there any idea how to make it?

Visual Basic FileSystem.GetFiles

I'm making a console application and I want to see what files is in a folder
For Each foundFile As String In My.Computer.FileSystem.GetFiles("c:\users\zac\desktop\booked vehicle\requested\")
Console.WriteLine(foundFile)
Next
after using this code and find that the folder is empty I need an If statement that say's
If foundfile has no files then
tell user no files found
end if
but I don't know how to write this so Visual Basic understands.
Load the files into a variable then check the count.
Dim files = My.Computer.FileSystem.GetFiles("c:\users\zac\desktop\booked vehicle\requested\")
If files.Count = 0 Then
'tell user no files
Else
For Each file In files
Console.WriteLine(file)
Next
End If
FileSystem.GetFiles() returns a collection of file name strings. As OneFineDay showed, you can use the collection's Count property to know if any files were found.
The downside of using FileSystem.GetFile() is that it has to search the entire folder before then returning the entire list of filenames. If you are searching large folders and speed is an issue, consider using Directory.EnumerateFiles() instead. That way, you can output a message if no file was found, otherwise loop throuh the list of found files. For example:
Dim files = Directory.EnumerateFiles("c:\users\zac\desktop\booked vehicle\requested\").GetEnumerator()
If files.MoveNext Then
' files were found
Do
Console.WriteLine(files.Current)
Loop Until Not files.MoveNext
Else
' no files were found
End If
I personally would use Linq to accomplish this. It's very quick and efficient to use in this case. I put the Console.ReadLine() at the end to show the files, you can remove this if need to be. Also you can change the Console.WriteLine to not include the string (s) if you don't want to. The s was declared if you want to show the files and also to see if there are any files. As I said, this was for my viewing to see the files. Straight to the point!
Dim s As String = String.Join(Environment.NewLine, New DirectoryInfo("YOUR DIRECTORY").GetFiles().[Select](Function(file) file.Name).ToArray)
Console.WriteLine(If(s.Length > 0, s, "No files found!"))
Console.ReadLine()

VB.NET - search for directory and delete if it contains certain characters

I have searched high and low and cannot find a way of doing this. I am writing a program that will run at logon and delete a directory within another directory. Our company has a software application that contains a directory that sometimes becomes corrupted. The issue is that the directory contains some static words and then is appended with a randomly generated set of characters. Thus, the need for a search for the static words and delete any directory that contains them. This is kicking my butt. Thanks for any help!
Edit:
My apologies for not adding some or all of the code that I've written thus far. I can delete the static directories, but not the dynamic ones. Again, I'm teaching myself and I'm sure there's better ways of doing what I need, but I don't know them. I'm also relatively certain that my code is messy and such. I would love some constructive criticism, but please don't bash me for trying. Please see below. Thanks!
Imports System.IO
Module Module1
Public Sub Main()
'I'm wanting to see the user name output in the console
Dim user As String
user = Environment.UserName
Console.Write(user)
'new line
Console.WriteLine()
Dim path1 As String
path1 = "\appdata\local\DIRECTORY\APPLICATIONNAME.exe_Url_ny2thmvtmqmw4jiqk1yuytwfbddruu02"
Dim path2 As String
path2 = "\appdata\local\DIRECTORY\APPLICATIONNAME.exe_Url_r3joylqll52q54guz0002pxu4swqous0"
Dim fullpath As String
fullpath = "C:\Users\" & user & path1
Dim fullpath2 As String
fullpath2 = "C:\Users\" & user & path2
Dim toplevel As String
toplevel = "\appdata\local\APPLICATIONNAME\"
Dim toplevel1 As String
toplevel1 = "C:\Users" & user & toplevel
If Directory.Exists(fullpath) = True Then
Directory.Delete(fullpath, True)
ElseIf Directory.Exists(fullpath2) = True Then
Directory.Delete(fullpath2, True)
End If
'I would like to keep the window open until I work the kinks out
Console.WriteLine("Finished. You may now close this window.")
Console.ReadKey()
End Sub
End Module
This should do what you need. I've included parameter names to make it more readable. You can strip them out if you prefer the more concise approach...
' Will find all directories under C:\Root\Folder\
' (including subdirectories) with a name that starts
' with "SearchString", then delete them and their contents
System.IO.
Directory.
GetDirectories(
path:="C:\Root\Folder\",
searchPattern:="SearchString*",
searchOption:=System.IO.SearchOption.AllDirectories).
ToList().
ForEach(Sub(x) System.IO.Directory.Delete(path:=x, recursive:=True))
That said, This is simply joining together two tasks:
Finding a list of directories
Deleting each one in turn
There are many tutorials and examples on the internet (and numerous questions on Stack Overflow) relating to these topics.
Edit: The concise version
Imports System.IO
Directory.GetDirectories("C:\Root\Folder\", "SearchString*", SearchOption.AllDirectories).
ToList().ForEach(Sub(x) Directory.Delete(x, True))
try using something like
this code below deletes every folder thats contains the pattern listed on
the string array.
Dim Words() As String = {"Word1","Word3","Word4",.."Wordn"}
For Each iPatternWord as String In Words
For Each iDir As System.IO.DirectoryInfo In System.IO.Directory.GetDirectories(#"C:\",iPattern)
iDir.Delete(true);//===>Delete this folder.
Loop
Loop