Excel vba kill only specified extension - vba

I trying to kill all files with extension xls
Sub testt()
downloadF = Environ("USERPROFILE") & "\Downloads\*.xls"
Kill downloadF
End Sub
But it also kill files .xlsx and .xlsm and everything with .xls*
Why?
How to kill only *.xls?

I have a theory as to why this is happening, but I haven't quite proven it... in the meantime I found an alternate method to delete only the intended files is to refer to the file's "short" (8.3) name:
For example, when I first checked my (NTFS) drive, using the /X switch with Dir at the command prompt:
      t.xlsx has a short name of TF99B~1.XLS
...and with Dir /x:
...and programmatically:
Option Explicit
Private Declare Function GetShortPathNameA Lib "kernel32" _
(ByVal lpszLongPath As String, ByVal lpszShortPath As String, ByVal cchBuffer As Long) As Long
Public Function ShortPath(ByVal fName As String) As String
Dim fNum As Integer, strBuffer As String * 255
fNum = FreeFile
If Dir(fName) = "" Then
On Error Resume Next 'Create file if it doesn't exist
Open fName For Output As #fNum
Close #fNum
End If
ShortPath = Left$(strBuffer, GetShortPathNameA(fName, strBuffer, 255))
End Function
As #Pᴇʜ pointed out, if you strip these from the files, eg. with:
fsutil 8dot3name strip c:\temp\test
...the Kill command works as expected (and does not kill xlsx).
fsutil 8dot3name strip : Removes the 8dot3 file names for all files that are located in the specified DirectoryPath. The 8dot3 file name is not removed for any files where the DirectoryPath combined with the file name contains more than 260 characters.
This command lists, but does not modify the registry keys that point to the files that had 8dot3 file names permanently removed.
For more information about the effects of permanently removing the 8dot3 file names from files, see Remarks.
...and through the command line, for a whole folder or volume at once:
To query for the disable 8dot3 name behavior for a disk volume
that is for a specific volume, use:
fsutil 8dot3name query Volume{xyz-VolumeGUID-xyz}
You can also query the 8dot3 name behavior by using the behavior
subcommand.
To remove 8dot3 file names in the D:\MyData directory and all
subdirectories, while writing the information to the log file that is
specified as mylogfile.log, type:
fsutil 8dot3name scan /l mylogfile.log /s d:\MyData
More Info:
Fsutil 8dot3name documentation
Fsutil documentation
Namespaces
'Source: Naming Files, Paths, and Namespaces (Microsoft)
All file systems follow the same general naming conventions for an individual file: a base file name and an optional extension, separated by a period. However, each file system, such as NTFS, CDFS, exFAT, UDFS, FAT, and FAT32, can have specific and differing rules about the formation of the individual components in the path to a directory or file.
. . .
Character count limitations can also be different and can vary depending on the file system and path name prefix format used. This is further complicated by support for backward compatibility mechanisms. For example, the older MS-DOS FAT file system supports a maximum of 8 characters for the base file name and 3 characters for the extension, for a total of 12 characters including the dot separator. This is commonly known as an 8.3 file name. The Windows FAT and NTFS file systems are not limited to 8.3 file names, because they have long file name support, but they still support the 8.3 version of long file names.
\\?\
Win32 File Namespaces
For file I/O, the \\?\ prefix to a path string tells the Windows APIs to disable all string parsing and to send the string that follows it straight to the file system. For example, if the file system supports large paths and file names, you can exceed the MAX_PATH limits that are otherwise enforced by the Windows APIs. For more information about the normal maximum path limitation, see the section Maximum Path Length Limitation.
Because it turns off automatic expansion of the path string, the \\?\ prefix also allows the use of .. and . in the path names, which can be useful if you are attempting to perform operations on a file with these otherwise reserved relative path specifiers as part of the fully qualified path.
Many but not all file I/O APIs support \\?\; you should look at the reference topic for each API to be sure.
\\.\
Win32 Device Namespaces
The \\.\ prefix will access the Win32 device namespace instead of the Win32 file namespace. This is how access to physical disks and volumes is accomplished directly, without going through the file system, if the API supports this type of access. You can access many devices other than disks this way (using the CreateFile and DefineDosDevice functions, for example).
NT Namespaces
There are also APIs that allow the use of the NT namespace convention, but the Windows Object Manager makes that unnecessary in most cases. To illustrate, it is useful to browse the Windows namespaces in the system object browser using the Windows Sysinternals WinObj tool. When you run this tool, what you see is the NT namespace beginning at the root, or \. The subfolder called Global?? is where the Win32 namespace resides.
FAT Naming Convention
Source: Overview of FAT, HPFS, and NTFS File Systems (Microsoft)
FAT uses the traditional 8.3 file naming convention and all filenames must be created with the ASCII character set. The name of a file or directory can be up to eight characters long, then a period . separator, and up to a three character extension. The name must start with either a letter or number and can contain any characters except for the following:
. " / \ [ ] : ; | = ,
If any of these characters are used, unexpected results may occur. The name cannot contain any spaces.
NTFS Naming Conventions
File and directory names can be up to 255 characters long, including any extensions. Names preserve case, but are not case sensitive. NTFS makes no distinction of filenames based on case. Names can contain any characters except for the following:
? " / \ < > * | :
Currently, from the command line, you can only create file names of up to 253 characters.
NOTE: Underlying hardware limitations may impose additional partition size limitations in any file system. Particularly, a boot partition can be only 7.8 GB in size, and there is a 2-terabyte limitation in the partition table.
More Information
MSDN : DeleteFile function
MSDN : DeleteFileFromApp function
MSDN : CheckNameLegalDOS8Dot3 function

Try
Option Explicit
Public Sub DelFiles()
Dim fso As Object, fol As Object, f As Object
Set fso = CreateObject("Scripting.FileSystemObject")
Set fol = fso.GetFolder(Environ$("USERPROFILE") & "\Downloads")
For Each f In fol.Files
'Debug.Print f
If fso.GetExtensionName(f) = "xls" Then Kill f
Next f
End Sub

Kill Environ("USERPROFILE") & "\Downloads\*.xls" should kill the .xls only.
However, can you try the following:
Open any folder in Windows
Go to View
Options
View
Uncheck "Hide extensions for known file types"
Click OK
See what is going on

I have no explanation for that, but found something strange.
I created 2 files, one test1.xls and with test2.xlsx. I copied these files to various places:
To %userprofile%\downloads
to %userprofile%\documents
to C:\junk
to U:\junk (where U: is a network share)
to G:\MyDrive\MyDocs\junk (where G: is created by Google File Stream)
For the first three cases (where the files live on C:\), the VBA command dir *.xls and also the Command-prompt dir *.xls listed both files, while for the "foreign" drives, only the test1.xls was listed. I assume that the kill used the same logic.
(Tested on Windows 10)

Related

How to add disk in zip using DotNetZip

I use DotNetZip for creating zips. It has many option but I couldn't find if it is possible to store the disk where the file is located, in the archive. E.g. like the Absolute mode in 7-Zip. As far as I can see I can only do this:
zip.AddFile(cFileFull, cPath);
When cFileFull is e.g. "c:\temp\SomeFile.txt" and cPath = "c:\temp" opening the zipfile shows
temp
while I would like to see
C
and then, when I click on C
temp
This allows storing the same path/file found on different drives. Is this possible?

VB.net rename each file in a directory

Id like to rename all my files in one specific directory. They shall all get the identical extension. I tried using a for loop:
For Each s As String In IO.Directory.GetFiles(Environ("PROGRAMFILES(x86)"), "*", IO.SearchOption.AllDirectories)
Try
My.Computer.FileSystem.RenameFile(s, s & ".new")
Catch ex As Exception
End Try
So that the name s (as string) becomes s & extension ".new"
However, that didnt work.
If you had read the documentation for the RenameFile method you are calling, as you should have to begin with but especially when it didn't work, then you would know that the first argument requires the full path of the file while the second argument requires just the new name of the file. That means that you need this:
My.Computer.FileSystem.RenameFile(s, My.Computer.FileSystem.GetName(s) & ".new")
The File.Move method requires full paths in both cases because it supports renaming within the same folder and moving to a different folder. You say that you want to use RenameFile but didn't bother to note how it is different, i.e. it only supports renaming within the same folder so specifying that path twice is pointless and allowing different paths to be specified would cause problems.

GetAttr Returning Value of 8211 VBA

What does the value of 8211 returned from the GetAttr funciton in VBA mean?
Code used:
Private Sub this()
Dim path As String
path = "c:\"
Dim firstdur As String
firstdir = Dir(path, vbNormal + vbHidden + vbDirectory)
Do Until firstdir = ""
Debug.Print ; firstdir & " " & GetAttr(path & firstdir)
firstdir = Dir()
Loop
End Sub
Output in question:
MSOCache 8211
GetAttr() Function returns an Integer representing the attributes of a file, directory, or folder.
Actually the result is a sum of the following constants specified by VBA within Enum VbFileAttribute:
vbNormal 0 Normal.
vbReadOnly 1 Read-only.
vbHidden 2 Hidden.
vbSystem 4 System file. Not available on the Macintosh.
vbDirectory 16 Directory or folder.
vbArchive 32 File has changed since last backup. Not available on the Macintosh.
vbAlias 64 Specified file name is an alias. Available only on the Macintosh.
Also there are File Attribute Constants which are used by Windows File API:
FILE_ATTRIBUTE_READONLY 1 (0x1) A file that is read-only. Applications can read the file, but cannot write to it or delete it. This attribute is not honored on directories.
FILE_ATTRIBUTE_HIDDEN 2 (0x2) The file or directory is hidden. It is not included in an ordinary directory listing.
FILE_ATTRIBUTE_SYSTEM 4 (0x4) A file or directory that the operating system uses a part of, or uses exclusively.
FILE_ATTRIBUTE_DIRECTORY 16 (0x10) The handle that identifies a directory.
FILE_ATTRIBUTE_ARCHIVE 32 (0x20) A file or directory that is an archive file or directory. Applications typically use this attribute to mark files for backup or removal .
FILE_ATTRIBUTE_DEVICE 64 (0x40) This value is reserved for system use.
FILE_ATTRIBUTE_NORMAL 128 (0x80) A file that does not have other attributes set. This attribute is valid only when used alone.
FILE_ATTRIBUTE_TEMPORARY 256 (0x100) A file that is being used for temporary storage. File systems avoid writing data back to mass storage if sufficient cache memory is available, because typically, an application deletes a temporary file after the handle is closed. In that scenario, the system can entirely avoid writing the data. Otherwise, the data is written after the handle is closed.
FILE_ATTRIBUTE_SPARSE_FILE 512 (0x200) A file that is a sparse file.
FILE_ATTRIBUTE_REPARSE_POINT 1024 (0x400) A file or directory that has an associated reparse point, or a file that is a symbolic link.
FILE_ATTRIBUTE_COMPRESSED 2048 (0x800) A file or directory that is compressed. For a file, all of the data in the file is compressed. For a directory, compression is the default for newly created files and subdirectories.
FILE_ATTRIBUTE_OFFLINE 4096 (0x1000) The data of a file is not available immediately. This attribute indicates that the file data is physically moved to offline storage. This attribute is used by Remote Storage, which is the hierarchical storage management software. Applications should not arbitrarily change this attribute.
FILE_ATTRIBUTE_NOT_CONTENT_INDEXED 8192 (0x2000) The file or directory is not to be indexed by the content indexing service.
FILE_ATTRIBUTE_ENCRYPTED 16384 (0x4000) A file or directory that is encrypted. For a file, all data streams in the file are encrypted. For a directory, encryption is the default for newly created files and subdirectories.
FILE_ATTRIBUTE_INTEGRITY_STREAM 32768 (0x8000) The directory or user data stream is configured with integrity (only supported on ReFS volumes). It is not included in an ordinary directory listing. The integrity setting persists with the file if it's renamed. If a file is copied the destination file will have integrity set if either the source file or destination directory have integrity set.
FILE_ATTRIBUTE_VIRTUAL 65536 (0x10000) This value is reserved for system use.
FILE_ATTRIBUTE_NO_SCRUB_DATA 131072 (0x20000) The user data stream not to be read by the background data integrity scanner (AKA scrubber). When set on a directory it only provides inheritance. This flag is only supported on Storage Spaces and ReFS volumes. It is not included in an ordinary directory listing.
FILE_ATTRIBUTE_RECALL_ON_OPEN 262144 (0x40000) This attribute only appears in directory enumeration classes (FILE_DIRECTORY_INFORMATION, FILE_BOTH_DIR_INFORMATION, etc.). When this attribute is set, it means that the file or directory has no physical representation on the local system; the item is virtual. Opening the item will be more expensive than normal, e.g. it will cause at least some of it to be fetched from a remote store.
FILE_ATTRIBUTE_RECALL_ON_DATA_ACCESS 4194304 (0x400000) When this attribute is set, it means that the file or directory is not fully present locally. For a file that means that not all of its data is on local storage (e.g. it may be sparse with some data still in remote storage). For a directory it means that some of the directory contents are being virtualized from another location. Reading the file / enumerating the directory will be more expensive than normal, e.g. it will cause at least some of the file/directory content to be fetched from a remote store. Only kernel-mode callers can set this bit.
Particularly for your case it is a sum of 8211 = 8192 + 16 + 2 + 1, that means read-only hidden folder which is not to be indexed.
You can refer to this page and check which attributes (flags) are set. For C:\MSOCACHE:
8211 = &H2013 = 0010 0000 0001 0011
= 1 + 2 + 16 + 8192
= READONLY + HIDDEN + DIRECTORY + NOT_CONTENT_INDEXED
So the file C:\MSOCACHE is a readonly hidden directory which is not content-indexed.

WinSCP Session::RemoveFiles - Delete specified files in sub directories

[Question] Does Session::RemoveFiles() remove files in sub directory of source directory? If not, how to implement this ability?
(Please do not ask me why I have the remote directory as /C/testTransfer/. The code just for testing purpose.)
I have a SFTP program using WinSCP .Net assembly. Program language is C++/CLI. It opens up a work file. The file contains many lines of FTP instructions.
One type of instruction I have to handle is to transfer *.txt from source directory. The source directory may contain sub directories which may contain .txt as well. Once transfer is successful, delete the source files.
I use Session::GetFiles() for the transfer. It correctly transfer all .txt files (/C/testTransfer/*.txt), even those in sub directories (/C/testTransfer/sub/*.txt), in the source to the destination.
transferOptions->FileMask = "*.txt";
session->GetFiles("/C/testTransfer", "C:\\temp\\win", false, transferOption);
Now to remove, I use session->RemoveFiles("/C/testTransfer/*.txt"). I only see *.txt in the source (/C/testTransfer/*.txt), but not in the sub directory (/C/testTransfer/sub/*.txt), are removed.
The Session::RemoveFiles can remove even files in subdirectories in general. But not this way with wildcard, because WinSCP will not descend to subdirectories that do not match the wildcard (*.txt). Also note that even if you do not need the wildcard, the Session::RemoveFiles would remove even the subdirectories themselves, what I'm not sure you want it to.
Though you have other (and better = more safe) options:
Use the remove parameter of the Session::GetFiles method to instruct it to remove source file after successful transfer.
If you need to delete source files transactionally (=only after download of all files succeed), iterate the TransferOperationResult::Transfers returned by Session::GetFiles and call the Session::RemoveFiles for each (unless the TransferEventArgs::Error is not null).
Use the TransferEventArgs::FileName to get a file path to pass to the Session::RemoveFiles. Use the RemotePath::EscapeFileMask to escape the file name before passing it to the Session::RemoveFiles.
There's a similar full example available for Moving local files to different location after successful upload.
To recursively delete files matching a wildcard in a standalone operation (not after downloading the same files), use the Session::EnumerateRemoteFiles. Pass your wildcard to its mask argument. Use the EnumerationOptions.AllDirectories option for recursion.
Call the Session::RemoveFiles for each returned file. Use the RemotePath::EscapeFileMask to escape the file name before passing it to the Session::RemoveFiles.

How to copy file to a new location having path length more than 260 characters in vista?

in my previous question as follows:
"How to create a copy of a file having length more than 260 characters."
I have asked almost same qustion and I got a solution to rename the directory name and then copy to a new location. But as per the client's requirement we can't rename the directory in any case.
So now my problem is when we try to copy a file having path length (including file name) more than 260 characters, (say 267 characters), it allows us to copy manually but throws an exception programmetically in vista OS.
Please let me know if any one has a solution.
Prepend \\?\ to your path to enable path lengths up to 32767 characters long. E.g:
copy \\?\C:\big\dir\hierarchy\myfile.txt \\?\C:\tohere.txt
This page has more details.
I've only tested this with DIR in WinXP, but that seems to work.
If the problem is just with the length of the file (not the preceding path), then you can use the short name version of the file (probabaly Outloo~1.xls ).
However, the only real viable solution is to use network redirection or SUBST command to shorten the path. I can imagine that you'd have to be keeping track of the path length in your program, and spawn a SUBST drive letter when the length is exceeded... dropping the drive letter when it's no longer needed. Ugly programming, but no hope.
Or
I know some unicode version of windows api functions (copyfileex..? http://msdn.microsoft.com/en-us/library/aa363852(VS.85).aspx) can handle to 32,767 chars.
Try to name it with a \\?\ prefix, for example, \\?\D:\. I'm not sure if CLR uses this kind of naming style, but you can give it a try.
You could check if compression tools like 7zip are limited by the length of the path in Vista.
If not, that means a "copy by program" would by:
compressed the tree of directories/file you want to copy
copy the .zip/.rar to the destination
uncompress