powershell , microsoft custom properties for sharepoint

Nouveau challenge, ranger pleins de documents automatiquement dans sharepoint. Revu à la baisse, sur les documents doc et xls il suffira de positionner des “custom properties”. l’onglet en plus qu’on a sur clic-droit-propriété.

La semaine dernière j’étais donc favorablement surpris par powershell. Par sa syntaxe souple et familière, cool sur les majuscules, les antislashes, la complétion, le mode debug, les paramètres, les déclarations, et un peu la doc.

 

#
#`http://blogs.technet.com/b/heyscriptingguy/archive/2010/04/06/hey-scripting-guy-how-can-i-add-custom-properties-to-a-microsoft-word-document.aspx
# get-executionpolicy /# set-executionpolicy remotesigned
# set-psdebug -off /# set-psdebug -trace 2
#
# Product name Ant
# ContentType Document
# Product type Web
# Doc Type TCD (Tech Config Doc)
#
Param (
[string]$file = "",
[string]$Producttype = "",
[string]$ContentType = "Document",
[string]$DocType = "",
[string]$Productname = ""
)
if ($file -eq "") { Write-Host "usage -file \\xxx\PTI-apache-9.9.99.doc [(optional params deducted from filename:) -Producttype Web -ContentType DOC -DocType PTI -Productname apache ]" ; Exit;}
if ( -Not (Test-Path $file)) { Write-Host "ERR -file $file : this file does not exists" ; Exit;}
if ( Test-Path $file -pathtype container ) { Write-Host "ERR -file $file : this is a folder" ; Exit;}
Write-Host "$file"
$filesl = $file.replace('\','/')
$pathsl = $filesl -replace '/[^/]*$',''
$fname = $filesl.replace("$pathsl/",'')
$pathsl = $pathsl.replace('/','\')
$fext = $fname -replace '^.*\.([^\.]*)$','$1'
$ftype = $fname.substring(0,3)
if ($ftype.tolower() -eq 'ebr') { $ftype = $fname.substring(0,6) }
if ($ftype.tolower() -eq 'spe') { $ftype = $fname.substring(0,4) }
$ftxd=$ftype
if ($ftype.tolower() -eq 'pti') { $ftxd='TID' }
if ($ftype.tolower() -eq 'pte') { $ftxd='TOD' }
if ($ftype.tolower() -eq 'spec') { $ftxd='TDD' }
$fappver=$fname.replace($ftype,'').replace(".$fext","") -replace '^[-\.]',''
$fapp=$fappver -replace '[-\.].*$',''
$fver=$fappver -replace "^$fapp[-\.]",''
#$papp = $pathsl -replace '^.*('/','\')
 
if ($DocType -eq '') {$DocType = $ftxd } # unless forced in param
if ($Productname -eq '') {$Productname = $fapp } # unless forced in param
if ($Producttype -eq '') {$Producttype = "Web";
if ($Productname -eq "mysql") {$Producttype="Database"}
if ($Productname -eq "vtom") {$Producttype="Tooling"}
}# unless forced in param
 
#try to stick to official : 
$off_txd=( "TDD (Tech Design Doc)", "TID (Tech Install Doc)", "unknown");
$off_app=("Apache", "ProFTPd","unknown");
ForEach($offi in $off_txd){if ($offi -match "^$DocType") {$DocType=$offi;break;}}
ForEach($offi in $off_app){if ($offi -match "^$Productname") {$Productname=$offi;break;}}
 
if ($fext.toLower() -match 'doc')
{
$application = New-Object -ComObject word.application
$application.Visible = $false
$document = $application.Documents.open($file)
}
if ($fext.toLower() -match 'xls')
{
$application = New-Object -ComObject Excel.Application
$application.Visible = $false
$document = $application.Workbooks.open($file)
}
if ( -Not ($document)) { Write-Host "ERR -file $file : $fext extension = ignored" ; Exit;}
 
$binding = "System.Reflection.BindingFlags" -as [type]
 
$customProperties = $document.CustomDocumentProperties
$typeCustomProperties = $customProperties.GetType()
 
[array]$arrayCPk = "Product name","ContentType","Product type","Doc Type"
[array]$arrayCPv = $Productname,$ContentType,$Producttype,$DocType
for($CPi=0; $CPi -lt 4; $CPi++){
$CustomProperty = $arrayCPk[$CPi]
$Value = $arrayCPv[$CPi]
 
#set custom prop
[array]$arrayArgs = $CustomProperty,$false, 4, $Value
Try
{
$typeCustomProperties.InvokeMember(`
"add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
out-null
}
Catch [system.exception]
{
$propertyObject = $typeCustomProperties.InvokeMember(`
"Item", $binding::GetProperty,$null,$customProperties,$CustomProperty)
$typeCustomProperties.InvokeMember(`
"Delete", $binding::InvokeMethod,$null,$propertyObject,$null)
$typeCustomProperties.InvokeMember(`
"add", $binding::InvokeMethod,$null,$customProperties,$arrayArgs) |
Out-Null
}
}
 
#set title
$propertyName='Title'
$value=$fname
$binding = "System.Reflection.BindingFlags" -as [type]
$builtinProperties = $document.BuiltInDocumentProperties
[Array]$getArgs = $propertyName
$builtinPropertiesType = $builtinProperties.GetType()
$builtinProperty = $builtinPropertiesType.InvokeMember( "Item", $binding::GetProperty, $null, $builtinProperties, $getArgs)
$builtinPropertyType = $builtinProperty.GetType()
[Array]$setArgs = $value
$builtinPropertyType.InvokeMember( "Value", $binding::SetProperty, $null, $builtinProperty, $setArgs)
 
$document.Saved = $false
$document.save()
$application.quit()
$application = $null
[gc]::collect()
[gc]::WaitForPendingFinalizers()

Comme pour les films, on est peu à peu moins enthousiaste quand le temps a passé.

Ici on voit :
– que les syntaxes et objets de mises à jour de custom properties sont lourdes, différentes entre doc et xls, différente pour le titre.
– que d’autres lignes de code (de validation par exemple) sont aussi cryptiques et sont bien sûr copiées d’exemples venant de MSDN.

Donc en gros c’est l’API microsoft qui est désespérante, tandis que le code autour est pas mal. ça date de 2007. voilà, on n’est pas fâché mais c’est pas suffisant pour l’adopter, même à la place des .BAT .