যখন কল কেবল একটি বস্তু ফেরত দেয় আমি কীভাবে পাওয়ারশেলকে একটি অ্যারে ফিরিয়ে দিতে বাধ্য করতে পারি?


123

আমি ওয়েব সার্ভারে আইআইএস বাইন্ডিংগুলি সেট আপ করতে পাওয়ারশেল ব্যবহার করছি এবং নিম্নলিখিত কোডটিতে সমস্যা হচ্ছে:

$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+ আইপি থাকে তবে জরিমানা - পাওয়ারশেল একটি অ্যারের ফিরিয়ে দেয় এবং আমি অ্যারের দৈর্ঘ্যটি জিজ্ঞাসা করতে পারি এবং প্রথম এবং দ্বিতীয় ঠিকানাগুলি ঠিক সূক্ষ্মভাবে বের করতে পারি।

সমস্যাটি হ'ল - যদি কেবল একটি আইপি থাকে তবে পাওয়ারশেল কোনও এক-এলিমেন্ট অ্যারেটি ফিরিয়ে দেয় না, এটি আইপি ঠিকানা দেয় ("192.168.0.100" এর মতো একটি স্ট্রিং হিসাবে) - স্ট্রিংটির একটি .lengthসম্পত্তি রয়েছে, এটি 1 এর চেয়েও বড়, তাই পরীক্ষাটি পাস হয় এবং আমি সংগ্রহের প্রথম দুটি আইপি ঠিকানার পরিবর্তে স্ট্রিংয়ের প্রথম দুটি অক্ষর দিয়ে শেষ করি।

আমি কীভাবে পাওয়ারশেলকে একটি উপাদান উপাদান সংগ্রহ করতে বাধ্য করতে পারি, বা বিকল্পভাবে নির্ধারণ করতে পারি যে সংগ্রহের পরিবর্তে প্রত্যাবর্তিত "জিনিস" কোনও বস্তু কিনা?


28
পাওয়ারশেলের সর্বাধিক এককভাবে বিরক্তিকর / বাগ-চালিত দিক ..
ব্যবহারকারী 2864740

আমি আপনার উদাহরণকে অতিরিক্ত জটিল বলে মনে করি। সহজ প্রশ্ন: << $ x = প্রতিধ্বনি হ্যালো; $ x -is [অ্যারে] >> মিথ্যা ফল দেয়।
রাউল সালিনাস-মন্টেইগুডো

এই আচরণটি পাওয়ারশেল 5 এ পরিবর্তিত হয়েছিল? আমি একটি অনুরূপ ইস্যু পেয়েছি যা আমি 5 এ পুনরুত্পাদন করতে পারি না, তবে 4
নিকল

উত্তর:


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]শূন্য বস্তু থাকলে ফলটি একটি- টাইপযুক্ত ভেরিয়েবলকে নির্ধারণ করা এখনও ull নাল ফিরে আসবে।
নিক

1
কেবলমাত্র একটি দ্রষ্টব্য যে অবজেক্টটি ফেরত পাঠানো হলে এই সমাধানগুলির কোনওটিই কাজ করে না PSObject (সম্ভবত অন্যরা)।
মারাত্মক-ব্যাগেল

2
@ মারাত্মক-ব্যাগেল আপনি কি এর উদাহরণ দেখাতে পারেন? আমার @(...)জন্য যে কোনও ধরণের অবজেক্টের জন্য সঠিকভাবে কাজ করুন (ফল উত্সাহিত করি এটির উত্পাদন হওয়া উচিত)।
user4003407

1
আপনি একই প্রশ্নে কীভাবে শেষ করবেন তা মজার। আমার কিছুটা আলাদা সমস্যা ছিল (এবং আবারও), হ্যাঁ প্রশ্নের হিসাবে এটি ঠিক আছে তবে কোনও ফাংশন থেকে ফিরে আসার সময় এটি একটি ভিন্ন গল্প different যদি একটি উপাদান থাকে তবে অ্যারেটিকে উপেক্ষা করা হবে এবং কেবলমাত্র উপাদানটি ফিরে আসবে। আপনি যদি ভেরিয়েবলের আগে কমা রাখেন তবে এটি এটিকে একটি অ্যারেতে বাধ্য করে তবে একটি বহু-উপাদান অ্যারে তারপরে একটি দ্বি-মাত্রিক অ্যারে ফিরে আসবে। খুব ক্লান্তিকর।
মারাত্মক-ব্যাগেল

1
গাহ, গতবারের মতোও এটি হয়েছিল, এখন আমি এটির অনুলিপি করতে পারি না। যে কোনও হারে আমি আমার সাম্প্রতিক সমস্যাটি ব্যবহার করে সমাধান করেছি Return ,$outযা সর্বদা কাজ করে বলে মনে হয়। আমি যদি আবার সমস্যায় পড়ে তবে আমি একটি উদাহরণ পোস্ট করব।
মারাত্মক-ব্যাগেল

13

ফলাফলটিকে একটি অ্যারেতে বাধ্য করুন যাতে আপনার একটি কাউন্টের সম্পত্তি থাকতে পারে। একক বস্তুর (স্কেলার) একটি গণনা সম্পত্তি নেই। স্ট্রিংগুলির একটি দৈর্ঘ্যের সম্পত্তি রয়েছে যাতে আপনি ভুল ফলাফল পেতে পারেন, গণনা সম্পত্তিটি ব্যবহার করুন:

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

যাইহোক, ওয়াইল্ডকার্ড ব্যবহারের পরিবর্তে স্ট্রিংগুলির সাথে মেলে তুলতে পারে, -আস অপারেটরটি ব্যবহার করুন:

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

এর জন্য তিনি কি কেবল ডাটা টাইপ দিয়ে পরীক্ষা করতে পারেন -is?
জেএনকে

স্ট্রিংগুলির একটি দৈর্ঘ্যের সম্পত্তি রয়েছে - সে কারণেই এটি কাজ করছে ... :)
ডিলান বিটি

8

যদি আপনি ভেরিয়েবলটিকে সময়ের আগে অ্যারে হিসাবে ঘোষণা করেন তবে আপনি এতে উপাদান যুক্ত করতে পারেন - এমনকি এটি যদি একটি মাত্র ...

এই কাজ করা উচিত...

$serverIps = @()

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

আমি আসলে অনুভব করি এটি সর্বাধিক পরিষ্কার এবং নিরাপদ বিকল্প। আপনি নির্ভরযোগ্যভাবে "। হিসাব - জে 1 'সংগ্রহ বা' ফরচ 'ব্যবহার করতে পারেন
জয়গেন কাং

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

একটি অ্যাজুর ডিপ্লোয়মেন্ট টেম্পলেটটিতে অ্যারে পাস করার ক্ষেত্রে আমার এই সমস্যা হয়েছিল। যদি একটি অবজেক্ট থাকে তবে পাওয়ারশেল এটিকে স্ট্রিংয়ে "রূপান্তরিত" করে। নীচের উদাহরণে, $aকোনও ফাংশন থেকে ফিরে আসে যা কোনও ট্যাগের মান অনুসারে ভিএমকে আপত্তি জানায়। আমি এটিকে জড়িয়ে $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 গেট-আজুরআরএমভিএম এর আউটপুট।

আমি $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") }
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.