4

昇格モードで vbscript を実行する方法を学習しようとしています。昇格して実行しようとしているvbscriptに引数がある場合、これをうまく機能させることができません。

以下に簡単な例を示します。

OSVersion.vbs

' Return a string indicating the operating system
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
   & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colOperatingSystems = objWMIService.ExecQuery _
   ("Select * from Win32_OperatingSystem")

'Wscript.echo Wscript.Arguments(0)
For Each objOperatingSystem in colOperatingSystems
   Wscript.StdOut.Write objOperatingSystem.Caption
   Wscript.StdOut.WriteBlankLines(1)
   Wscript.StdOut.Write "Version " & objOperatingSystem.Version
Next

RunElevated.vbs

' Run the script in elevated mode
'
' This will be needed to install programs into Program Files
prgName      = Wscript.Arguments.Item(0)
prgArgs      = ""
If Wscript.Arguments.Count > 1 Then
   For i = 1 To Wscript.Arguments.Count - 1
      prgArgs = prgArgs & " " & Wscript.Arguments.Item(i)
   Next
End If
Wscript.echo "Running: " & prgName & prgArgs
Set objShell = CreateObject("Shell.Application")
Set fso      = CreateObject("Scripting.FileSystemObject")
strPath      = fso.GetParentFolderName (WScript.ScriptFullName)
If fso.FileExists(strPath & "\" & prgName) Then
   objShell.ShellExecute "wscript.exe", _
     Chr(34) & strPath & "\" & prgName & Chr(34), _
     "", "runas", 1
Else
   Wscript.echo "Script file not found"
End If 

OSVersion.vbs スクリプトは正常に実行されます。

cscript OSVersion.vbs Microsoft (R) Windows Script Host バージョン 5.8 Copyright (C) Microsoft Corporation. 全著作権所有。

Microsoft Windows 7 ホーム プレミアム

バージョン 6.1.7601

問題 #1 この管理者特権で実行しようとすると、stdout に何も表示されない

C:\Users\ChemModeling\Documents\FreeThink\Java\install>cscript RunElevated.vbs OSVersion.vbs Microsoft (R) Windows Script Host バージョン 5.8 Copyright (C) Microsoft Corporation. 全著作権所有。

実行中: OSVersion.vbs

問題 2 RunElevated に渡すスクリプトに引数を含める方法がわかりません。「ここに私のパラメーター」のような構文を使用する必要があると読んだので、これを試しました:

' Run the script in elevated mode
'
' This will be needed to install programs into Program Files
prgName      = Wscript.Arguments.Item(0)
prgArgs      = ""
If Wscript.Arguments.Count > 1 Then
   For i = 1 To Wscript.Arguments.Count - 1
      prgArgs = prgArgs & " " & Wscript.Arguments.Item(i)
   Next
End If
Wscript.echo "Running: " & prgName & prgArgs
Set objShell = CreateObject("Shell.Application")
Set fso      = CreateObject("Scripting.FileSystemObject")
strPath      = fso.GetParentFolderName (WScript.ScriptFullName)
If fso.FileExists(strPath & "\" & prgName) Then
   objShell.ShellExecute "wscript.exe", _
     Chr(39) & Chr(34) & strPath & "\" & prgName & prgArgs & Chr(34) & Chr(39), _
     "", "runas", 1
Else
   Wscript.echo "Script file not found"
End If 

私が実行した場合:

cscript RunElevated.vbs OSVersion.vbs Test Microsoft (R) Windows Script Host バージョン 5.8 Copyright (C) Microsoft Corporation. 全著作権所有。

実行中: OSVersion.vbs テスト

次に、「ファイル拡張子 ".vbs Test" のエンジンがありません」というエラーが表示されます。

誰が私が変更する必要があるかを提案できますか?

私はこの問題を解決するためにいくらか前進しました-

最初のスクリプトを次のように変更しました。

OSVersion.vbs

' Return a string indicating the operating system
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
   & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colOperatingSystems = objWMIService.ExecQuery _
   ("Select * from Win32_OperatingSystem")

'Wscript.echo Wscript.Arguments(0)
For Each objOperatingSystem in colOperatingSystems
   Wscript.Echo objOperatingSystem.Caption
   Wscript.Echo "Version " & objOperatingSystem.Version
Next

だから私は実際に何かが起こったかどうかを見ることができました.

2 番目のスクリプトを次のように変更しました。

' Run the script in elevated mode
'
' This will be needed to install programs into Program Files
prgName      = Wscript.Arguments.Item(0)
prgArgs      = ""
If Wscript.Arguments.Count > 1 Then
   For i = 1 To Wscript.Arguments.Count - 1
      prgArgs = prgArgs & " " & Wscript.Arguments.Item(i)
   Next
End If
Wscript.echo "Running: " & prgName & prgArgs
Set objShell = CreateObject("Shell.Application")
Set fso      = CreateObject("Scripting.FileSystemObject")
strPath      = fso.GetParentFolderName (WScript.ScriptFullName)
If fso.FileExists(strPath & "\" & prgName) Then
   objShell.ShellExecute "wscript.exe", _
     Chr(34) & strPath & "\" & prgName & Chr(34) & prgArgs, _
     "", "runas", 1
Else
   Wscript.echo "Script file not found"
End If 

および使用: wscript RunElevated.vbs OSVersion.vbs Test

そして今、スクリプトの実行時にポップアップにエコーしている情報が表示されます。

問題 1 に戻ります。管理者モードで実行する新しいシェルを開始しているので、cscript に切り替えて情報を stdout に書き込もうとしたり、Wscript.StdOut.Write を使用したりすると、新しいシェルに表示されます。そして、私はそれを見ることはありません、または少なくともそれが問題だと私が信じていることです.

この問題に対処する標準的な方法はありますか?

4

2 に答える 2

5

問題#1:

RunElevated.vbs スクリプトは WScript.exe を使用して OSVersion.vbs スクリプトを再起動するため、スクリプトを管理者特権で実行しても出力は表示されません。OSVersion.vbs は、コンソールからのみ利用できる標準の入力と出力を使用します。RunElevated.vbs のコマンド ラインを wscript.exe の代わりに cscript.exe を使用するように変更すると、この問題が解決します。詳細については、私の記事「エラー トラップと WSH でのサード パーティの出力のキャプチャ」を参照してください。

問題#2

ここでの問題は、さまざまな種類の引用符を混在させていることです。コマンドは次のようになります。

「C:\パス スペースあり\command.exe」「スペースありパラメータ」「その他」

これらのスクリプトを試してください。

RunElevated.vbs

' Run a script in Elevated Mode
strName      = WScript.Arguments.Item(0)
strArgs      = ""
If WScript.Arguments.Count > 1 Then
    For i = 1 To WScript.Arguments.Count - 1
        strArgs = strArgs & " " & WScript.Arguments.Item(i)
    Next
End If
WScript.echo "Running: ", strName, strArgs
Set objShell = CreateObject("Shell.Application")
Set objFso   = CreateObject("Scripting.FileSystemObject")
strPath      = objFso.GetParentFolderName(WScript.ScriptFullName)
strParams    = Chr(34) & strPath & "\" & strName & Chr(34)
If strArgs <> "" Then
    strParams = strParams & " " & Chr(34) & strArgs & Chr(34)
End If
If objFso.FileExists(strPath & "\" & strName) Then
     objShell.ShellExecute "cscript.exe", strParams, "", "runas", 1
Else
    WScript.echo "Script file not found"
End If

OSVersion.vbs

'Test passing arguments to launched script
If WScript.Arguments.Count > 0 Then
    For i = 0 To WScript.Arguments.Count - 1
        strArgs = Trim(strArgs & " " & WScript.Arguments.Item(i))
    Next
End If

' Return a string indicating the operating system
strComputer = "."
Set objWMIService = GetObject("winmgmts:" _
    & "{impersonationLevel=impersonate}!\\" & strComputer & "\root\cimv2")

Set colOperatingSystems = objWMIService.ExecQuery _
    ("Select * from Win32_OperatingSystem")

For Each objOperatingSystem in colOperatingSystems
    WScript.StdOut.Write objOperatingSystem.Caption
    WScript.StdOut.WriteBlankLines(1)
    WScript.StdOut.Write "Version " & objOperatingSystem.Version
    WScript.StdOut.WriteBlankLines(2)
Next

' Print out any passed arguments
WScript.StdOut.WriteBlankLines(2)
WScript.StdOut.Write strArgs
WScript.StdOut.WriteBlankLines(2)

' Keep the window from closing before you get a chance to read it
WScript.StdOut.Write "Press any key to continue "
strInput = WScript.StdIn.Read(1)

出力をキャプチャするために、WshShellExecuteメソッドを使用して別のアプローチを試みることになるでしょう。昇格された特権でコマンド ラインを起動できるElevateHStartなどの利用可能なコマンド ライン ツールがあります。Elevateを使用してそれを行う方法は次のとおりです。

' Run a script in Elevated Mode
strName      = WScript.Arguments.Item(0)
strArgs      = ""
If WScript.Arguments.Count > 1 Then
    For i = 1 To WScript.Arguments.Count - 1
        strArgs = strArgs & " " & WScript.Arguments.Item(i)
    Next
End If
WScript.echo "Running: ", strName, strArgs
Set WshShell = CreateObject("WScript.Shell")
Set objFso   = CreateObject("Scripting.FileSystemObject")
strPath      = objFso.GetParentFolderName(WScript.ScriptFullName)
strParams    = Chr(34) & strPath & "\" & strName & Chr(34)
If strArgs <> "" Then
    strParams = strParams & " " & Chr(34) & strArgs & Chr(34)
End If
If objFso.FileExists(strPath & "\" & strName) Then
    Set WshShellExec = WshShell.Exec("elevate cscript.exe " & strParams)

    Select Case WshShellExec.Status
        Case WshFinished
            strOutput = WshShellExec.StdOut.ReadAll
        Case WshFailed
            strOutput = WshShellExec.StdErr.ReadAll
    End Select
Else
    WScript.echo "Script file not found"
End If

WScript.echo strOutput
于 2012-07-22T17:16:54.473 に答える
1

私は 2 つの興味深いことを発見しました。まず、適切な数の引用符とスペースを取得する必要がありました。次に、最初に暫定スクリプトを実際に呼び出してから、昇格した最終スクリプトを呼び出す必要がありました。

初期呼び出しスクリプト スニペット:

If objFSO.FileExists("C:\Windows\System32\elevate.vbs") Then
     objWSHShell.ShellExecute "wscript.exe", Chr(34) & Chr(34) & "C:\Windows\System32\elevate.vbs" & Chr(32) & strCampus & Chr(32) & strLocation & Chr(32) & strAssetTag & Chr(34) & Chr(34), "", "", 1
Else
     MsgBox "Regbrand script file not found",0,"Error Message"
End If

Chr() ステートメントと、元のスクリプトから中間スクリプトに渡される 3 つの変数に注意してください。

中間スクリプト スニペット:

If Args.Count = 0 Then
    MsgBox "Missing arguments to UAC permissions script.",0,"Missing Parameters"
Else
    strCampus = Args.Item(0)
    strLocation = Args.Item(1)
    strAssetTag = Args.Item(2)

    strFilePath = objFSO.GetParentFolderName (WScript.ScriptFullName)
    If objFSO.FileExists("C:\Windows\System32\regbrand.vbs") Then
         objWSHShell.ShellExecute "wscript.exe", Chr(34) & Chr(34) & "C:\Windows\System32\regbrand.vbs" & Chr(32) & strCampus & Chr(32) & strLocation & Chr(32) & strAssetTag & Chr(34) & Chr(34), "", "runas", 1
    Else
         MsgBox "Script file not found",0,"Error Message"
    End If
End If

中間スクリプトでは、同じ引数を最終スクリプトに渡します。ここでも、Chr() ステートメントに注意してください。

最初のスクリプトは 3 つの引数を渡し、中間スクリプトを呼び出します。中間スクリプトは、昇格された権限で 3 番目のスクリプト「regbrand.vbs」を呼び出します。本来のように機能します。中間スクリプトを削除すると、機能しませんでした。私はまだそれを理解していませんが、ネットワーク上の場所から元のスクリプトを呼び出すことに関係があると考えています。ただし、パラメーターを呼び出して渡すための構文が役立つことを願っています。

于 2013-01-29T19:49:53.127 に答える