जब कोई कॉल केवल एक वस्तु लौटाती है तो मैं एक सरणी वापस करने के लिए पॉवर्स को कैसे मजबूर कर सकता हूं?


123

मैं वेब सर्वर पर IIS बाइंडिंग सेट करने के लिए Powershell का उपयोग कर रहा हूं, और निम्न कोड के साथ समस्या हो रही है:

$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

if ($serverIps.length -le 1) {
    Write-Host "You need at least 2 IP addresses for this to work!"
    exit
}

$primaryIp = $serverIps[0]
$secondaryIp = $serverIps[1]

यदि सर्वर पर 2+ आईपी हैं, तो ठीक है - पॉवरशेल एक सरणी देता है, और मैं सरणी लंबाई को क्वेरी कर सकता हूं और पहले और दूसरे पते को ठीक कर सकता हूं।

समस्या यह है - यदि केवल एक IP है, तो Powershell एक-तत्व सरणी नहीं लौटाता है, यह IP पता (एक स्ट्रिंग के रूप में, "192.168.0.100") लौटाता है - स्ट्रिंग में एक .lengthगुण है, यह 1 से अधिक है, इसलिए परीक्षण पास हो जाता है, और मैं संग्रह में पहले दो आईपी पतों के बजाय, स्ट्रिंग में पहले दो पात्रों के साथ समाप्त होता हूं।

मैं या तो पॉवर्स को एक-तत्व संग्रह को वापस करने के लिए कैसे मजबूर कर सकता हूं, या वैकल्पिक रूप से यह निर्धारित कर सकता है कि संग्रह के बजाय "वस्तु" लौटाया गया ऑब्जेक्ट है?


28
PowerShell का सबसे एकल-कष्टप्रद कष्टप्रद / बग-ग्रस्त पहलू ..
user2864740

मैं आपके उदाहरण को अधूरा मानता हूं। सरल प्रश्न: << $ x = गूंज हैलो; $ x -is [ऐरे] >> उपज गलत।
राउल सालिनास-मोंटेगुडो

क्या यह व्यवहार शक्तियां 5 में बदला गया था? मुझे एक समान मुद्दा मिला है कि मैं 5 पर पुन: पेश नहीं कर सकता, लेकिन 4 पर कर सकता हूं
NickL

जवाबों:


143

चर को दो तरीकों में से एक में परिभाषित करें ...

@शुरुआत में अपने पाइप्ड कमांड्स को कोष्ठक में लपेटें :

$serverIps = @(gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort)

सरणी के रूप में डेटा प्रकार निर्दिष्ट करें:

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

या, चर के डेटा प्रकार की जाँच करें ...

IF ($ServerIps -isnot [array])
{ <error message> }
ELSE
{ <proceed> }

28
@(...)शून्य ऑब्जेक्ट्स होने पर भी एक कमांड लपेटने से एक सरणी वापस आ जाएगी। जबकि [Array]शून्य-ऑब्जेक्ट होने पर भी -typed चर के परिणाम को असाइन करना अभी भी $ null वापस आ जाएगा।
निक

1
बस ध्यान दें कि यदि कोई वस्तु वापस नहीं आ रही है तो इनमें से कोई भी समाधान काम नहीं करता है।
घातक-बघेल

2
@ घातक-बघेल क्या आप इसका उदाहरण दिखा सकते हैं? मेरे @(...)लिए किसी भी प्रकार की वस्तुओं के लिए ठीक से काम करना (परिणाम मैं उम्मीद करता हूं कि यह उत्पादन करना चाहिए) का उत्पादन करें।
user4003407

1
मजेदार है कि कैसे आप एक ही सवाल पर वापस समाप्त। मेरे पास (और फिर से) थोड़ी अलग समस्या थी, हां सवाल में यह ठीक काम करता है लेकिन जब एक समारोह से लौटते हैं तो यह एक अलग कहानी है। यदि एक तत्व है, तो सरणी को नजरअंदाज कर दिया जाता है और केवल उस तत्व को लौटा दिया जाता है। यदि आप वैरिएबल से पहले अल्पविराम लगाते हैं, तो यह एक सरणी के लिए मजबूर करता है, लेकिन एक बहु-तत्व सरणी फिर दो-आयामी सरणी लौटाएगा। बहुत थकाऊ है।
घातक-बगेल

1
हां, पिछली बार भी यही हुआ था, अब मैं इसे दोहरा नहीं सकता। किसी भी दर पर मैंने अपनी हाल की समस्या को हल किया Return ,$outजिसका उपयोग करके हमेशा काम करने लगता है। अगर मैं फिर से समस्या में हूँ तो एक उदाहरण पोस्ट करूँगा।
घातक-बगेल

13

परिणाम को एक Array पर बल दें ताकि आपके पास एक Count गुण हो सके। सिंगल ऑब्जेक्ट्स (स्केलर) में काउंट प्रॉपर्टी नहीं होती है। स्ट्रिंग्स की लंबाई संपत्ति होती है ताकि आपको गलत परिणाम मिलें, गणना संपत्ति का उपयोग करें:

if (@($serverIps).Count -le 1)...

वैसे, वाइल्डकार्ड का उपयोग करने के बजाय जो तार से मेल भी खा सकता है, -as ऑपरेटर का उपयोग करें:

[array]$serverIps = gwmi Win32_NetworkAdapterConfiguration -filter "IPEnabled=TRUE" | Select-Object -ExpandProperty IPAddress | Where-Object {($_ -as [ipaddress]).AddressFamily -eq 'InterNetwork'}

क्या इसके लिए वह केवल डेटा प्रकार की जांच नहीं कर सकता है -is?
JNK

स्ट्रिंग्स में एक .length संपत्ति है - इसीलिए यह काम कर रही है ... :)
डायलन बीट्टी

8

यदि आप चर को समय के आगे एक सरणी के रूप में घोषित करते हैं, तो आप इसमें तत्व जोड़ सकते हैं - भले ही यह सिर्फ एक हो ...

यह काम करना चाहिए ...

$serverIps = @()

gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort | ForEach-Object{$serverIps += $_}

मुझे वास्तव में ऐसा लगता है कि यह सबसे स्पष्ट और सुरक्षित विकल्प है। आप मज़बूती से ".Count - ge 1 'को संग्रह या' Foreach 'पर प्रयोग कर सकते हैं
Jaigene Kang

2

आप Measure-Objectकिसी वस्तु की Countसंपत्ति का सहारा लिए बिना, वास्तविक वस्तु गणना प्राप्त करने के लिए उपयोग कर सकते हैं।

$serverIps = gwmi Win32_NetworkAdapterConfiguration 
    | Where { $_.IPAddress } 
    | Select -Expand IPAddress 
    | Where { $_ -like '*.*.*.*' } 
    | Sort

if (($serverIps | Measure).Count -le 1) {
    Write-Host "You need at least 2 IP addresses for this to work!"
    exit
}

1

आप या तो ,वापसी सूची से पहले अल्पविराम ( ) जोड़ सकते हैं या return ,$listइसे डाल सकते हैं [Array]या [YourType[]]जहां आप सूची का उपयोग करते हैं।


0

मुझे यह समस्या एक एज़्योर परिनियोजन टेम्पलेट के लिए एक सरणी पास करने में थी। यदि एक वस्तु थी, तो PowerShell ने इसे एक स्ट्रिंग में "परिवर्तित" कर दिया। नीचे दिए गए उदाहरण में, $aएक फ़ंक्शन से लौटा दिया गया है जो एक टैग के मूल्य के अनुसार वीएम पर आपत्ति करता है। मैं इसे में लपेटकर cmdlet $aको पास करता हूं । इस तरह:New-AzureRmResourceGroupDeployment@()

$TemplateParameterObject=@{
     VMObject=@($a)
}

New-AzureRmResourceGroupDeployment -ResourceGroupName $RG -Name "TestVmByRole" -Mode Incremental -DeploymentDebugLogLevel All -TemplateFile $templatePath -TemplateParameterObject $TemplateParameterObject -verbose

VMObject टेम्पलेट के मापदंडों में से एक है।

यह करने के लिए सबसे तकनीकी / मजबूत तरीका नहीं हो सकता है, लेकिन यह एज़्योर के लिए पर्याप्त है।


अपडेट करें

खैर ऊपर वाले ने काम किया। मैंने उपरोक्त सभी और कुछ की कोशिश की है, लेकिन एक ही तरीका है कि मैं $vmObjectएक सरणी के रूप में पारित करने में कामयाब रहा , तैनाती टेम्पलेट के साथ संगत, एक तत्व निम्नानुसार है (मुझे उम्मीद है कि एमएस फिर से खेल रहा है (यह एक रिपोर्ट और तय किया गया था) 2015 में बग)):

[void][System.Reflection.Assembly]::LoadWithPartialName("System.Web.Extensions")
    
    foreach($vmObject in $vmObjects)
    {
        #$vmTemplateObject = $vmObject 
        $asJson = (ConvertTo-Json -InputObject $vmObject -Depth 10 -Verbose) #-replace '\s',''
        $DeserializedJson = (New-Object -TypeName System.Web.Script.Serialization.JavaScriptSerializer -Property @{MaxJsonLength=67108864}).DeserializeObject($asJson)
    }

$vmObjects Get-AzureRmVM का आउटपुट है।

मैं उत्तीर्ण हो गया $DeserializedJson परिनियोजन टेम्पलेट के पैरामीटर (प्रकार सरणी का) करता ।

संदर्भ के लिए, सुंदर त्रुटि New-AzureRmResourceGroupDeploymentफेंकता है

"The template output '{output_name}' is not valid: The language expression property 'Microsoft.WindowsAzure.ResourceStack.Frontdoor.Expression.Expressions.JTokenExpression' 
can't be evaluated.."

0

संदर्भित वस्तु के रूप में लौटें, इसलिए यह गुजरते समय कभी परिवर्तित नहीं हुई।

return @{ Value = @("single data") }
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.