2013-09-20 8 views
4

Я пытаюсь разбить строку в PowerShell, вызывая $ varname.split (','). Это отлично работает, когда я нахожусь в консоли PowerShell, но не тогда, когда я вызываю скрипт напрямую.Powershell String Splitting discrepency

из командной строки: powershell .\scriptname.ps1

Method invocation failed because [System.Object[]] doesn't contain a method named 'split'. 
At C:\scriptname.ps1:92 char:30 
+   reboot $varname.split <<<< (',') 
    + CategoryInfo   : InvalidOperation: (split:String) [], RuntimeException 
    + FullyQualifiedErrorId : MethodNotFound 

Опять же, это отлично работает, когда я запускаю его в ISE или непосредственно из PS строки. Мысли?

Редактировать: Я предоставил свой сценарий ниже. Я вроде как новый для powershell, поэтому я не вижу ничего, что могло бы привести к тому, что переменная будет вести себя как массив только при вызове через командную строку.

[string]$servers 
[string]$filepath 
[string]$account = $([System.Security.Principal.WindowsIdentity]::GetCurrent().Name) 
[string]$mode 
[bool] $reboot = $FALSE 

Write-Host "========================================" 
Write-Host "| Windows Server Shutdown Utility v1.0 |" 
Write-Host "========================================" 

Function usage(){ 
    Write-Host "Arguments are accepted in any order as long as the data follows the mode." 
    Write-Host "<required> [optional]" 
    Write-Host "Usage: powershell .\wss.ps1 <-l|-f> <data> [-account] [-reboot] [--help]" 
    Write-Host "`tModes" 
    Write-Host "`t`t-list: A list of servers, seperated by commas with no spaces inbetween" 
    Write-Host "`t`t`tAliases: -l" 
    Write-Host "`t`t`t[*] Example: `"ServerA.domain,ServerB.domain`"" 
    Write-Host "`t`t-file: A path to a file that contains one server name on each line" 
    Write-Host "`t`t`tAliases: -f" 
    Write-Host "`t`t`t[*] Example: `"C:\allDomainServers.txt`"" 
    Write-Host "`taccount: The domain and account to use. You will be prompted for a password." 
    Write-Host "`t`t`tAliases: -a, -ac" 
    Write-Host "`treboot: If specified, the servers will be shutdown instead of rebooted." 
    Write-Host "`t`t`tAliases: -r" 
    Write-Host "`thelp: Prints the help screen." 
    Write-Host "`t`t`tAliases: -h, -help, /help, /?" 
    Write-Host "`t`tNOTE: If no account is specified, the current user will be used." 

} 

Function shutdown($arr){ 
    $arr | ForEach{ 
     Write-Host "Attempting to shutdown $_" 
     Stop-Computer -computername ($_) -credential ($c) -force 
    } 
    Write-Host "Finished. Please be aware that some servers may still be in the process of shutting down." 
} 

Function reboot($arr){ 
    $arr | ForEach{ 
     Write-Host "Attempting to reboot $_" 
     Restart-Computer -computername ($_) -credential ($c) -force 
    } 
    Write-Host "Finished. Please be aware that some servers may still be in the process of rebooting." 
} 

#Parse Arguments 
if($args.length -eq 0 -or $args[0] -eq "-help" -or $args[0] -eq "/help" -or $args[0] -eq "--help" -or $args[0] -eq "/?"){ 
    usage 
    exit 
} 

for($i=0; $i -lt $args.length; $i++){ 
    $k = $args[$i] 
    if($k -eq "-r" -or $k -eq "-reboot"){ 
     $reboot = $TRUE 
    }elseif($k -eq "-a" -or $k -eq "-ac" -or $k -eq "-account"){ 
     $account = $args[++$i] 
    }elseif((!$mode) -and ($k -eq "-l" -or $k -eq "-list")){ 
     $servers = $args[++$i] 
     $mode = "list" 
    }elseif((!$mode) -and ($k -eq "-f" -or $k -eq "-file")){ 
     $filepath = $args[++$i] 
     $mode  = "file" 
    } 
} 

#Verify Account Credentials 
$c = get-credential $account 

if(!$c){ 
    Write-Host "No credentials specified!" 
    exit 
} 

if($mode -eq "list"){ 
    Write-Host "Using Mode: List" 
    if([string]::IsNullOrEmpty($servers)){ 
     usage 
     exit 
    } 

    if($reboot){ 
     reboot $servers.split(',') 
    }else{ 
     shutdown $servers.split(',') 
    } 

}elseif($mode -eq "file"){ 
    Write-Host "Using Mode: File" 
    if([string]::IsNullOrEmpty($filepath)){ 
     $filepath = Read-Host 'Enter the path to the file containing a list of hosts:' 
    } 

    if(!(Test-Path $filepath)){ 
     Write-Host "Error! File doesn't exist!" 
     exit 
    } 

    if($reboot){ 
     reboot (get-content $filepath) 
    }else{ 
     shutdown (get-content $filepath) 
    } 

}else{ 
    Write-Host "Unknown Mode! Got: $mode" 
    exit 
} 

Edit 2: Смотрите далее тестирование с помощью этого скрипта:

for($i=0; $i -lt $args.length; $i++){ 
    Write-Host $args[$i] 
    Write-Host $args[$i].GetType() 
} 

Powershell Подсказка:

PS C:\> .\test.ps1 asdf fdsa 
asdf 
System.String 
fdsa 
System.String 

PS C:\> .\test.ps1 "asdf,fdas" 
asdf,fdas 
System.String 

PS C:\> .\test.ps1 "asdf","fdas" 
asdf fdas 
System.Object[] 

PS C:\> .\test.ps1 asdf,fdas 
asdf fdas 
System.Object[] 

Командная строка:

C:\>powershell .\test.ps1 asdf fdsa 
asdf 
System.String 
fdsa 
System.String 

C:\>powershell .\test.ps1 "asdf,fdas" 
asdf fdas 
System.Object[] 

C:\>powershell .\test.ps1 "asdf","asdfa" 
asdf asdfa 
System.Object[] 

C:\>powershell .\test.ps1 asdf,fdas 
asdf fdas 
System.Object[] 

Notic e разница между тем, как он обрабатывает цитируемые строки (тест № 2). Почему это происходит? И есть ли способ обойти это?

ответ

1

Я смог исправить свою проблему, проверив, что указанный аргумент был строкой. Если он уже был массивом, он просто передавался функции. Это проверяется так:

if($servers -is [system.string]){ 
     $servers = $servers.split(',') 
} 
2

По какой-то причине, $ varname содержит массив при запуске в скрипте. И нет метода Split в массиве. Можете ли вы показать скрипт, в котором вы определяете значение, присвоенное $ varname? BTW, если массив содержит строку, которую вы хотите разбить, попробуйте это $varname[0].Split(',').

+0

Я добавил свой сценарий и тестовый пример. Мысли? – nlowe