Windows vbs脚本在86上工作,但在64上失败

Windows vbs脚本在86上工作,但在64上失败,windows,vbscript,x86,64-bit,Windows,Vbscript,X86,64 Bit,该脚本可以在x86上运行,但不能在x64上创建文件 有人能理解并解释原因吗 脚本正在搜索注册表,卸载注册表项,并检查displayname是否与我搜索的内容相同,然后获取productcode,并保存到一个文件,然后复制到我设置的远程共享 On error resume Next Dim strName, WshShell, oReg, keyname, WshNetwork, ComputerName Set fso = CreateObject("Scripting.FileSystem

该脚本可以在x86上运行,但不能在x64上创建文件

有人能理解并解释原因吗

脚本正在搜索注册表,卸载注册表项,并检查displayname是否与我搜索的内容相同,然后获取productcode,并保存到一个文件,然后复制到我设置的远程共享

On error resume Next

Dim strName, WshShell, oReg, keyname, WshNetwork, ComputerName

Set fso = CreateObject("Scripting.FileSystemObject")
Set WshShell = CreateObject("WScript.Shell")
Set WshNetwork = WScript.CreateObject("WScript.Network")

Const HKEY_LOCAL_MACHINE = &H80000002
Const ForReading = 1, ForWriting = 2, ForAppending = 8 

ComputerName = WshNetwork.ComputerName
FileName = ComputerName & "_data.txt"
'FileName = "sep_data.txt"

'=============================================
'Chage the value here with DisplayName's value 
strName = "Symantec Endpoint Protection"
'=============================================

'currentDirectory = Left(WScript.ScriptFullName,(Len(WScript.ScriptFullName))-(Len(WScript.ScriptName)))
currentDirectory = "c:\windows\temp\"




'set location in registry we want to get data from
Set oReg=GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & ComputerName & "\root\default:StdRegProv")
strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
oReg.EnumKey HKEY_LOCAL_MACHINE, strKeyPath, arrSubKeys

'check each key in uninstall for any display name called Symantec Endpoint Protection
For Each subkey In arrSubKeys
    keyname = ""
    keyname = wshshell.RegRead("HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\" & subkey & "\DisplayName")
    If keyname = strName then
        i = subkey
    End If



' Writes text to file if it exists
If i Then  


    'open text file for writing
    Set filetxt = fso.OpenTextFile(currentDirectory & FileName, 2, True) 


    'write to text file 
    filetxt.WriteLine "" & computerName & "," & i & ""


    'Close file
    filetxt.Close 

    'Copy file to network share
    fso.CopyFile "c:\windows\temp\" & FileName & "", "\\hostname\test\", true


End If
Next

Set WshShell = Nothing
Set ObjReg = Nothing
Set computerName = Nothing
Set i = Nothing

WScript.Quit
您可以找到原因(简而言之,注册表中的32位和64位有单独的结构,文件系统访问被重定向)

如果应用程序/注册表为32位,请使用32位脚本主机版本启动脚本(在64b操作系统版本中,32b可执行文件位于
%systemroot%\SysWOW64
下)

相反的问题是,您有一个32位的进程,但是您需要访问64位注册表,需要启动一个64位的进程,这里情况会发生变化

虽然
%systemroot%\System32
中的可执行文件是64位的,但由于当前进程是32位的,它在注册表和文件系统重定向下运行,并且对
%systemroot%\System32
的任何引用都转换为对
%systemroot%\SysWOW64
的引用(32位进程需要32位操作系统)。这可以通过使用

"%systemroot%\sysnative\cscript.exe" myscript.vbs
是的,如果从64位进程中搜索
sysnative
文件夹,您将找不到它,但从32位进程中,您可以访问64位
system32
文件夹

已编辑以包含变通方法。基本思想是尝试使用当前引擎查找所需信息。如果未找到,脚本将使用其他主机重新启动自身

Option Explicit 

Const HKEY_LOCAL_MACHINE = &H80000002

Const ForReading = 1 _ 
    , ForWriting = 2 _ 
    , ForAppending = 8 

Const UNINSTALL_KEY_PATH = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Const KEY_DISPLAY_NAME = "Symantec Endpoint Protection"
Const TARGET_FOLDER = "C:\TEMP"
Const ARGUMENT_FLAG = "_CHILD_"

Dim shell
    Set shell = WScript.CreateObject("WScript.Shell")

Dim retValue, alternateHost
    If Not WScript.Arguments.Named.Exists(ARGUMENT_FLAG) Then 
        retValue = shell.Run( quote(WScript.FullName) & " " & quote(WScript.ScriptFullName) & " /" & ARGUMENT_FLAG, 0, True )
        If retValue > 0 Then 
            With WScript.CreateObject("Scripting.FileSystemObject")
                If .GetFile( WScript.FullName ).ParentFolder.Name = "SysWOW64" Then 
                    alternateHost = "\sysnative\"
                Else 
                    alternateHost = "\SysWOW64\"
                End If 
                alternateHost = .BuildPath( shell.ExpandEnvironmentStrings("%systemroot%") & alternateHost, "cscript.exe" )
                If .FileExists( alternateHost ) Then 
                    Call shell.Run( quote(alternateHost) & " " & quote(WScript.ScriptFullName) & " /" & ARGUMENT_FLAG, 0, True )
                End If 
            End With 
        End If 
        WScript.Quit
    End If 

Dim reg    
    Set reg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

Dim subKeys, subKey, value, keyFound
    keyFound = False
    reg.EnumKey HKEY_LOCAL_MACHINE, UNINSTALL_KEY_PATH, subKeys
    For Each subKey In subKeys
        reg.GetStringValue HKEY_LOCAL_MACHINE, UNINSTALL_KEY_PATH & "\" & subkey , "DisplayName", value
        If Not IsNull( value ) Then 
            If value = KEY_DISPLAY_NAME Then 
                keyFound = True
                Exit For
            End If 
        End If 
    Next 

Dim computerName, baseName, fileName, exitCode
    If keyFound Then 
        computerName = WScript.CreateObject("WScript.Network").ComputerName
        baseName = computerName & "_data.txt"
        With WScript.CreateObject("Scripting.FileSystemObject")
            fileName = .BuildPath( shell.ExpandEnvironmentStrings("%temp%"), baseName ) 
            .CreateTextFile( fileName, True ).WriteLine( computerName & "," & KEY_DISPLAY_NAME )
            .CopyFile fileName, .BuildPath( TARGET_FOLDER, .GetFile( fileName ).Name )
        End With 
        exitCode = 0
    Else 
        exitCode = 1
    End If 

    Call WScript.Quit( exitCode )

Function quote( text ) 
    quote = """" & text & """"
End Function
您可以找到原因(简而言之,注册表中的32位和64位有单独的结构,文件系统访问被重定向)

如果应用程序/注册表为32位,请使用32位脚本主机版本启动脚本(在64b操作系统版本中,32b可执行文件位于
%systemroot%\SysWOW64
下)

相反的问题是,您有一个32位的进程,但是您需要访问64位注册表,需要启动一个64位的进程,这里情况会发生变化

虽然
%systemroot%\System32
中的可执行文件是64位的,但由于当前进程是32位的,它在注册表和文件系统重定向下运行,并且对
%systemroot%\System32
的任何引用都转换为对
%systemroot%\SysWOW64
的引用(32位进程需要32位操作系统)。这可以通过使用

"%systemroot%\sysnative\cscript.exe" myscript.vbs
是的,如果从64位进程中搜索
sysnative
文件夹,您将找不到它,但从32位进程中,您可以访问64位
system32
文件夹

已编辑以包含变通方法。基本思想是尝试使用当前引擎查找所需信息。如果未找到,脚本将使用其他主机重新启动自身

Option Explicit 

Const HKEY_LOCAL_MACHINE = &H80000002

Const ForReading = 1 _ 
    , ForWriting = 2 _ 
    , ForAppending = 8 

Const UNINSTALL_KEY_PATH = "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall"
Const KEY_DISPLAY_NAME = "Symantec Endpoint Protection"
Const TARGET_FOLDER = "C:\TEMP"
Const ARGUMENT_FLAG = "_CHILD_"

Dim shell
    Set shell = WScript.CreateObject("WScript.Shell")

Dim retValue, alternateHost
    If Not WScript.Arguments.Named.Exists(ARGUMENT_FLAG) Then 
        retValue = shell.Run( quote(WScript.FullName) & " " & quote(WScript.ScriptFullName) & " /" & ARGUMENT_FLAG, 0, True )
        If retValue > 0 Then 
            With WScript.CreateObject("Scripting.FileSystemObject")
                If .GetFile( WScript.FullName ).ParentFolder.Name = "SysWOW64" Then 
                    alternateHost = "\sysnative\"
                Else 
                    alternateHost = "\SysWOW64\"
                End If 
                alternateHost = .BuildPath( shell.ExpandEnvironmentStrings("%systemroot%") & alternateHost, "cscript.exe" )
                If .FileExists( alternateHost ) Then 
                    Call shell.Run( quote(alternateHost) & " " & quote(WScript.ScriptFullName) & " /" & ARGUMENT_FLAG, 0, True )
                End If 
            End With 
        End If 
        WScript.Quit
    End If 

Dim reg    
    Set reg = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\default:StdRegProv")

Dim subKeys, subKey, value, keyFound
    keyFound = False
    reg.EnumKey HKEY_LOCAL_MACHINE, UNINSTALL_KEY_PATH, subKeys
    For Each subKey In subKeys
        reg.GetStringValue HKEY_LOCAL_MACHINE, UNINSTALL_KEY_PATH & "\" & subkey , "DisplayName", value
        If Not IsNull( value ) Then 
            If value = KEY_DISPLAY_NAME Then 
                keyFound = True
                Exit For
            End If 
        End If 
    Next 

Dim computerName, baseName, fileName, exitCode
    If keyFound Then 
        computerName = WScript.CreateObject("WScript.Network").ComputerName
        baseName = computerName & "_data.txt"
        With WScript.CreateObject("Scripting.FileSystemObject")
            fileName = .BuildPath( shell.ExpandEnvironmentStrings("%temp%"), baseName ) 
            .CreateTextFile( fileName, True ).WriteLine( computerName & "," & KEY_DISPLAY_NAME )
            .CopyFile fileName, .BuildPath( TARGET_FOLDER, .GetFile( fileName ).Name )
        End With 
        exitCode = 0
    Else 
        exitCode = 1
    End If 

    Call WScript.Quit( exitCode )

Function quote( text ) 
    quote = """" & text & """"
End Function


我使用了另一种方法将文件移动到共享。64位操作系统丢失的原因是我的reg查询调用。最后缺少/reg64。

我使用了另一种方法将文件移动到共享。64位操作系统丢失的原因是我的reg查询调用。结尾处缺少/reg64。

下一步
缺少,请修复代码或粘贴整个脚本。您可以尝试在脚本的第一行调用
CheckOSx86x64Args
,如fixed,谢谢您指出。删除“下一步出错时继续”,现在您可以找到原因。我现在就试试,谢谢您!更新到follow我看到它在读取某些子键时有一些问题,这很好。我真的只针对一个关键,我知道有读访问权。我还可以尝试什么?
下一步
缺失,请修复代码,或粘贴整个脚本。您可以尝试在脚本的第一行调用
CheckOSx86x64Args
,如fixed,谢谢您指出。删除“下一步出错时继续”,现在您可以找到原因。我现在就试试,谢谢您!更新到follow我看到它在读取某些子键时有一些问题,这很好。我真的只针对一个关键,我知道有读访问权。我还可以尝试什么?我按照建议运行,但它在64位中仍然不起作用。如果我双击vbs文件,它会工作,但我通过SCCM或DesktopCentral或EXE/MSI运行它,它会失败。当然是奇怪的问题。@3264那么你的问题可能正好相反。请尝试使用
%windir%\sysnative\cscript.exe“myscript.vbs
检查一下。。是否更新为遵循sysnative?这对我来说是新的,我通常只使用
%SystemRoot%\System32\cscript.exe
@Lankymart,在文件系统重定向下,32位进程将看不到真正的64位
System32
。对
system32
的请求被重定向到我按照建议运行的
SysWoW64
,但它在64位中仍然不起作用。如果我双击vbs文件,它会工作,但我通过SCCM或DesktopCentral或EXE/MSI运行它,它会失败。当然是奇怪的问题。@3264那么你的问题可能正好相反。请尝试使用
%windir%\sysnative\cscript.exe“myscript.vbs
检查一下。。是否更新为遵循sysnative?这对我来说是新的,我通常只使用
%SystemRoot%\System32\cscript.exe
@Lankymart,在文件系统重定向下,32位进程将看不到真正的64位
System32
。对
system32
的请求被重定向到
SysWoW64