简体   繁体   English

使用NSIS检测目标卷是否为NTFS

[英]Detecting if the target volume is NTFS using NSIS

I'm creating an installer with NSIS for a program that needs to run on an NTFS volume. 我正在使用NSIS为需要在NTFS卷上运行的程序创建安装程序。 How do I detect if the install to path is on an NTFS volume and act accordingly (show a help/warning message)? 如何检测路径安装是否在NTFS卷上并采取相应措施(显示帮助/警告消息)?

Using external tools is not always a good idea (Not every command line tool exists on the Home versions of windows ) It's always better to call the correct API directly with the system plug in. 使用外部工具并非总是一个好主意(并非Windows的Home版本中存在每个命令行工具)总是最好使用系统插件直接调用正确的API。

!include LogicLib.nsh

StrCpy $0 "c:\"
System::Call 'Kernel32::GetVolumeInformation(t "$0",t,i ${NSIS_MAX_STRLEN},*i,*i,*i,t.r1,i ${NSIS_MAX_STRLEN})i.r0'
${If} $0 <> 0
    MessageBox mb_ok "fs=$1"
${EndIf}

But in this case, you should not be checking the file system type, but you should look for the actual feature you need (compression,encryption,junctions,sparse files etc) 但是在这种情况下,您不应检查文件系统类型,而应查找所需的实际功能(压缩,加密,连接,稀疏文件等)。

!define FILE_SUPPORTS_ENCRYPTION 0x00020000
!define FILE_READ_ONLY_VOLUME 0x00080000
!define FILE_VOLUME_QUOTAS 0x00000020

!macro MakeBitFlagYesNo flags bit outvar
IntOp ${outvar} ${flags} & ${bit}
${IfThen} ${outvar} <> 0 ${|} StrCpy ${outvar} "Yes" ${|}
${IfThen} ${outvar} == 0 ${|} StrCpy ${outvar} "No" ${|}
!macroend

StrCpy $0 "c:\"
System::Call 'Kernel32::GetVolumeInformation(t "$0",t,i ${NSIS_MAX_STRLEN},*i,*i,*i.r1,t,i ${NSIS_MAX_STRLEN})i.r0'
${If} $0 <> 0
    !insertmacro MakeBitFlagYesNo $1 ${FILE_SUPPORTS_ENCRYPTION} $2
    !insertmacro MakeBitFlagYesNo $1 ${FILE_READ_ONLY_VOLUME} $3
    !insertmacro MakeBitFlagYesNo $1 ${FILE_VOLUME_QUOTAS} $4
    MessageBox mb_ok "flags=$1 $\nFILE_SUPPORTS_ENCRYPTION=$2$\nFILE_READ_ONLY_VOLUME=$3$\nFILE_VOLUME_QUOTAS=$4"
${EndIf}

I'm not familiar with NSIS, but you may find this little "DOS" trick helpful. 我不熟悉NSIS,但是您可能会发现这个小的“ DOS”技巧很有帮助。

I did notice that it is possible to open a file with NSIS, so this may help -- 我确实注意到可以使用NSIS打开文件,所以这可能会有所帮助-

chkntfs c: | find "file system" > yourfile.abc

CHKNTFS is a utility for managing the CHKDSK operations, but if you run the command with no command line switches, it simply reports the results. CHKNTFS是用于管理CHKDSK操作的实用程序,但是如果您在没有命令行开关的情况下运行该命令,它将仅报告结果。

the "C:" is the drive you're interested in -- “ C:”是您感兴趣的驱动器-

You can run this from a command prompt to see the result, without the "> yourfile.abc" part, of course, which is what directs the output into that file. 当然,您可以从命令提示符处运行此命令以查看结果,而没有“> yourfile.abc”部分,这是将输出定向到该文件的原因。

Before anyone down votes this, I just offer it as a thought provoking SUGGESTION, perhaps sparking the real solution and remember SO motto -- be KIND ... lol ... 在任何人对此投反对票之前,我只是以发人深省的建议为由,也许是引发真正的解决方案,并记住一个座右铭-亲切...大声笑...

EDIT: this snippet may help -- I have no way to really TEST this -- THIS IS COMPILE TIME USAGE -- and you will most likely want RUN-TIME ... BUT, it may give you an idea ... 编辑:此代码片段可能会有所帮助-我没有办法真正测试一下-这是编译时间的用法-您很可能需要运行时...但是,它可能会给您一个想法...

I "assume" there isn't a define already named NTFS -- if so, change this accordingly. 我“假定”没有一个已经命名为NTFS的定义-如果是这样,请相应地更改它。 The first call CREATES the include file, the second APPENDS to it (the double > )... The /C option for FIND simply COUNTS the number lines containing the search item. 第一个调用创建包含文件,第二个调用附加到该文件(双>)... FIND的/ C选项仅对包含搜索项的数字行进行计数。 Hence, the 0 or 1 result. 因此,结果为0或1。

!system 'echo "!define NTFS=" > newinclude.nsh'
!system 'chkntfs c: | find /c "NTFS" >> newinclude.nsh'
!include newinclude.nsh
!ifdef NTFS
  !echo "NTFS is defined and value should reflect accordingly; 0=NO, 1=Yes it is NTFS"
!endif

EDIT: (again, lol) 编辑:(再次,大声笑)

here's a snippet that will set an ENVIRONMENT variable, which from what I can tell, should be rather easy to read during run-time -- you could construct a variable to execute, replacing the drive letter accordingly. 这是一个片段,它将设置一个环境变量,据我所知,它在运行时应该很容易阅读-您可以构造一个变量来执行,从而相应地替换驱动器号。

ExecWait 'chkntfs c: | find /c "NTFS"  > tempfile.abc'
ExecWait 'set /p NTFS= < tempfile.abc'
Exec     'del tempfile.abc'

Now, an environment variable called NTFS should hold a 0 if not NTFS and 1 if the volume being inspected IS NTFS. 现在,如果不是NTFS,则称为NTFS的环境变量应保留0,如果要检查的卷为NTFS,则应保留1。

Or directly 或直接

ExecWait 'chkntfs c: | find /c "NTFS"' $0

$0 holds the return code; $ 0保留返回码; The results are kind of backwards as this is the ERROR return code. 结果有点倒退,因为这是错误返回码。 If 0 you HAVE NTFS and > 0 means NO NTFS. 如果为0,则表示已拥有NTFS,而> 0表示没有NTFS。

Your test would need to be at run-time, so Borzio's answer would not work by itself. 您的测试将需要在运行时进行,因此Borzio的答案本身不会起作用。

It also looks like the ExecWait command does not allow for redirection, so it would not work to execute it that way and then check the contents of a file. 看起来ExecWait命令似乎不允许重定向,因此以这种方式执行然后检查文件内容将不起作用。

It looks to me like your best options would be to pick one of: 在我看来,您最好的选择是选择以下一项:

  • make a batch file that would run chkntfs and then set the error level based on the result 制作一个将运行chkntfs的批处理文件,然后根据结果设置错误级别
  • write a C/C++/VB/etc. 编写C / C ++ / VB / etc。 app that would run chkntfs and then set the error level based on the result 应用会运行chkntfs,然后根据结果设置错误级别
  • write a C/C++/VB/etc. 编写C / C ++ / VB / etc。 app that would use Win32 APIs to determine the filesystem 使用Win32 API确定文件系统的应用程序
  • write a plug-in for NSIS that would use Win32 APIs to determine the filesystem 为NSIS编写一个插件,该插件将使用Win32 API确定文件系统

Edit: Borzio updated his before I finished mine :) 编辑: Borzio在我完成我的工作之前更新了他的:)

You might need to add something I found on the Winamp forums: ExecWait with file redirection 您可能需要添加在Winamp论坛上找到的内容: 具有文件重定向的ExecWait

  ExpandEnvStrings $1 %COMSPEC%
  ExecWait '"$1" /C chkntfs c: | find /c "NTFS"' $0

Without the ExpandEnvStrings $1 %COMSPEC% , it was not working on my system to generate a redirected file. 没有ExpandEnvStrings $1 %COMSPEC% ,它在我的系统上无法生成重定向文件。

I've tested the above, and it does work, 0 for NTFS and 1 for non NTFS. 我已经测试了上面的内容,并且确实可以使用,对于NTFS为0,对于非NTFS为1。

The only possible drawback for this method is that a command windows pops up briefly during the code execution. 该方法的唯一可能的缺点是在执行代码期间会短暂弹出命令窗口。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM