3

我在遇到與New-WebBinding時管道在對象中的問題。我有一個定義了5個屬性的對象:Name,Protocol,Port,IPAddress和HostHeader(New-WebBinding cmdlet中全部5個都支持Accept Pipeline輸入:ValueByPropertyName)。但是,當你在這個對象中管道時,它仍然會請求一個名稱:被提交。如果您想複製問題,請使用快速測試功能。如果在提示符下按回車鍵,它會成功處理對象,添加綁定。但提示本身將其作爲非交互式腳本進行分解。PowerShell新WebBinding管道問題與名稱屬性

我已經用PS v3和PS v4測試過了。

我很確定我正確地做了這件事,但是想確保沒有我可能忽略的東西。現在我只是在foreach循環中迭代我的對象集合,但沒有這個問題,但希望看看這是否是我應該報告的錯誤。

function Test-WebBinding{ 
    [CmdletBinding()] 
    Param() 

    $testBindingCol = @() 

    $testBinding1 = New-Object System.Object 
    $testBinding1 | Add-Member -MemberType NoteProperty -Name Name -Value 'Default Web Site' 
    $testBinding1 | Add-Member -MemberType NoteProperty -Name Protocol -Value 'https' 
    $testBinding1 | Add-Member -MemberType NoteProperty -Name Port -Value '4000' 
    $testBinding1 | Add-Member -MemberType NoteProperty -Name IPAddress -Value '*' 
    $testBinding1 | Add-Member -MemberType NoteProperty -Name HostHeader -Value 'Test4000' 
    $testBindingCol += $testBinding1 

    $testBinding2 = New-Object System.Object 
    $testBinding2 | Add-Member -MemberType NoteProperty -Name Name -Value 'Default Web Site' 
    $testBinding2 | Add-Member -MemberType NoteProperty -Name Protocol -Value 'http' 
    $testBinding2 | Add-Member -MemberType NoteProperty -Name Port -Value '4001' 
    $testBinding2 | Add-Member -MemberType NoteProperty -Name IPAddress -Value '*' 
    $testBinding2 | Add-Member -MemberType NoteProperty -Name HostHeader -Value 'Test4001' 
    $testBindingCol += $testBinding2 

    $testBindingCol | New-WebBinding 
} 
+0

期待看到這個答案。我也嘗試過使用'PSObject'和'PSCustomObject'的變體而沒有成功。很好的問題。 – Kev

+0

它沒有出現Microsoft Connect現在正在爲任何版本的Powershell使用任何錯誤報告。所以我會留下這個最可能的錯誤,唯一的解決方法是遍歷你的對象在foreach中。我還沒有版本5,我想知道它是否已在最新版本中解決。 – Paolis

+0

這在v5中表現相同。我確實反彙編了'New-WebBinding' cmdlet所在的'Microsoft.IIs.PowerShell.Provider'程序集,並且我們感興趣的屬性用'[Parameter(ValueFromPipelineByPropertyName = true)]'正確歸屬' – Kev

回答

2

PetSerAl是到上面他的意見正確的觀念:

一個解決辦法是改變當前位置到一些網站(cd IIS:\Sites\SomeSite),它並不真正的問題,其

這確實有效,但它爲什麼不能從普通文件系統提示符下工作?

要發現爲什麼New-WebBinding表現如此,我將包含此和其他WebAdministration cmdlet的Microsoft.IIS.PowerShell.Provider程序集加載到dotPeek中。該程序集位於GAC中,因此您告訴dotPeek「從GAC打開」。

加載時,我們感興趣的類被稱爲NewWebBindingCommand

在一個粗略的觀察,我們可以看到,所有的參數屬性與[Parameter(ValueFromPipelineByPropertyName = true)]屬性裝飾所以這是一個良好的開端,管道對象的數組相匹配的屬性名應當做工;

enter image description here

NewWebBindingCommand最終從System.Management.Automation.Cmdlet繼承,並且在這種情況下重寫BeginProcessing方法。如果被覆蓋,BeginProcessing由PowerShell調用,「爲cmdlet提供一次性預處理功能。」

在處理任何管道提供的命名參數並將其綁定到cmdlet的屬性(請參閱:Cmdlet Processing Lifecycle (MSDN))之前,需要了解cmdlet的重寫被調用很重要。

我們New-WebBinding小命令的執行BeginProcessing樣子:

protected override void BeginProcessing() 
{ 
    base.BeginProcessing(); 
    if (!string.IsNullOrEmpty(this.siteName)) 
    return; 
    this.siteName = this.GetSiteName("Name"); 
} 

this.siteName是其中將被綁定到-Name參數Name財產私有成員的值。當我們到達上面的if(...)聲明時。網站名尚未綁定(它爲空)等落空至:

this.siteName = this.GetSiteName("Name"); 

GetSiteName()調用可以調出到cmdlet的直接基類HelperCommand它提供了大量的「幫手」的方法是有用的多不同的WebAdministration cmdlet。

HelperCommand.GetSiteName(string prompt)看起來是這樣的:

protected string GetSiteName(string prompt) 
{ 
    PathInfo pathInfo = this.SessionState.PSVariable.Get("PWD").Value as PathInfo; 
    if (pathInfo != null && pathInfo.Provider.Name.Equals("WebAdministration", StringComparison.OrdinalIgnoreCase)) 
    { 
    string[] strArray = pathInfo.Path.Split('\\'); 
    if (strArray.Length == 3 && strArray[1].Equals("sites", StringComparison.OrdinalIgnoreCase)) 
     return strArray[2]; 
    } 
    if (!string.IsNullOrEmpty(prompt)) 
    return this.PromptForParameter<string>(prompt); 
    return (string) null; 
} 

爲了瞭解這個問題,我創建了自己的PowerShell命令(稱爲Kevulator,對不起)和New-WebBinding小命令的BeginProcessing()代碼拉,從New-WebBinding代碼的目的的基類助手方法GetSiteName()

這裏的內部在VS2015 GetSiteName打破的截圖連接時,在您的綁定一個PowerShell會話管道到New-Kevulator

enter image description here

頂部箭頭表明我們Name財產siteName支持尚未已經被綁定並且仍然是null(其如上所述導致GetSiteName被執行)。我們也剛剛走過這條線上的一個突破點:

PathInfo pathInfo = 
     this.SessionState.PSVariable.Get("PWD").Value as PathInfo; 

......它決定我們坐的是什麼樣的路徑提供者。在這種情況下,我們使用正常的文件系統C:\>提示,因此提供者名稱將爲FileSystem。我用第二個箭頭突出顯示了這一點。

如果我們Import-Module WebAdministrationCD IIS:然後重新運行,並再次打破你可以看到,路徑提供已更改爲WebAdministration負責處理內部IIS:>及以後的生活:

enter image description here

如果pathInfo名稱不等於WebAdministration,即我們沒有在IIS:提示符處,那麼代碼將在命令行中出現並提示您輸入參數Name,就像您遇到過一樣。

如果pathInfo價值WebAdministration那麼一兩件事情會發生:

如果路徑IIS:IIS:\Sites代碼落空,併發出對Name參數的提示。

如果路徑是IIS:\Sites\SomeSiteName,則返回SomeSiteName,有效地成爲-Name參數值,我們從GetSiteName()功能解救回BeginProcessing

最後一個行爲是有用的,因爲如果您當前的路徑是說IIS:\Sites\MySite那麼你可以在該網站的綁定數組管道,但沒有指定Name參數。或者,如果您確實在管道對象陣列中提供了Name屬性,那麼這些將覆蓋從IIS:\Sites\MySite上下文中拾取的默認站點名稱。

於是,又回到了我們的代碼,一旦BeginProcessing已經走完,現在我們的管道命名參數實際結合,然後ProcessRecord方法被調用,這是香餑餑的工作,New-WebBinding必須執行。

TLDR:除非你改變你的當前工作目錄的IIS網站

New-WebBinding不會綁定流水線參數,e.g,cd iis:\Sites\MySite

+0

優秀的解構和解釋。感謝您的努力。 – Paolis

+0

@Paolis不客氣,這是一個癢,太好了不會劃傷:) – Kev