Nota
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare ad accedere o modificare le directory.
L'accesso a questa pagina richiede l'autorizzazione. È possibile provare a modificare le directory.
Gli elementi di MSBuild sono input nel sistema di compilazione e in genere rappresentano i file (i file vengono specificati nell'attributo Include
). Gli elementi vengono raggruppati in tipi di elemento in base ai relativi nomi di elemento. I tipi di elemento sono elenchi denominati di elementi che possono essere usati come parametri per le attività. Le attività usano i valori dell'elemento per eseguire i passaggi del processo di compilazione.
Poiché gli elementi sono denominati dal tipo di elemento a cui appartengono, i termini "item" e "item value" possono essere usati in modo intercambiabile.
Creare elementi in un file di progetto
Gli elementi nel file di progetto vengono dichiarati come elementi figlio di un elemento ItemGroup . I nomi degli elementi validi iniziano con una lettera maiuscola o minuscola o un carattere di sottolineatura (_
); i caratteri successivi validi includono caratteri alfanumerici (lettere o cifre), carattere di sottolineatura e trattino (-
). Il nome dell'elemento figlio è il tipo dell'elemento. L'attributo Include
dell'elemento specifica gli elementi (file) da includere in tale tipo di elemento. Ad esempio, il codice XML seguente crea un tipo di elemento denominato Compile
, che include due file.
<ItemGroup>
<Compile Include = "file1.cs"/>
<Compile Include = "file2.cs"/>
</ItemGroup>
L'elemento file2.cs non sostituisce l'elemento file1.cs; Al contrario, il nome del file viene aggiunto all'elenco di valori per il Compile
tipo di elemento.
Il codice XML seguente crea lo stesso tipo di elemento dichiarando entrambi i file in un Include
attributo. Si noti che i nomi di file sono separati da un punto e virgola.
<ItemGroup>
<Compile Include = "file1.cs;file2.cs"/>
</ItemGroup>
L'attributo Include
è un percorso interpretato rispetto alla cartella del file di progetto, $(MSBuildProjectPath)
, anche se l'elemento si trova in un file importato, ad esempio un .targets
file.
Creare elementi durante l'esecuzione
Gli elementi esterni agli elementi Target vengono assegnati valori durante la fase di valutazione di una compilazione. Durante la fase di esecuzione successiva, gli elementi possono essere creati o modificati nei modi seguenti:
Qualsiasi attività può generare un elemento. Per generare un elemento, l'elemento Task deve avere un elemento Output figlio con un
ItemName
attributo .L'attività CreateItem può generare un elemento. Questo utilizzo è deprecato.
Target
gli elementi possono contenere elementi ItemGroup che possono contenere elementi dell'elemento.
Elementi di riferimento in un file di progetto
Per fare riferimento ai tipi di elemento nel file di progetto, usare la sintassi @(ItemType)
. Ad esempio, si fa riferimento al tipo di elemento nell'esempio precedente usando @(Compile)
. Usando questa sintassi, è possibile passare elementi alle attività specificando il tipo di elemento come parametro di tale attività. Per altre informazioni, vedere Procedura: Selezionare i file da compilare.
Per impostazione predefinita, gli elementi di un tipo di elemento sono separati da punti e virgola (;) quando viene espanso. È possibile usare la sintassi @(ItemType, 'separator')
per specificare un separatore diverso da quello predefinito. Per altre informazioni, vedere Procedura: Visualizzare un elenco di elementi separati da virgole.
Usare caratteri jolly per specificare gli elementi
È possibile usare i **
caratteri jolly , *
e ?
per specificare un gruppo di file come input per una compilazione anziché elencare ogni file separatamente.
- Il
?
carattere jolly corrisponde a un singolo carattere. - Il
*
carattere jolly corrisponde a zero o più caratteri. - La
**
sequenza di caratteri jolly corrisponde a un percorso parziale.
Ad esempio, è possibile specificare tutti i .cs
file nella directory che contiene il file di progetto usando l'elemento seguente nel file di progetto.
<CSFile Include="*.cs"/>
L'elemento seguente seleziona tutti i .vb
file nell'unità D:
:
<VBFile Include="D:/**/*.vb"/>
Se si desidera includere caratteri letterali *
o ?
caratteri in un elemento senza espansione con caratteri jolly, è necessario eseguire l'escape dei caratteri jolly.
Per altre informazioni sui caratteri jolly, vedere Procedura: Selezionare i file da compilare.
Usare l'attributo Exclude
Gli elementi dell'elemento possono contenere l'attributo Exclude
, che esclude elementi specifici (file) dal tipo di elemento. L'attributo Exclude
viene in genere usato insieme ai caratteri jolly. Ad esempio, il codice XML seguente aggiunge ogni .cs file nella directory al tipo di elemento, ad eccezione del CSFile
file DoNotBuild.cs .
<ItemGroup>
<CSFile Include="*.cs" Exclude="DoNotBuild.cs"/>
</ItemGroup>
L'attributo Exclude
influisce solo sugli elementi aggiunti dall'attributo nell'elemento Include
elemento che li contiene entrambi. L'esempio seguente non esclude il file Form1.cs, che è stato aggiunto nell'elemento dell'elemento precedente.
<Compile Include="*.cs" />
<Compile Include="*.res" Exclude="Form1.cs">
Per altre informazioni, vedere Procedura: Escludere i file dalla compilazione.
Metadati dell'elemento
Gli elementi possono contenere metadati oltre alle informazioni contenute negli Include
attributi e Exclude
. Questi metadati possono essere usati dalle attività che richiedono altre informazioni sugli elementi o per eseguire attività e destinazioni batch. Per ulteriori informazioni, vedere Raggruppamento.
I metadati sono una raccolta di coppie chiave-valore dichiarate nel file di progetto come elementi figlio di un elemento elemento. Il nome dell'elemento figlio è il nome dei metadati e il valore dell'elemento figlio è il valore dei metadati.
I metadati sono associati all'elemento che lo contiene. Ad esempio, il codice XML seguente aggiunge Culture
metadati con valore Fr
sia al one.cs che agli elementi two.cs del CSFile
tipo di elemento.
<ItemGroup>
<CSFile Include="one.cs;two.cs">
<Culture>Fr</Culture>
</CSFile>
</ItemGroup>
Un elemento può avere zero o più valori di metadati. È possibile modificare i valori dei metadati in qualsiasi momento. Se si impostano metadati su un valore vuoto, è possibile rimuoverli dalla compilazione.
Metadati degli elementi di riferimento in un file di progetto
È possibile fare riferimento ai metadati degli elementi nel file di progetto usando la sintassi %(ItemMetadataName)
. Se esistono ambiguità, è possibile qualificare un riferimento usando il nome del tipo di elemento. Ad esempio, è possibile specificare %(ItemType.ItemMetaDataName)
. Nell'esempio seguente vengono usati i Display
metadati per eseguire il batch dell'attività Message
. Per altre informazioni su come usare i metadati degli elementi per l'invio in batch, vedere Metadati degli elementi in batch delle attività.
<Project>
<ItemGroup>
<Stuff Include="One.cs" >
<Display>false</Display>
</Stuff>
<Stuff Include="Two.cs">
<Display>true</Display>
</Stuff>
</ItemGroup>
<Target Name="Batching">
<Message Text="@(Stuff)" Condition=" '%(Display)' == 'true' "/>
</Target>
</Project>
Metadati di elementi noti
Quando un elemento viene aggiunto a un tipo di elemento, a tale elemento vengono assegnati alcuni metadati noti. Ad esempio, tutti gli elementi hanno i metadati %(Filename)
noti , il cui valore è il nome file dell'elemento (senza l'estensione). Per altre informazioni, vedere Metadati degli elementi noti.
Trasformare i tipi di elemento usando i metadati
È possibile trasformare gli elenchi di elementi in nuovi elenchi di elementi usando i metadati. Ad esempio, è possibile trasformare un tipo di CppFiles
elemento con elementi che rappresentano .cpp
i file in un elenco corrispondente di .obj
file usando l'espressione @(CppFiles -> '%(Filename).obj')
.
Il codice seguente crea un CultureResource
tipo di elemento che contiene copie di tutti gli EmbeddedResource
elementi con Culture
metadati. Il Culture
valore dei metadati diventa il valore dei nuovi metadati CultureResource.TargetDirectory
.
<Target Name="ProcessCultureResources">
<ItemGroup>
<CultureResource Include="@(EmbeddedResource)"
Condition="'%(EmbeddedResource.Culture)' != ''">
<TargetDirectory>%(EmbeddedResource.Culture) </TargetDirectory>
</CultureResource>
</ItemGroup>
</Target>
Per altre operazioni sugli elementi, vedere Funzioni degli elementi di MSBuild e Trasformazioni.
Definizioni di elementi
È possibile aggiungere metadati predefiniti a qualsiasi tipo di elemento usando l'elemento ItemDefinitionGroup. Analogamente ai metadati noti, i metadati predefiniti sono associati a tutti gli elementi del tipo di elemento specificato. È possibile eseguire l'override esplicito dei metadati predefiniti in una definizione di elemento. Ad esempio, il codice XML seguente fornisce agli Compile
elementi one.cs e three.cs i metadati BuildDay
con il valore "Monday". Il codice fornisce all'elemento two.cs i metadati BuildDay
con il valore "Tuesday".
<ItemDefinitionGroup>
<Compile>
<BuildDay>Monday</BuildDay>
</Compile>
</ItemDefinitionGroup>
<ItemGroup>
<Compile Include="one.cs;three.cs" />
<Compile Include="two.cs">
<BuildDay>Tuesday</BuildDay>
</Compile>
</ItemGroup>
Per altre informazioni, vedere Definizioni di elementi.
Attributi per gli elementi in un ItemGroup di una destinazione
Target
gli elementi possono contenere elementi ItemGroup che possono contenere elementi dell'elemento. Gli attributi in questa sezione sono validi quando vengono specificati per un elemento in un ItemGroup
oggetto che si trova in un oggetto Target
.
Rimuovi attributo
L'attributo Remove
rimuove elementi specifici (file) dal tipo di elemento. Questo attributo è stato introdotto in .NET Framework 3.5 (solo all'interno di destinazioni). Le destinazioni interne e esterne sono supportate a partire da MSBuild 15.0.
Nell'esempio seguente viene rimosso ogni .config
file dal Compile
tipo di elemento.
<Target>
<ItemGroup>
<Compile Remove="*.config"/>
</ItemGroup>
</Target>
Attributo MatchOnMetadata
L'attributo MatchOnMetadata
è applicabile solo agli attributi che fanno riferimento ad Remove
altri elementi (ad esempio, Remove="@(Compile);@(Content)"
) e indica all'operazione Remove
di trovare le corrispondenze tra gli elementi in base ai valori dei nomi di metadati specificati, anziché la corrispondenza in base ai valori dell'elemento.
Regola di corrispondenza per B Remove="@(A)" MatchOnMetadata="M"
: rimuovere tutti gli elementi da B
con metadati M
, il cui valore V
dei metadati per corrisponde a M
qualsiasi elemento da A
con i metadati M
di valore V
.
<Project>
<ItemGroup>
<A Include='a1' M1='1' M2='a' M3="e"/>
<A Include='b1' M1='2' M2='x' M3="f"/>
<A Include='c1' M1='3' M2='y' M3="g"/>
<A Include='d1' M1='4' M2='b' M3="h"/>
<B Include='a2' M1='x' m2='c' M3="m"/>
<B Include='b2' M1='2' m2='x' M3="n"/>
<B Include='c2' M1='2' m2='x' M3="o"/>
<B Include='d2' M1='3' m2='y' M3="p"/>
<B Include='e2' M1='3' m2='Y' M3="p"/>
<B Include='f2' M1='4' M3="r"/>
<B Include='g2' M3="s"/>
<B Remove='@(A)' MatchOnMetadata='M1;M2'/>
</ItemGroup>
<Target Name="PrintEvaluation">
<Message Text="%(B.Identity) M1='%(B.M1)' M2='%(B.M2)' M3='%(B.M3)'" />
</Target>
</Project>
Nell'esempio i valori b2
dell'elemento , c2
e d2
vengono rimossi dall'elemento B
perché:
-
b2
ec2
dallaB
partita controb1
daA
onM1=2
eM2=x
-
d2
dalleB
corrispondenze controc1
da onA
M1=3
eM2=y
L'attività Message
restituisce quanto segue:
a2 M1='x' M2='c' M3='m'
e2 M1='3' M2='Y' M3='p'
f2 M1='4' M2='' M3='r'
g2 M1='' M2='' M3='s'
Esempio di utilizzo di MatchOnMetadata
da MSBuild:
<_TransitiveItemsToCopyToOutputDirectory Remove="@(_ThisProjectItemsToCopyToOutputDirectory)" MatchOnMetadata="TargetPath" MatchOnMetadataOptions="PathLike" />
Questa riga rimuove gli elementi da _TransitiveItemsToCopyToOutputDirectory
con gli stessi TargetPath
valori di metadati dagli elementi in _ThisProjectItemsToCopyToOutputDirectory
Attributo MatchOnMetadataOptions
Specifica la strategia di corrispondenza delle stringhe usata da MatchOnMetadata
per trovare la corrispondenza dei valori dei metadati tra gli elementi (i nomi dei metadati sono sempre senza distinzione tra maiuscole e minuscole). I valori possibili sono CaseSensitive
, CaseInsensitive
o PathLike
. Il valore predefinito è CaseSensitive
.
PathLike
applica la normalizzazione compatibile con il percorso ai valori come la normalizzazione degli orientamenti delle barre, ignorando le barre finali, eliminando .
e ..
e rendendo assoluti tutti i percorsi relativi rispetto alla directory corrente.
Attributo KeepMetadata
Se un elemento viene generato all'interno di una destinazione, l'elemento dell'elemento può contenere l'attributo KeepMetadata
. Se questo attributo viene specificato, verranno trasferiti dall'elemento di origine all'elemento di destinazione solo i metadati specificati nell'elenco delimitato da punto e virgola. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo KeepMetadata
è stato introdotto in .NET Framework 4.5.
Nell'esempio seguente viene illustrato come usare l'attributo KeepMetadata
.
<Project>
<ItemGroup>
<FirstItem Include="rhinoceros">
<Class>mammal</Class>
<Size>large</Size>
</FirstItem>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<SecondItem Include="@(FirstItem)" KeepMetadata="Class" />
</ItemGroup>
<Message Text="FirstItem: %(FirstItem.Identity)" />
<Message Text=" Class: %(FirstItem.Class)" />
<Message Text=" Size: %(FirstItem.Size)" />
<Message Text="SecondItem: %(SecondItem.Identity)" />
<Message Text=" Class: %(SecondItem.Class)" />
<Message Text=" Size: %(SecondItem.Size)" />
</Target>
</Project>
<!--
Output:
FirstItem: rhinoceros
Class: mammal
Size: large
SecondItem: rhinoceros
Class: mammal
Size:
-->
Attributo RemoveMetadata
Se un elemento viene generato all'interno di una destinazione, l'elemento dell'elemento può contenere l'attributo RemoveMetadata
. Se questo attributo viene specificato, tutti i metadati vengono trasferiti dall'elemento di origine all'elemento di destinazione, ad eccezione dei metadati i cui nomi sono contenuti nell'elenco di nomi delimitato da punto e virgola. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo RemoveMetadata
è stato introdotto in .NET Framework 4.5.
Nell'esempio seguente viene illustrato come usare l'attributo RemoveMetadata
.
<Project>
<PropertyGroup>
<MetadataToRemove>Size;Material</MetadataToRemove>
</PropertyGroup>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<Item2 Include="@(Item1)" RemoveMetadata="$(MetadataToRemove)" />
</ItemGroup>
<Message Text="Item1: %(Item1.Identity)" />
<Message Text=" Size: %(Item1.Size)" />
<Message Text=" Color: %(Item1.Color)" />
<Message Text=" Material: %(Item1.Material)" />
<Message Text="Item2: %(Item2.Identity)" />
<Message Text=" Size: %(Item2.Size)" />
<Message Text=" Color: %(Item2.Color)" />
<Message Text=" Material: %(Item2.Material)" />
</Target>
</Project>
<!--
Output:
Item1: stapler
Size: medium
Color: black
Material: plastic
Item2: stapler
Size:
Color: black
Material:
-->
Per altre operazioni sugli elementi, vedere Funzioni dell'elemento MSBuild.
Attributo KeepDuplicates
Se un elemento viene generato all'interno di una destinazione, l'elemento dell'elemento può contenere l'attributo KeepDuplicates
.
KeepDuplicates
è un Boolean
attributo che specifica se un elemento deve essere aggiunto al gruppo di destinazione se l'elemento è un duplicato esatto di un elemento esistente.
Se l'elemento di origine e di destinazione ha lo stesso Include
valore ma metadati diversi, l'elemento viene aggiunto anche se KeepDuplicates
è impostato su false
. Un valore vuoto per questo attributo equivale a non specificarlo. L'attributo KeepDuplicates
è stato introdotto in .NET Framework 4.5.
Nell'esempio seguente viene illustrato come usare l'attributo KeepDuplicates
.
<Project>
<ItemGroup>
<Item1 Include="hourglass;boomerang" />
<Item2 Include="hourglass;boomerang" />
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<Item1 Include="hourglass" KeepDuplicates="false" />
<Item2 Include="hourglass" />
</ItemGroup>
<Message Text="Item1: @(Item1)" />
<Message Text=" %(Item1.Identity) Count: @(Item1->Count())" />
<Message Text="Item2: @(Item2)" />
<Message Text=" %(Item2.Identity) Count: @(Item2->Count())" />
</Target>
</Project>
<!--
Output:
Item1: hourglass;boomerang
hourglass Count: 1
boomerang Count: 1
Item2: hourglass;boomerang;hourglass
hourglass Count: 2
boomerang Count: 1
-->
Poiché l'attributo KeepDuplicates
considera i metadati degli elementi oltre ai valori dell'elemento, è importante sapere cosa accade con i metadati. Ad esempio, vedere Rilevamento di duplicati quando si usa la funzione Elemento metadati.
Aggiornamento dei metadati per gli elementi in un ItemGroup all'esterno di una destinazione
Gli elementi esterni alle destinazioni possono avere i metadati esistenti aggiornati tramite l'attributo Update
. Questo attributo non è disponibile per gli elementi nelle destinazioni.
<Project>
<PropertyGroup>
<MetadataToUpdate>pencil</MetadataToUpdate>
</PropertyGroup>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Color>red</Color>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="notebook">
<Size>SMALL</Size>
<Color>YELLOW</Color>
</Item2>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Update="$(MetadataToUpdate);stapler;er*r;@(Item2)" Price="10" Material="">
<Color>RED</Color>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)" />
</Target>
</Project>
<!--
Item1: stapler
Size: medium
Color: RED
Material:
Price: 10
Item1: pencil
Size: small
Color: RED
Material:
Price: 10
Item1: eraser
Size:
Color: RED
Material:
Price: 10
Item1: notebook
Size: large
Color: RED
Material:
Price: 10
-->
In MSBuild versione 16.6 e successive, l'attributo Update
supporta riferimenti ai metadati qualificati per facilitare l'importazione di metadati da due o più elementi.
<Project>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Size>small</Size>
<Color>red</Color>
<Material>gum</Material>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="pencil">
<Size>MEDIUM</Size>
<Color>RED</Color>
<Material>PLASTIC</Material>
<Price>10</Price>
</Item2>
<Item3 Include="notebook">
<Size>SMALL</Size>
<Color>BLUE</Color>
<Price>20</Price>
</Item3>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Update="@(Item2);er*r;@(Item3)" Size="%(Size)" Color="%(Item2.Color)" Price="%(Item3.Price)" Model="2020">
<Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
</Item1>
</ItemGroup>
<Target Name="MyTarget">
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)
Model: %(Item1.Model)" />
</Target>
</Project>
<!--
Item1: stapler
Size: medium
Color: black
Material: plastic
Price:
Model:
Item1: pencil
Size: small
Color: RED
Material: Premium PLASTIC
Price:
Model: 2020
Item1: eraser
Size: small
Color:
Material: gum
Price:
Model: 2020
Item1: notebook
Size: large
Color:
Material: paper
Price: 20
Model: 2020
-->
Note:
- I metadati non qualificati (
%(MetadataName)
) vengono associati al tipo di elemento da aggiornare (Item1
nell'esempio precedente). I metadati qualificati (%(Item2.Color)
) vengono associati all'interno del set di tipi di elementi corrispondenti acquisiti dall'espressione Update. - Se un elemento corrisponde più volte all'interno e tra più elementi a cui si fa riferimento:
- L'ultima occorrenza di ogni tipo di elemento a cui viene fatto riferimento viene acquisita (quindi un elemento acquisito per ogni tipo di elemento).
- Questo corrisponde al comportamento dell'invio in batch degli elementi dell'attività nelle destinazioni.
- Dove è possibile inserire riferimenti %():
- Metadati
- Condizioni dei metadati
- La corrispondenza dei nomi dei metadati non fa distinzione tra maiuscole e minuscole.
Aggiornamento dei metadati per gli elementi in un ItemGroup di una destinazione
I metadati possono essere modificati anche all'interno delle destinazioni, con una sintassi meno espressiva di Update
:
<Project>
<ItemGroup>
<Item1 Include="stapler">
<Size>medium</Size>
<Color>black</Color>
<Material>plastic</Material>
</Item1>
<Item1 Include="pencil">
<Size>small</Size>
<Color>yellow</Color>
<Material>wood</Material>
</Item1>
<Item1 Include="eraser">
<Size>small</Size>
<Color>red</Color>
<Material>gum</Material>
</Item1>
<Item1 Include="notebook">
<Size>large</Size>
<Color>white</Color>
<Material>paper</Material>
</Item1>
<Item2 Include="pencil">
<Size>MEDIUM</Size>
<Color>RED</Color>
<Material>PLASTIC</Material>
<Price>10</Price>
</Item2>
<Item2 Include="ruler">
<Color>GREEN</Color>
</Item2>
</ItemGroup>
<Target Name="MyTarget">
<ItemGroup>
<!-- Metadata can be expressed either as attributes or as elements -->
<Item1 Size="GIGANTIC" Color="%(Item2.Color)">
<Material Condition="'%(Item2.Material)' != ''">Premium %(Item2.Material)</Material>
</Item1>
</ItemGroup>
<Message Text="Item1: %(Item1.Identity)
Size: %(Item1.Size)
Color: %(Item1.Color)
Material: %(Item1.Material)
Price: %(Item1.Price)
Model: %(Item1.Model)" />
</Target>
</Project>
<!--
Item1: stapler
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: pencil
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: eraser
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
Item1: notebook
Size: GIGANTIC
Color: GREEN
Material: Premium PLASTIC
Price:
Model:
-->