VB关于获取短文件名!

valmin 2011-05-13 11:13:39
在API中,有一个函数 GetShortPathName 可以获取到 正常文件/文件夹 的短文件名,可是,有一些 特殊的文件/文件夹 (比如 带点的文件夹 ),的短文件名却无法获取,经一番查找,发现这个函数是95那个时代的,所以没有特殊的文件夹,导致现在使用的时候,无法完成一些功能,但是, 用 dir /a/x 的CMD命令可以查看到,在VB里面却无法实现,不知有什么方法可以解决的?
...全文
377 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
Lactoferrin 2011-05-14
  • 打赏
  • 举报
回复
这样得到的是正确的短文件名,在fat文件系统中a.才有短文件名,在ntfs文件系统中,a.被认为符合短文件名规则,就没有长文件名项,尽管它有.这个字符


这句话不对,在ntfs中,如果NtfsDisable8dot3NameCreation=0或没有,就会生成短文件名项
Lactoferrin 2011-05-14
  • 打赏
  • 举报
回复
这是转换方式
The technique chosen to auto-generate short names from long names is modeled after Windows NT.
Auto-generated short names are composed of the basis-name and an optional numeric-tail.

The Basis-Name Generation Algorithm

The basis-name generation algorithm is outlined below. This is a sample algorithm and serves to
illustrate how short names can be auto-generated from long names. An implementation should follow
this basic sequence of steps.

1. The UNICODE name passed to the file system is converted to upper case.
2. The upper cased UNICODE name is converted to OEM.
if (the uppercased UNICODE glyph does not exist as an OEM glyph in the OEM code page)
or (the OEM glyph is invalid in an 8.3 name)
{
Replace the glyph to an OEM '_' (underscore) character.
Set a "lossy conversion" flag.
}
3. Strip all leading and embedded spaces from the long name.
4. Strip all leading periods from the long name.
5. While (not at end of the long name)
and (char is not a period)
and (total chars copied < 8)
{
Copy characters into primary portion of the basis name
}
6. Insert a dot at the end of the primary components of the basis-name iff the basis name has an
extension after the last period in the name.
7. Scan for the last embedded period in the long name.
If (the last embedded period was found)
{
While (not at end of the long name)
and (total chars copied < 3)
{
Copy characters into extension portion of the basis name
}
}
Proceed to numeric-tail generation.

The Numeric-Tail Generation Algorithm

If (a "lossy conversion" was not flagged)
and (the long name fits within the 8.3 naming conventions)
and (the basis-name does not collide with any existing short name)
{
The short name is only the basis-name without the numeric tail.
}
else
{
Insert a numeric-tail "~n" to the end of the primary name such that the value of the "~n" is
chosen so that the
name thus formed does not collide with any existing short name and that the primary name does
not exceed eight characters in length.
}
The "~n" string can range from "~1" to "~999999". The number "n" is chosen so that it is the next
number in a sequence of files with similar basis-names. For example, assume the following short
names existed: LETTER~1.DOC and LETTER~2.DOC. As expected, the next auto-generated name
of name of this type would be LETTER~3.DOC. Assume the following short names existed:
LETTER~1.DOC, LETTER~3.DOC. Again, the next auto-generated name of name of this type
would be LETTER~2.DOC. However, one absolutely cannot count on this behavior. In a directory
with a very large mix of names of this type, the selection algorithm is optimized for speed and may
select another "n" based on the characteristics of short names that end in "~n" and have similar leading
name patterns.
Lactoferrin 2011-05-14
  • 打赏
  • 举报
回复
int main()
{
WIN32_FIND_DATAW f;
FindFirstFileW(L"\\\\?\\C:\\a.",&f);
_putws(f.cAlternateFileName);
}
这样得到的是正确的短文件名,在fat文件系统中a.才有短文件名,在ntfs文件系统中,a.被认为符合短文件名规则,就没有长文件名项,尽管它有.这个字符

再看一下硬盘实际存储的样子







valmin 2011-05-14
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 lactoferrin 的回复:]
旧的api照样可用,msdn并没有说GetShortPathName被废弃,windows7上都可用,实际上没有GetShortPathName ,只有GetShortPathNameW 和GetShortPathNameA
使用GetShortPathNameW时加上\\?\可以绕过RtlDosPathNameToNtPathName_U的修正

GetShortPathNameW通过Fi……
[/Quote]

不是不可用的问题,由于这个函数在出现的时候,并没有所谓的文件系统命名漏洞出现,所以针对通过文件命名漏洞生成的 带点文件夹 比如 d:\1234. 这样的文件夹,是无法获取得其8.3格式的文件名的,目的是想获得 d:\1234~1 这样的效果,但是用这个API,还是返回原来的 D:\1234. 如果是 \\?\d:\1234. 返回的还是 \\?\d:\1234. 所以并不能达到目的。

我自己也写过自定的函数来转换,可是,只能针对在相同文件夹下面,没有超过4个命名相近的文件就可以,比如有文件是按 年-月-日 时-分-秒 等来命名的,那么,文件名的前段就会有很多相同的,而8.3格式的文件名,我测试过,貌似只有到 ~4 也就是说,超过4个文件名类似的文件夹,就无法使用我的自定函数,如果知道8.3格式名的转换方式就好了~!
valmin 2011-05-14
  • 打赏
  • 举报
回复
嗯,经过测试,FindFirstFile 这个函数可以获取得到文件的短文件名

下面附上VB的源码:


Option Explicit

Private Declare Function FindFirstFile Lib "kernel32" Alias "FindFirstFileA" (ByVal lpFileName As String, lpFindFileData As WIN32_FIND_DATA) As Long

Private Type FILETIME
dwLowDateTime As Long
dwHighDateTime As Long
End Type

Private Type WIN32_FIND_DATA
dwFileAttributes As Long
ftCreationTime As FILETIME
ftLastAccessTime As FILETIME
ftLastWriteTime As FILETIME
nFileSizeHigh As Long
nFileSizeLow As Long
dwReserved0 As Long
dwReserved1 As Long
cFileName As String * 260
cAlternate As String * 14
End Type

Const INVALID_HANDLE_VALUE = -1

Private Sub Command1_Click()
'查找文件的过程
Dim FileHandle& '存储句柄
Dim FileName1$ '存储返回的文件名
Dim nFindFileData As WIN32_FIND_DATA
Dim FileStatu&

FileStatu& = FindFirstFile(Text1.Text, nFindFileData) '

If FileHandle& <> INVALID_HANDLE_VALUE Then
FileName1$ = nFindFileData.cAlternate
MsgBox "文件的短文件名:" & FileName1$
Else
MsgBox "文件不存在!"
End If

End Sub

Private Sub Form_Load()
Text1.Text = "\\?\D:\1234."
End Sub


在此非常感谢 Lactoferrin 的指导,谢谢~!~!分给你~!
Lactoferrin 2011-05-13
  • 打赏
  • 举报
回复
旧的api照样可用,msdn并没有说GetShortPathName被废弃,windows7上都可用,实际上没有GetShortPathName ,只有GetShortPathNameW 和GetShortPathNameA
使用GetShortPathNameW时加上\\?\可以绕过RtlDosPathNameToNtPathName_U的修正

GetShortPathNameW通过FindFirstFileW来实现,FindFirstFile旧不?照样常用。
valmin 2011-05-13
  • 打赏
  • 举报
回复
GetShortPathNameW 和 GetShortPathName 是同样的,因为这个是旧的API了,所以无法使用其功能,至于CMD命令,主要是比较麻烦,就是想找看有没有新版的相关的API,这样就方便多了
Lactoferrin 2011-05-13
  • 打赏
  • 举报
回复
Private Declare Function GetShortPathNameW Lib "kernel32.dll" (ByVal LongPath As Long, ByVal ShortPath As Long, ByVal Length As Long) As Long
Private Sub Form_Load()
Dim a$
a$ = Space(255)
GetShortPathNameW StrPtr("\\?\C:\a."), StrPtr(a), 255
MsgBox a$
End Sub
Lactoferrin 2011-05-13
  • 打赏
  • 举报
回复
[Quote=引用楼主 valmin 的回复:]
在API中,有一个函数 GetShortPathName 可以获取到 正常文件/文件夹 的短文件名,可是,有一些 特殊的文件/文件夹 (比如 带点的文件夹 ),的短文件名却无法获取,经一番查找,发现这个函数是95那个时代的,所以没有特殊的文件夹,导致现在使用的时候,无法完成一些功能,但是, 用 dir /a/x 的CMD命令可以查看到,在VB里面却无法实现,不知有什么方法可以解决的?
[/Quote]

你的带点文件夹是什么意思
赵4老师 2011-05-13
  • 打赏
  • 举报
回复
引用 1 楼 theforever 的回复:
先 SHELL "dir /a/x >某文件.log",vbHide
然后 OPEN 某文件.log 读内容即可。需要完整名称就截取短文件名和文件夹名进行拼接。


支持。
凡是能用DOS命令加输出重定向解决的问题尽量避免改用API啥的整,因为API不如DOS命令稳定。
  • 打赏
  • 举报
回复
先 SHELL("dir /a/x>某文件.log")
然后 OPEN 某文件.log 读内容即可。需要完整名称就截取短文件名和文件夹名进行拼接。
vb提取查看thumbs.db文件中的图像内容,VB6.0编写开发的Windows XP缩略图缓存文件查看提取工具,把有图片的文件夹中的Thumbs.db拖到下面的列表框中(在资源管理器的文件夹选项设置中要取消“隐藏受保护的系统文件(推荐)”,才可以看到XP的缓存缩略图文件Thumbs.db)。   实现原理部分需要说明的是:PSC原作者使用String类型来读取,这可能是英文操作系统上可以运行,但是在中文操作系统是错误的,在用 Preserve 关键字时,只能改变多维数组中最后一维的上界;所以,第1维存放数据,范围就是0(缩略图Jpg大小最大不会超过5KB),第2维根据项目的个数来表示的编号但是不能直接使用数组的形式来返回,必须用传址的方式返回   还有一种方法,是记录每个图片文件项目的差异的偏移,及插入的非jpg数据块的大校   因为没有Thumbs.db的详细文件格式资料,无法获取文件的个数现在这个版本有一个问题,会有些文件看不到,因为查看文件内容发现,中间有些Jpg文件很,只有几百字节,与文件数据前的文件大小不符合,这样就会跳过一个文件,导致漏掉文件。   增加一个判断,每找到一个标志,跳过文件长度时,先判断该长度的文件尾是不是Jpg的文件尾标志,如果不是则从之前的位置继续搜索。一种情况:就是4位字节文件大小的值,小于实际的文件大小值,这就需要搜索修正在Thumbs.db文件里找到了全部对应文件的文件名,是用Unicode字符存储在里面的,有的是单独的一个,有的是几个连续一起。

1,486

社区成员

发帖
与我相关
我的任务
社区描述
VB API
社区管理员
  • API
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧