2012-04-27 23 views
6

Estoy configurando un atributo XML con un String, y PowerShell me dice "solo se pueden usar cadenas como valores para establecer propiedades XmlNode". Aquí hay un ejemplo simple. En primer lugar, me encuentro esto:¿Por qué PowerShell me dice que una cadena no es una cadena? Y solo cuando llamo String.Length, primero

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

Para mí, la salida es:

$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 

Ese mensaje de error tiene que ser malo. El valor en el lado derecho del signo de igual es a String, como se muestra en el resultado anterior. Pero tenía errores, por lo que el atributo XML aún dice "a". Ahora se pone más raro. Comentemos la línea que llama $ newId.length, y miremos cómo funciona correctamente.

Comentando como tal: #$length = $newId.Length. La salida es ahora:

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

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

ComponentRef.Id is now: b 

No estoy pidiendo una solución, porque sé cómo evitar este problema echando a [cadena] en el lado derecho del último operador de asignación. Lo que me gustaría saber es:

¿Alguien puede explicar por qué llamar $ newId.Length (un getter!) Podría hacer que PowerShell piense que $ newId ya no es una cadena?

Gracias!

+0

Parece que el problema es en algún lugar de cómo los objetos PowerShell están adaptadas a los objetos .NET raíz (por ejemplo, en C# no podías t llame a xmlDoc.root - root es una propiedad que PS está agregando). Esto debería ser transparente para PS y para cualquier objeto .NET que encuentres, así que no estoy seguro de por qué está explotando. $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId) por ejemplo funciona bien. Muy extraño ... –

+0

Tiene que ser algo así. Es muy extraño que llamar a Length lo desencadene. Me hace pensar que es un error de PowerShell. Tal vez sea tan lejos como vaya la respuesta, ya veremos;) No estoy seguro si el equipo de PowerShell toma informes de errores del público en general o no. – Vimes

+1

JohnB toman informes de errores: inicie sesión en connect.microsoft.com/powershell con una identificación en vivo y registre el error con la reproducción. – x0n

Respuesta

6

Este es un error desafortunado en el sistema de tipo extendido V2 donde se puede crear un contenedor psobject alrededor de un tipo base .NET. Esto puede suceder cuando agrega miembros a un objeto o cuando accede a una propiedad que no existe. También puede ocurrir cuando accede a la propiedad psobject en un objeto IIRC, p. $newId.psobject. Cuando te quedas dentro de PowerShell esto generalmente no causa ningún problema.

Actualización: Esto no es un problema para llamar a .NET. Algunos códigos rápidos de prueba .NET muestran que obtiene un objeto desenvuelto para un setter de propiedades. Después de mirar esto con Trace-Command que parece ser un error en XmlNodeAdapater de 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) 

Una forma de asegurar que siempre obtenga el objeto base .NET es:

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

buena noticia es que esta cuestión se fija en V3 por ejemplo:

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

Tiene sentido que el adaptador XML está causando el problema. Eso explicaría por qué recurrir al método .NET SetAttribute funciona: $ xmlDoc.root.ComponentRef.SetAttribute ("Id", $ newId) –

+0

Tengo el mismo problema en 5.0 (Windows 10).Parece que esta "característica" está apareciendo de nuevo ... –

+0

La secuencia de comandos OP funciona para mí en 5.0 compilación 5.0.10130.0. ¿Qué versión de 5.0 estás ejecutando? –

Cuestiones relacionadas