2012-04-27 10 views
6

Sto impostando un attributo XML con una stringa e PowerShell mi dice che "solo le stringhe possono essere utilizzate come valori per impostare le proprietà XmlNode". Ecco un semplice esempio. In primo luogo, ho eseguito questo:Perché PowerShell mi sta dicendo che una stringa non è una stringa? E solo quando si chiama String.Length, prima

$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) 

Per me, l'output è:

$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 

Questo messaggio di errore si è avuto modo di essere sbagliato. Il valore sul lato destro del segno di uguale a è a String, come mostrato nell'output sopra. Ma ha errato, quindi l'attributo XML continua a leggere "a". Ora diventa più strano. Esaminiamo la riga che chiama $ newId.length e osserviamo che funziona correttamente.

Come commento: #$length = $newId.Length. L'uscita è ora:

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

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

ComponentRef.Id is now: b 

Non sto chiedendo per una correzione, perché so come risolvere questo problema lanciando a [stringa] sul lato destro dell'ultimo operatore di assegnazione. Quello che vorrei sapere è:

Qualcuno può spiegare perché chiamare $ newId.Length (un getter!) Potrebbe far pensare a PowerShell che $ newId non sia più una stringa?

Grazie!

+0

Sembra che il problema sia da qualche parte nel modo in cui gli oggetti PowerShell vengono adattati dagli oggetti .NET di root (ad esempio, in C# non si potrebbe t chiama xmlDoc.root - root è una proprietà che PS sta aggiungendo). Questo dovrebbe essere trasparente per PS e per qualsiasi oggetto .NET che si incontra, quindi non sono sicuro del motivo per cui questo sta esplodendo. $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId) per esempio funziona bene. Molto strano ... –

+0

Deve essere qualcosa del genere. È strano che chiamare Length lo faccia scattare. Mi fa pensare che sia un bug di PowerShell. Forse è fin dove arriva la risposta, vedremo;) Non sono sicuro se il team di PowerShell prende segnalazioni di bug dal grande pubblico o meno. – Vimes

+1

JohnB si occupa di segnalazioni di bug - accedi a connect.microsoft.com/powershell con un ID live e registra il bug con la repro. – x0n

risposta

6

Questo è un bug sfortunato nel sistema di tipo esteso V2 in cui un wrapper psobject può essere creato attorno a un tipo .NET di base. Questo può accadere quando aggiungi membri a un oggetto o quando accedi a una proprietà che non esiste. Può anche accadere quando si accede alla proprietà psobject su un oggetto IIRC, ad es. $newId.psobject. Quando si rimane in PowerShell questo di solito non causa alcun problema.

Aggiornamento: questo non è un problema che chiama .NET. Alcuni codici di test .NET rapidi mostrano che ottiene un oggetto non imballato per un setter di proprietà. Dopo aver guardato questo con Trace-Command sembra essere un bug nel XmlNodeAdapater di PowerShell:

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) 

Un modo per essere sicuri di ottenere sempre l'oggetto base NET è:

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

buona notizia è che questo problema è fissato in V3 ad esempio:

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

Ha senso che l'adattatore XML sta causando il problema. Questo spiegherebbe perché ricorrere al metodo .NET SetAttribute funziona: $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId) –

+0

Ho lo stesso problema in 5.0 (Windows 10).Sembra che questa "caratteristica" stia di nuovo spuntando ... –

+0

Lo script dell'OP funziona per me su 5.0 build 5.0.10130.0. Quale build di 5.0 stai correndo? –

Problemi correlati