2015-06-28 17 views
6

Esiste un elenco di argomenti %* (file batch) o $* (script di bash) equivalente per VBScript?

Desidero recuperare l'esatto richiamo della riga di comando.

esempio inventato:

cscript //nologo script.vbs /arg1:a -s "a b" 1 c /arg2:"x y" "d e" -l '3 4' 

dovrebbe restituire:

/arg1:a -s "a b" 1 c /arg2:"x y" "d e" -l '3 4' 

(comprese le virgolette).

Ho visto WScript.Arguments ma non restituisce la riga di comando verbatim.

risposta

0

Non ce n'è uno. Ma è abbastanza banale.

For each ag in wscript.arguments 
    CMDLINE = CMDLINE & " " & ag 
Next 
wscript.echo mid(CMDLINE, 2) 

o

For each ag in wscript.arguments 
    If Instr(Ag, " ") = True then 
     CMDLINE = CMDLINE & " " & Chr(34) & ag & Chr(34) 
    Else 
     CMDLINE = CMDLINE & " " & ag 
    End if 
Next 
wscript.echo mid(CMDLINE, 2) 

E

C:\Users\User>cscript //nologo "C:\Users\User\Desktop\New Text Document (3).vbs" cat dog "mouse and cat" 
cat dog mouse and cat 

Questo vale per VBScript e VBA.

Entrambe queste informazioni di base sono ospitate da altri programmi. È l'host che raccoglie informazioni sulla riga di comando (se presenti). È l'host che lo rende disponibile alle vbs tramite un oggetto nel caso di wscript, ma non quando è ospitato in IE/IIS. E VBA ha una funzione implementata dall'host (implementata da Corel Office, Microsoft Office e VB6).

Function Declaration 
Function Command() As Variant 
Function Command$() As String 
Runtime Semantics. 
Returns the argument portion of the implementation dependent command used to initiate execution of the currently executing VBA program. 
The runtime semantics of Command$ are identical to those of Command with the exception that the declared type of the return value is String rather than Variant. 

Sotto il cofano (ho rimosso alcun paragrafi comportamento parsing) (e notare le differenze/Unicode ANSI)

CommandLineToArgvW funzione


Analizza una stringa e ritorna a riga di comando Unicode una serie di stringhe Unicode con terminazione null contenenti i singoli argomenti trovati in tale riga di comando e un conteggio di argomenti, simile ai valori di argv di runtime C standard e ai valori di argc.

sintassi

LPWSTR *CommandLineToArgvW(   LPCWSTR lpCmdLine, 
    int *pNumArgs 
); 

Parametri

Questa funzione accetta righe di comando che contengono il nome del programma che si sia racchiuso tra virgolette o meno racchiuso tra virgolette.

CommandLineToArgvW ha una speciale interpretazione dei caratteri di barra rovesciata quando sono seguiti da un carattere di virgolette ("), come segue:

backslash
  • 2n seguita da una virgoletta produrre n backslash seguita da una citazione mark

    (2n) + 1 barre rovesciate seguite da una virgoletta producono nuovamente n barre inverse seguite da virgolette.

    n rovesciate non seguite da virgolette producono semplicemente n. barre rovesciate.

GetCommandLine

recupera la stringa di riga di comando per il processo corrente.

LPTSTR WINAPI GetCommandLine(void); 

processi di console ANSI scritti in C possono utilizzare gli argomenti argc e argv della funzione principale per accedere gli argomenti della riga di comando. Le applicazioni GUI ANSI possono utilizzare il parametro lpCmdLine della funzione WinMain per accedere alla stringa della riga di comando, escluso il nome del programma. Il motivo per cui main e WinMain non possono restituire stringhe Unicode è che argc, argv e lpCmdLine utilizzano il tipo di dati LPSTR per i parametri, non il tipo di dati LPTSTR. La funzione GetCommandLine può essere utilizzata per accedere alle stringhe Unicode, poiché utilizza il tipo di dati LPTSTR.

Per convertire la riga di comando in una matrice di stringhe in stile argv, chiamare la funzione CommandLineToArgvW.

Nota Il nome dell'eseguibile nella riga di comando che il sistema operativo fornisce a un processo non è necessariamente identico a quello nella riga di comando che il processo chiamante attribuisce alla funzione CreateProcess. Il sistema operativo può anteporre un percorso completo a un nome eseguibile fornito senza un percorso completo.

+2

Gli argomenti con spazi devono essere citati. –

+2

'Instr (Ag," ") = True' viola la regola" Non confrontare mai con True/False "(http://blogs.msdn.com/b/ericlippert/archive/2004/07/15/184431.aspx) . –

+0

Anche il secondo blocco di codice richiede un 'End If'. – Bond

6

Non esiste un valore equivalente a %* o $* in VBScript. La collezione WScript.Arguments nasconde la riga di comando di input, dando accesso agli argomenti come elementi all'interno delle raccolte.

L'unico modo che conosco per recuperare le informazioni richieste è eseguire una query su WMI per il processo corrente e dalle informazioni sul processo leggere la riga di comando.

Questo ti darà l'intera riga di comando utilizzata per avviare lo script corrente.

Option Explicit 

' We need a child process to locate the current script. 
Const FLAG_PROCESS = "winver.exe" 

' WMI constants 
Const wbemFlagForwardOnly = 32 

' Generate a unique value to be used as a flag 
Dim guid 
    guid = Left(CreateObject("Scriptlet.TypeLib").GUID,38) 

' Start a process using the indicated flag inside its command line 
    WScript.CreateObject("WScript.Shell").Run """" & FLAG_PROCESS & """ " & guid, 0, False 

' To retrieve process information a WMI reference is needed  
Dim wmi 
    Set wmi = GetObject("winmgmts:{impersonationLevel=impersonate}!\\.\root\cimv2") 

' Query the list of processes with the flag in its command line, retrieve the 
' process ID of its parent process (our script!) and terminate the process 
Dim colProcess, process, myProcessID 
    Set colProcess = wmi.ExecQuery(_ 
     "SELECT ParentProcessID From Win32_Process " & _ 
     "WHERE Name='" & FLAG_PROCESS & "' " & _ 
     "AND CommandLine LIKE '%" & guid & "%'" _ 
     ,"WQL" , wbemFlagForwardOnly _ 
    ) 
    For Each process In colProcess 
     myProcessID = process.ParentProcessID 
     process.Terminate 
    Next 

' Knowing the process id of our script we can query the process list 
' and retrieve its command line 
Dim commandLine 
    set colProcess = wmi.ExecQuery(_ 
     "SELECT CommandLine From Win32_Process " & _ 
     "WHERE ProcessID=" & myProcessID _ 
     ,"WQL" , wbemFlagForwardOnly _ 
    ) 
    For Each process In colProcess 
     commandLine = process.CommandLine 
    Next 

' Done 
    WScript.Echo commandLine 
+0

Questa è una buona idea. Ma generare e terminare un nuovo processo ed eseguire due query WMI sembra proprio eccessivo rispetto alla semplice concatenazione delle stringhe nella raccolta 'WScript.Arguments'. – Bond

+2

@Bond, sì, non è il modo più semplice per farlo, ma concatenare gli argomenti non vedrà la differenza tra '/ test:" data "' e '/ test: data' o'/test: "da" " ta "'. Oppure '/ test:" da \ "ta" 'e'/test: "da \ ta" '. La raccolta di argomenti rimuove qualsiasi virgolette doppie e OP indica che le citazioni devono essere incluse –

+1

Hai ragione. (Anche se OP dovrebbe capire come funzionano gli arg in WSH e cercare di evitare quei tipi di situazioni per cominciare). – Bond