[新手上路]批处理新手入门导读[视频教程]批处理基础视频教程[视频教程]VBS基础视频教程[批处理精品]批处理版照片整理器
[批处理精品]纯批处理备份&还原驱动[批处理精品]CMD命令50条不能说的秘密[在线下载]第三方命令行工具[在线帮助]VBScript / JScript 在线参考
返回列表 发帖

[系统相关] 【已解】如何在命令行中使指定文件处于独占状态

我的需求是
在命令行中用任意命令打开指定文件
在该命令执行期间
该文件无法被其它程序复制、改名、删除以及覆盖
类似C:\WINDOWS\system32\config\sam文件的状态

如果上述需求是实现有困难
可以考虑用命令行程序独占该文件
不允许任意程序复制、改名、删除以及覆盖
除非接触独占状态
————————————————————————————
结语

关于这个需求
CrLf巡查付出了不懈的努力
我从中收获良多
虽然最终没有采用这些方案
但是这可求索的过程
让我不虚此问
你若看到此贴
如果也与我有一样的想法
那么请点赞 ^_^
1

评分人数

    • Batcher: 感谢给帖子标题标注[已解决]字样PB + 2
天的白色影子

Batcher版主可以预知未来
把未来的奖励都预支给我了

CrLf的代码都很有意思
每一段都值得仔细品读
  1. (for /r %%a in (*.*) do del /f /s "%%~nxa" 3>>"%%a") 2>nul 4>>%0
复制代码
这段代码中的4>>%0是什么意思还没有揣摩出来
  1. @echo off 3>&1l 4>>"a.txt"
复制代码
这段里面3>&1后面的字母l是何意啊?

这些代码都很好
这些部分的解决我的问题
只是还有两点遗憾啊

一是没有办法防复制
看来对SAM文件的处理
还是与普通的文件独占与不同之处
怀疑是相关驱动程序有特别的过滤逻辑

二是需要解除占用时都不是很轻便

另外测试时发现了一个不太明白的问题
type test.txt > test.txt
会将test.txt原本的内容清空
type test.txt >> test.txt
却会将test.txt原本的内容加倍

如果说>>test.txt会先将文件独占
那么type test.txt就应该无法读取文件内容
那应该保持test.txt内容原样才对
天的白色影子

TOP

CrLf的敬业让我佩服啊!

for /f改成下面这样就内容加倍了
  1. for /f %%a in (a.txt) do echo %%a>>a.txt
复制代码
4>>%0 是为了保证脚本在该目录下运行时不会被删。

从上下文看这个脚本肯定是在for /r的根上
如果这个目录树下与脚本同名的文件组
那脚本必然是第一个枚举并被占用保护的啊
不过为了脚本通用性这样设计也可以理解

那个vb程序应该不算是纯CLI程序
不过管它GUI,CLI
达到目的就行
要想改成CLI有难度
关键是程序退出前怎么处理打开的文件句柄
我再想想吧
也许有人可以帮忙

不过下次上传别绕这么多弯好不好
不让rar上传那直接改后缀名不行吗?
天的白色影子

TOP

回复 6# CrLf
根据以往的分析结果
重定向符号的分析必然优先于前面的语句命令
这也是type test.txt>test.txt会清空内容的本质原因
而不含()的for /f也与这个原则并不悖逆
因为可以认为那个>位于for/f的“子句”中
它仍然优先于子句的命令被解析了
但是type test.txt>>test.txt的结果
与上面这个原则似乎存在矛盾
这其中一定有什么我还不清楚的逻辑
看起来>>没有想象中的那样简单

lock.exe的CLI化我已经放弃了
希望有别人有这个兴趣吧
关于准确结束占用的话题
你想的可能有些复杂了
可以把lock改成一个指定的名字
比如lock_testfile.exe
然后再用它锁住文件
lock_testfile.exe testfile.txt
结束时只需要按进程名kill就可以了
我之前就是这样设想的

不过还是觉得杀进程太暴力了
而且为了一个并非主体的需求
消耗一个第三方程序代价有些高了
我回头由重新梳理了一下我的需求出发点

我只是需要在我的代码执行的某个周期内
某个指定的文件不会被其他程序有意无意的读写而已
于是我重新想到了一个不需使用文件占用的方法
这个方法也是收到7楼的Spring上尉的启发

就是修改文件的NTFS权限禁止当前用户读写
有了思路代码其实很简单了
  1. ::锁定的
  2. cacls testfile.txt /e /d %userdomain%\%username%
  3. ::解锁的
  4. cacls testfile.txt /e /p %userdomain%\%username%:f
复制代码
虽然代码并不十分完美和通用
但是在我所应用的情境下
这段代码完全可以胜任了

在此非常感谢两位兄弟
我的问题至此已经了结了
虽然留下一些未竟的遗憾
但是——
有时候就是这样
理论需要为实践做出让步
理想需要为现实做出妥协

不过——
如果大家有兴趣
还可以就文中的一些话题延伸讨论
我有时间也会尽可能关注的
1

评分人数

    • CrLf: “理想需要为现实做出妥协”技术 + 1
天的白色影子

TOP

Demon辛苦了
经过的你的分析
受到一点启发
终于比较明白>和>>的不同了

它们最本质的不同在于锁创建文件句柄是Desired Access参数不同
>创建的是Genric Write|Read Attributes模式的文件句柄
它会Overwrite原文件
即对文件长度置0
因此等到type再次打开该文件时
文件内容已被“清零”
>>创建的是Genric Read/Write模式的文件句柄
它会保持文件长度
并移动文件指针到原文件尾部
因此等到type再次打开该文件时
文件内容可以再次读取并写入

可以确认的是
在>和>>打开文件后
一直等待type再次打开并关闭同一文件后
才关闭文件
也就是>和>>并未以所谓“独占”的方式打开文件

另外一点意外的发现
在>正式打开文件之前
会预先打开一次文件查询文件的属性
主要包括长度、分配块大小、链接数等等
然后在关闭文件后再次正式打开
而>>是在正式打开文件的过程中查询该属性的
天的白色影子

TOP

我的分析都来自于Procmon的监测数据

对应的命令操作如下
  1. Microsoft Windows XP [版本 5.1.2600]
  2. (C) 版权所有 1985-2001 Microsoft Corp.
  3. C:\Documents and Settings\Administrator>d:
  4. D:\>cd test
  5. D:\test>dir
  6. 驱动器 D 中的卷没有标签。
  7. 卷的序列号是 5491-6D80
  8. D:\test 的目录
  9. 2014-04-13  17:15    <DIR>          .
  10. 2014-04-13  17:15    <DIR>          ..
  11. 2014-04-13  17:14                 3 testfile.dat
  12.                1 个文件              3 字节
  13.                2 个目录 15,396,376,576 可用字节
  14. D:\test>type testfile.dat >> testfile.dat
  15. D:\test>type testfile.dat > testfile.dat
  16. D:\test>
复制代码
进一步的测试发现
如果不存在的对应的文件
>预先的CreateFile会失败
自然也没有随后的查询与关闭
天的白色影子

TOP

返回列表