Powershell String Splitting discrepency
Solution 1
I was able to fix my problem by verifying that the specified argument was a string. If it was already an array, then it was just passed to the function. This is checked like so:
if($servers -is [system.string]){
$servers = $servers.split(',')
}
Solution 2
For whatever reason, $varname contains an array when you run it in a script. And there is no Split method on an array. Can you show the script where you determine the value assigned to $varname? BTW if the array contains a string you want to split, try this $varname[0].Split(',')
.
nlowe
Linux and Open Source enthusiast. I also like technical theater! Opinions are my own.
Updated on June 04, 2022Comments
-
nlowe almost 2 years
I am trying to split a string in PowerShell by calling $varname.split(','). This works fine when I am in a PowerShell console, but not when I invoke the script directly.
From the Command Prompt:
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
Again, this works perfectly fine when I run it in the ISE or directly from a PS prompt. Thoughts?
Edit: I've provided my script below. I'm sort of new to powershell, so I don't see anything that would cause a variable to behave as an array only when called through the commandline.
[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: See further testing using this script:
for($i=0; $i -lt $args.length; $i++){ Write-Host $args[$i] Write-Host $args[$i].GetType() }
Powershell Prompt:
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[]
Command Prompt:
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[]
Notice the difference between how it treats quoted strings (test # 2). Why is this happening? And is there any way around this?