2012-04-27 18 views
6

Bir String ile bir XML özniteliği ayarlıyorum ve PowerShell bana "yalnızca dizeleri XmlNode özelliklerini ayarlamak için değer olarak kullanılabilir" diyor. İşte basit bir örnek. Birincisi, bu çalıştırın:Neden PowerShell'in bir String söylediği bir String değil? Ve sadece String.Length çağrılırken, ilk

$xmlDoc = [xml]@" 
<root> 
    <ComponentRef Id="a" /> 
</root> 
"@ 

$newId = "b" 

$length = $newId.Length 

Write-Host ("`n`$newId is a string, see: `$newId.GetType().FullName = " + $newId.GetType().FullName + "`n") 
Write-Host ("Running `"`$xmlDoc.root.ComponentRef.Id = `$newId`"...`n") 
$xmlDoc.root.ComponentRef.Id = $newId 
Write-Host ("ComponentRef.Id is now: " + $xmlDoc.root.ComponentRef.Id) 

Benim için çıktıdır:

$newId is a string, see: $newId.GetType().FullName = System.String 

Running "$xmlDoc.root.ComponentRef.Id = $newId"... 

Cannot set "Id" because only strings can be used as values to set XmlNode properties. 
At D:\Build\Tools\mass processing\Untitled4.ps1:14 char:27 
+ $xmlDoc.root.ComponentRef. <<<< Id = $newId 
    + CategoryInfo   : InvalidOperation: (:) [], RuntimeException 
    + FullyQualifiedErrorId : PropertyAssignmentException 

ComponentRef.Id is now: a 

O hata mesajı yanlış olmak zorunda. eşittir işaretinin sağ tarafındaki değer, yukarıdaki çıktıda gösterildiği gibi bir a String'dir. Ama o, bu yüzden, XML özniteliği hala "a" okuyor. Şimdi garipleşiyor. Yeni newdd.length çağıran satırı yorumlayalım ve doğru şekilde çalıştığını izleyelim.

Böyle yorum yaparken: #$length = $newId.Length. Çıktı şimdi: Geçen atama operatörünün sağ tarafındaki [dize] olarak atayarak bu soruna geçici bir çözüm biliyorum çünkü bir düzeltme için sormuyorum

$newId is a string, see: $newId.GetType().FullName = System.String 

Running "$xmlDoc.root.ComponentRef.Id = $newId"... 

ComponentRef.Id is now: b 

. Bilmek istediklerim:

$ newId.Length (getter!) Çağrısının neden PowerShell'in $ newId'nin artık bir ip olduğunu düşünmesine neden olduğunu açıklayabilir mi?

Teşekkürler!

+0

Sorun, PowerShell nesnelerinin kök .NET nesnelerine nasıl uyarlandığıyla ilgili bir sorun olduğu gibi (örneğin, C# içinde t xmlDoc.root çağrısı - root, PS'nin eklediği bir özelliktir). Bu, PS'ye ve karşılaştığınız herhangi bir .NET nesnesine karşı saydam olmalıdır, bu yüzden neden bu kadar uçtuğunu bilmiyorum. Örneğin, iyi işler için $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId). Çok garip ... –

+0

Böyle bir şey olmalı. Boy'un onu tetikleyeceği garipti. Bana bir PowerShell hatası olduğunu düşünür. Belki de cevabı alabildiğimiz kadarıyla, göreceğiz;) PowerShell ekibinin genel halktan hata raporları alıp almadığından emin değilim. – Vimes

+1

JohnB hata raporları alırlar - canlı bir kimlik ile connect.microsoft.com/powershell adresine giriş yapın ve hatayı repro ile günlüğe kaydedin. – x0n

cevap

6

Bu, psobject sargısının temel bir .NET Türü etrafında oluşturulabildiği V2 genişletilmiş sistemde talihsiz bir hatadır. Bu, bir nesneyi üye eklediğinizde veya olmayan bir özelliğe eriştiğinizde gerçekleşebilir. Ayrıca, bir nesne IIRC'de psobject özelliğine eriştiğinizde de olabilir. $newId.psobject. PowerShell içinde kaldığınızda bu genellikle herhangi bir soruna neden olmaz.

Güncelleştirme: Bu, .NET'e çağrı yapmakta sorun değil. Bazı hızlı .NET sınama kodu, bir özellik belirleyici için istenmeyen bir nesne aldığını gösterir. Trace-Command ile bu baktıktan sonra onu PowerShell en XmlNodeAdapater bir hata gibi görünüyor: Her zaman base NET nesnesi elde etmek amacıyla

DEBUG: ETS Information: 0 : Method  Enter PSObject..ctor():object = System.Management.Automation.RuntimeException: 
Cannot set "Id" because only strings can be used as values to set XmlNode properties. ---> 
System.Management.Automation.SetValueException: Cannot set "Id" because only strings can be used as values to set 
XmlNode properties. 
    at System.Management.Automation.XmlNodeAdapter.PropertySet(PSProperty property, Object setValue, Boolean 
convertIfPossible) 
    at System.Management.Automation.Adapter.BasePropertySet(PSProperty property, Object setValue, Boolean convert) 
    at System.Management.Automation.PSProperty.SetAdaptedValue(Object setValue, Boolean shouldConvert) 
    at System.Management.Automation.PSProperty.set_Value(Object value) 
    at System.Management.Automation.PropertyReferenceNode.SetValue(PSObject obj, Object property, Object value, 
ExecutionContext context) 
    --- End of inner exception stack trace --- 
    at System.Management.Automation.PropertyReferenceNode.SetValue(PSObject obj, Object property, Object value, 
ExecutionContext context) 
    at System.Management.Automation.AssignablePropertyReference.SetValue(Object value, ExecutionContext context) 
    at System.Management.Automation.AssignmentStatementNode.Execute(Array input, Pipe outputPipe, ExecutionContext 
context) 
    at System.Management.Automation.StatementListNode.ExecuteStatement(ParseTreeNode statement, Array input, Pipe 
outputPipe, ArrayList& resultList, ExecutionContext context) 

Tek yoludur:

$xmlDoc.root.ComponentRef.Id = $newId.psobject.baseobject 

İyi haber bu konuda olmasıdır V3'te sabittir, örneğin:

PS> $xmlDoc = [xml]@" 
<root> 
    <ComponentRef Id="a" /> 
</root> 
"@ 

PS> $newId = "b" 

PS> $newId.Length 
1 

PS> $newId.psobject.typenames 
System.String 
System.Object 

PS> $xmlDoc.root.ComponentRef.Id = $newId 

PS> $xmlDoc | format-xml # From PowerShell Community Extensions 
<root> 
    <ComponentRef Id="b" /> 
</root> 
+1

XML bağdaştırıcısının soruna neden olduğunu düşünüyor. Bu, .NET yöntemi SetAttribute üzerinde geriye düşme nedenini açıklar: $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId) –

+0

Aynı sorunu 5.0 (Windows 10) 'da var.Görünüşe göre bu "özellik" tekrar açılıyor ... –

+0

OP'in senaryosu, 5.0 build 5.0.10130.0 üzerinde çalışıyor. Hangi 5.0 sürümünü çalıştırıyorsunuz? –

İlgili konular