Windows 拖动调用的vbscript中的当前工作目录&;下降操作

Windows 拖动调用的vbscript中的当前工作目录&;下降操作,windows,batch-file,vbscript,drag-and-drop,working-directory,Windows,Batch File,Vbscript,Drag And Drop,Working Directory,当我试图为我的批处理脚本获得更高的权限时,我发现了两个相关的SO问题 …这导致了部分有效的答案。出于某种原因,我在命令行传递VBS脚本中包含空格的文件路径参数时遇到问题,因此我尝试将解决方案分为三部分,并将重点放在内部(VBS)步骤上,然后通过调用无法找到的VBS批处理来添加最后一步,尽管该批处理与VBS脚本位于同一文件夹中。我发现拖放并不“那么容易”,当使用.vbs而不是.bat或.exe作为拖放目标时,情况就不同了 这是我的实际问题: 如果我拖动一个文件并将其放到可执行文件(exe)

当我试图为我的批处理脚本获得更高的权限时,我发现了两个相关的SO问题

…这导致了部分有效的答案。出于某种原因,我在命令行传递VBS脚本中包含空格的文件路径参数时遇到问题,因此我尝试将解决方案分为三部分,并将重点放在内部(VBS)步骤上,然后通过调用无法找到的VBS批处理来添加最后一步,尽管该批处理与VBS脚本位于同一文件夹中。我发现拖放并不“那么容易”,当使用
.vbs
而不是
.bat
.exe
作为拖放目标时,情况就不同了

这是我的实际问题: 如果我拖动一个文件并将其放到可执行文件(exe)或批处理文件(bat、cmd)上,则当前工作目录由拖动项的源决定。它的目录被设置为处理它的程序或脚本的工作目录

如果我把一个文件放到VBS脚本上,它就不同了。在Windows 8.1 x64上,我观察到它是
C:\Windows\System32
,即使参数与VBS位于同一文件夹中

我可以像这样简单地使用批处理文件(作为拖放中继)

my.vbs %*
为了获得“正常的”
.bat
行为(drop source指示CWD),但我也想了解它

它是一个bug还是一个特性?它在所有Windows版本上都是一致的吗



编辑:为问题添加了背景(在顶部),显示我是如何到达那里的(+轻微更正)

c:\windows\system32\CScript.exe
c:\windows\system32\Wscript.exe
是运行vbscript的程序。如您所见,它们位于
system32

Windows使用ShellExecuteEx启动程序-请参阅MSDN上的规则:

ShellExecuteEx使用CreateProcess(CreateProcessEx)实际启动程序

编辑

CMD不会将注册表用于它自己的东西。这些注册表项用于CMD以外的程序

CMD的主要目标是兼容MS Dos 5,同时增强它,它将正确运行大多数Dos批处理文件。它是由在OS/2而不是Windows上工作的IBM工程师编写的

编辑2

问题的核心是,您试图编写程序,就好像您是一个用户在操作计算机一样

作为一名程序员,你不会做出假设。不采用假设的最简单方法是指定所需内容的完整路径。批处理文件不应该关心当前目录是什么。例如,在CMD中,每个驱动器都有一个与MSDos 5兼容的当前目录(控制台中的程序倾向于共享它们,但不一定要共享)。在Windows中,每个程序有一个当前目录。默认的当前目录已更改多年

只有在编写供用户使用的批处理文件时,才应使用当前目录。例如,如果您键入
dir
它会显示当前目录,则表示为常规命令的批处理文件应以相同的方式工作。

该属性包含脚本上删除的所有项目的完整路径,因此您可以确定每个删除项目的目录,如下所示:

Set fso = CreateObject("Scripting.FileSystemObject")
For Each item In WScript.Arguments
  WScript.Echo fso.GetParentFolderName(item)
Next
Set fso = CreateObject("Scripting.FileSystemObject")
Set sh  = CreateObject("WScript.Shell")
For Each item In WScript.Arguments
  sh.CurrentDirectory = fso.GetParentFolderName(item)
  'working directory is now the parent folder of the current item

  '...
Next
假设工作目录将由放在脚本上的内容定义是一种错误的方法。如果您需要该逻辑,您可以自己在脚本中实现,例如:

Set fso = CreateObject("Scripting.FileSystemObject")
For Each item In WScript.Arguments
  WScript.Echo fso.GetParentFolderName(item)
Next
Set fso = CreateObject("Scripting.FileSystemObject")
Set sh  = CreateObject("WScript.Shell")
For Each item In WScript.Arguments
  sh.CurrentDirectory = fso.GetParentFolderName(item)
  'working directory is now the parent folder of the current item

  '...
Next
如果需要将工作目录作为VBScript文件的父目录,可以从以下属性派生:

Set fso = CreateObject("Scripting.FileSystemObject")
WScript.Echo fso.GetParentFolderName(WScript.ScriptFullName)

如果我在Windows注册表中查找文件类型,我会在其
Shell\Open\Command
值中看到以下内容:

  • batfile:
    %1%*
  • cmdfile:
    %1%*
  • exefile:
    %1%*
  • VBS文件:
    %SystemRoot%\System32\WScript.exe“%1”%*
这似乎表明,
bat
cmd
exe
本身被视为可执行文件,可能是出于历史原因,而VBS被认为是一个普通的脚本,它只是可执行的,因为它的扩展名注册了一些可执行文件来调用以解释它。与Python或Perl非常相似


[Update]事实上,我证明了Python脚本显示的行为与我的VBS脚本完全相同:从提供参数的命令行调用它会保留CWD,在其上删除文件会导致CWD
C:\Windows\System32
。所以我的问题似乎有点错误,但最终它帮助人们为我指出了进一步研究的正确方向…

在一些API监控之后,我看到了这一点

将文件放到
.exe
文件上时,
explorer.exe
使用API函数启动进程,将可执行文件作为
lpApplicationName
传递,将可执行文件和删除的文件作为
lpCommandLine
传递。调用方进程在函数调用中将
lpCurrentDirectory
设置为包含删除文件[1]的文件夹

将文件放到
.cmd
文件上时,
explorer.exe
也使用API,但在这种情况下,
lpApplicationName
null
lplCommandLine
包含批处理文件和删除的文件
lpCurrentDirectory
也设置为删除文件[1]的父文件夹

当您将文件放到
.vbs
文件上时,将使用该文件,并且结构的
lpDirectory
字段为
null
,因此,创建的进程将继承父进程的当前active directory。默认情况下,
explorer.exe
进程的当前active directory是
%systemroot%\system32
,但是可以使用不同的当前active directory启动
explorer
实例