VBScript出现HTA和类型不匹配错误的奇怪问题

VBScript出现HTA和类型不匹配错误的奇怪问题,vbscript,hta,type-mismatch,Vbscript,Hta,Type Mismatch,当我通过双击自己运行下面的脚本时,它运行得很好。它按预期返回上次登录的用户。但是,当我从作为所有脚本前端开发的HTA运行它时,在“wscript.echo strvalue”行上会出现一个类型不匹配错误。我已经尽了一切努力让它工作,比如将mshta.exe上的权限更改为完全控制自己。我只是不能让它从HTA运行而不出错,但它自己可以100%按预期工作。我完全被难住了 strinput = "myserver" Set objRegistry = GetObject("winmgmts:{imper

当我通过双击自己运行下面的脚本时,它运行得很好。它按预期返回上次登录的用户。但是,当我从作为所有脚本前端开发的HTA运行它时,在“wscript.echo strvalue”行上会出现一个类型不匹配错误。我已经尽了一切努力让它工作,比如将mshta.exe上的权限更改为完全控制自己。我只是不能让它从HTA运行而不出错,但它自己可以100%按预期工作。我完全被难住了

strinput = "myserver"
Set objRegistry = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & _ 
strinput & "\root\default:StdRegProv")
 strKeyPath = "SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI"
strValueName = "LastLoggedOnUser"
 objRegistry.GetStringValue HKEY_LOCAL_MACHINE, strKeyPath, strValueName, strValue
 Wscript.Echo strValue
使用而不是
Wscript.Echo
方法。HTA使用Internet Explorer脚本对象模型,该模型不包含
Wscript
对象(该对象属于)

阅读:

你可能已经注意到了,当你要向我汇报 操作系统版本我们使用VBScript Msgbox函数,而不是 而不是更常见的Wscript.Echo。我们为什么不使用Wscript.Echo? 原因如下:

事实证明,各种Wscript方法——Wscript.Echo, Wscript.Sleep、Wscript.Quit等都是专为在以下环境下运行而设计的 Windows脚本主机环境。当我们在HTA工作时 我们不是在WSH下运行;相反,我们在MSHTA下运行 过程因此,我们无法使用Wscript方法 (我们也不能创造它们)。因此,我们需要找到解决问题的办法 每种方法,Msgbox都完全可以替代 Wscript.Echo。(我们将讨论其他方法的变通方法,例如 作为Wscript.Sleep—当我们找到它们时。)

这个故事的寓意是:不要为Wscript.Echo操心;这行不通

编辑:使用
Wscript.Echo TypeName(strValue)&vbNewLine&VarType(strValue)

在一个简单的
HTA
中进行了尝试,得到了相同(不同)的结果

==> C:\Windows\SysWOW64\mshta.exe 33505295.hta
结论。检查
HTA
文件类型关联。例如,在我的Windows 8(64位)中,
ftype htafile
返回的值(令人惊讶?)与双击时导致错误行为的值相同:

==> assoc .hta
.hta=htafile

==> ftype htafile
htafile=C:\Windows\SysWOW64\mshta.exe "%1" {1E460BD7-F1C3-4B2E-88BF-4E770A288AF5}%U{1E460BD7-F1C3-4B2E-88BF-4E770A288AF5} %*    

默认情况下,Windows 64位使用
MSHTA.EXE
32位。注册表有一个用于64位和32位应用程序的单独分支,因此WMI无法找到您要查找的注册表值。 将下面的代码保存到e。g
C:\test\tmp.hta
,通过双击(默认为32位)尝试从资源管理器启动它-您将获得
null
,然后通过运行对话框(Win+R)启动,路径为:
%windir%\system32\mshta.exe“C:\test\tmp.hta”
(64位),结果将是您的用户名


子窗口_onload()
Const HKEY_本地_机器=&H8000002
设置objRegistry=GetObject(“winmgmts:{impersonationLevel=impersonate}!\\。\root\default:StdRegProv”)
strKeyPath=“SOFTWARE\Microsoft\Windows\CurrentVersion\Authentication\LogonUI”
strValueName=“LastLoggedOnUser”
objRegistry.GetStringValue HKEY_LOCAL_机器,strKeyPath,strValueName,strValue
document.body.innerText=strValue
端接头

请注意,脚本中的许多其他内容取决于应用程序体系结构,例如。GActiveX的数量仅在32位版本中可用,因此它们应该通过
%windir%\SysWOW64\
(Windows 64位子系统上的Windows 32位)启动。

几周前我遇到了同样的挑战。 以下代码使我能够查看当前登录到远程计算机的用户

我希望这能帮助你

Sub ActionGetCurrentUser(strCPU) 'strCPU is the computername
set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strCPU & "\root\cimv2")
    set Items = objWMI.ExecQuery("Select * From Win32_ComputerSystem")

    For Each obj in Items
        OutStr = right(obj.username,9)
    Next

    Resultstring = "Logged in User is: " & OutStr   

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    strTarget = "LDAP://" & strDNSDomain
' ---------------- Write the User's account & password to a variable -------------------
    strCurrentuser = Currentuser.value
    strPassword = PasswordArea.value
' ---------------- Connect to Ad Provider ----------------
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Properties("User ID") = strCurrentUser     ' pass credentials - if you omit this, the search is performed....
    objConnection.Properties("Password") = strPassword       ' ... with the current credentials
    objConnection.Properties("Encrypt Password") = True      ' only needed if you set "User ID" and "Password"
    objConnection.Open "Active Directory Provider"
    Set objCmd =   CreateObject("ADODB.Command")
    Set objCmd.ActiveConnection = objConnection 

    objCmd.CommandText = "SELECT DisplayName FROM '" & strTarget & "' WHERE extensionAttribute11 = '" & OutStr & "'"    

    Const ADS_SCOPE_SUBTREE = 2
    objCmd.Properties("Page Size") = 100
    objCmd.Properties("Timeout") = 30
    objCmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE
    objCmd.Properties("Cache Results") = False

    Set objRecordSet = objCmd.Execute

    If objRecordset.Recordcount = 0 then    ' If no user is found then the recordcount will be 0
        msgbox "No user is logged on"
        Resultstring = ""
        Set objCmd = Nothing
        Set objRootDSE = Nothing
        Set objRecordSet = Nothing
        Set objWMI = Nothing
        Set Items = Nothing
        exit sub
    End if

    Set objRecordSet = objCmd.Execute

    objRecordSet.MoveFirst

    Resultstring = Resultstring & vbcrlf & "Name: " & objRecordset.fields("DisplayName")        

    Msgbox Resultstring

    Resultstring = ""

    Set objCmd = Nothing
    Set objRootDSE = Nothing
    Set objRecordSet = Nothing
    Set objWMI = Nothing
    Set Items = Nothing
End Sub

不起作用。当我将'wscript.echo strvalue'更改为'msgbox strvalue'时,我遇到了另一个错误:在我更改的行上无效使用Null:strvalue代码:800A005E。再次通过双击运行脚本可以正常工作。通过HTA运行脚本会返回该错误。我忘记在原始代码中包含常量。但它已经在那里了。同样,双击也可以正常工作,但通过HTA返回一个错误。为什么它会用一种方法而不是另一种?毫无意义,就是这样!谢谢
==> assoc .hta
.hta=htafile

==> ftype htafile
htafile=C:\Windows\SysWOW64\mshta.exe "%1" {1E460BD7-F1C3-4B2E-88BF-4E770A288AF5}%U{1E460BD7-F1C3-4B2E-88BF-4E770A288AF5} %*    
Sub ActionGetCurrentUser(strCPU) 'strCPU is the computername
set objWMI = GetObject("winmgmts:{impersonationLevel=impersonate}!\\" & strCPU & "\root\cimv2")
    set Items = objWMI.ExecQuery("Select * From Win32_ComputerSystem")

    For Each obj in Items
        OutStr = right(obj.username,9)
    Next

    Resultstring = "Logged in User is: " & OutStr   

    Set objRootDSE = GetObject("LDAP://RootDSE")
    strDNSDomain = objRootDSE.Get("defaultNamingContext")
    strTarget = "LDAP://" & strDNSDomain
' ---------------- Write the User's account & password to a variable -------------------
    strCurrentuser = Currentuser.value
    strPassword = PasswordArea.value
' ---------------- Connect to Ad Provider ----------------
    Set objConnection = CreateObject("ADODB.Connection")
    objConnection.Provider = "ADsDSOObject"
    objConnection.Properties("User ID") = strCurrentUser     ' pass credentials - if you omit this, the search is performed....
    objConnection.Properties("Password") = strPassword       ' ... with the current credentials
    objConnection.Properties("Encrypt Password") = True      ' only needed if you set "User ID" and "Password"
    objConnection.Open "Active Directory Provider"
    Set objCmd =   CreateObject("ADODB.Command")
    Set objCmd.ActiveConnection = objConnection 

    objCmd.CommandText = "SELECT DisplayName FROM '" & strTarget & "' WHERE extensionAttribute11 = '" & OutStr & "'"    

    Const ADS_SCOPE_SUBTREE = 2
    objCmd.Properties("Page Size") = 100
    objCmd.Properties("Timeout") = 30
    objCmd.Properties("Searchscope") = ADS_SCOPE_SUBTREE
    objCmd.Properties("Cache Results") = False

    Set objRecordSet = objCmd.Execute

    If objRecordset.Recordcount = 0 then    ' If no user is found then the recordcount will be 0
        msgbox "No user is logged on"
        Resultstring = ""
        Set objCmd = Nothing
        Set objRootDSE = Nothing
        Set objRecordSet = Nothing
        Set objWMI = Nothing
        Set Items = Nothing
        exit sub
    End if

    Set objRecordSet = objCmd.Execute

    objRecordSet.MoveFirst

    Resultstring = Resultstring & vbcrlf & "Name: " & objRecordset.fields("DisplayName")        

    Msgbox Resultstring

    Resultstring = ""

    Set objCmd = Nothing
    Set objRootDSE = Nothing
    Set objRecordSet = Nothing
    Set objWMI = Nothing
    Set Items = Nothing
End Sub