Question [Function] Récupération des types mime

Plus d'informations
il y a 17 ans 9 mois #2427 par Laurent Dardenne
Une petite fonction permettant de déterminer le type mime d'un fichier :
[code:1]
################################################################################
#
# Nom : Get-TypeMime
# Récupère, dans la base de registre, les codages des types de fichiers (MIME)
#
# Version : 0.1
# Auteur : Laurent Dardenne
# Date : le 02/06/2008
#
################################################################################
Function Get-TypeMime()
{ #Récupère les formats MIME
Push-Location
cd HKLM:\SOFTWARE\Classes
#On ne prend que les clés portant sur une extension de fichier sauf celles contenant '*' qui
#renvoient sur la même liste
dir \".*\"|Where {!($_.Name -match \"\*\"«»)}|`
#Pour chaque clés on parcourt la liste des propriétés
#Seul nous intéresse les clés ayant la propriété \"Content Type\"
Foreach {get-itemproperty -path $_.PSPath|Foreach {if ($_.\"Content Type\" -ne $null«») {$_}} }|`
#On récupére le couple extension, mimeType dans une hastable (.bmp,image/bmp)
Foreach {$Result=@{}} {$Result.($_.PSChildName)=$_.'Content type'} {$Result}
Pop-Location
}[/code:1]
Usage :
[code:1]
$Mime=Get-TypeMime

Dir |Where-Object { ($_.PSIsContainer -eq 0)} |% { if ($Mime.($_.Extension) -match \"^(.*)/(.*)$\"«»)
{$Current=$_
switch ($matches[1])
{
\"text\" {\"Texte : $Current\"}
\"image\" {\"Image : $Current\"}
\"application\" {\"Exécutable : $Current\"}
\"audio\" {\"Audio : $Current\"}
default {\"Mime inexistant\"}
}
}
}
[/code:1]
Reste un pb, un fichier peut porter une extension qui ne soit pas en phase avec sont contenu. Par exemple un fichier .doc peut être un fichier texte ou un fichier MS-Word. Dans ce cas voir l’analyse du fichier via l’API FindMimeFromData ...<br><br>Message édité par: Laurent Dardenne, à: 24/06/08 21:20

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 9 mois #2449 par Arnaud Petitjean
Bonjour Laurent,

Merci pour ton script, nous le mettrons dans la bibliothèque prochainement. En attendant, pourrais-tu stp donner un ou deux exemples d'utilisations et nous dire dans quel cas il peut être utile ?

Cordialement,

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 9 mois #2454 par Laurent Dardenne
Salut,
Arnaud écrit:

et nous dire dans quel cas il peut être utile ?

Le projet suivant www.codeplex.com/paws utilise une liste de constantes, j'ai préféré une approche dynamique.

Si on souhaite effectuer un traitement selon le contenu d'un fichier, i.e. comment l'interpréter.
On peut vouloir ne copier que les images d'un répertoire, sans se préoccuper des extensions de fichiers.
Le mime est \&quot;une sorte de typage du contenu\&quot;. Mais cela ne fonctionne que pour quelques cas : \&quot;text\&quot;,\&quot;image\&quot;.

Arnaud écrit:

pourrais-tu stp donner un ou deux exemples d'utilisations

A l'origine je recherchais un moyen pour déterminer le contenu d'un fichier afin de créer un fichier de ressource :
[code:1]Get-ChildItem * | Where-Object { ($_.PSIsContainer -eq 0)| ConvertTo-Resource|Create-Resource (join-path $pwd Tst1.resources)[/code:1]
Et ça fonctionne !
Je peux donc automatiser la création de fichiers de ressources avec qq limites, ce sera un outil complémentaire au script de conversion de WinForm.

Le code de création de ressources utilisant les types mime :
[code:1]
process
{
$Current=$_
if ($Current -is [System.IO.FileInfo])
{ write-Debug (\&quot;File extension : {0}\&quot; -F $Current.Extension)
write-Debug (\&quot;Mime : {0}\&quot; -F $global:Mime.($Current.Extension))
#Extrait le champ 'discrete-type' du type Mime correspondant à l'extension du fichier courant
if ($global:Mime.($Current.Extension) -match \&quot;^(.*)/(.*)$\&quot;«»)
{ write-Debug (\&quot;Match extension : {0}\&quot; -F $matches[1])
switch ($matches[1]) {
#RFC : discrete-type := \&quot;text\&quot; / \&quot;image\&quot; / \&quot;audio\&quot; / \&quot;video\&quot; /\&quot;application\&quot; / extension-token
\&quot;image\&quot; { #Lit les données de l'image à partir du fichier
$Image=[System.Drawing.Image]::FromFile($Current.FullName)
$Data=@{
Name=$Current.Name
#L'image doit être dupliquée sinon l'appel à Dispose supprime l'objet
#Ces objets devront dont être supprimés manuellement
Value=$Image.Clone()
ResourceType=(&amp;$sbFindImageFormat $Image.RawFormat.Guid)
}#$Data
$Image.Dispose()
}
\&quot;text\&quot; {...
[/code:1]
Je suis en train de finaliser ces scripts et de rédiger un tutoriel sur la gestion des ressources et des flux ADS.
C'est vrai que ce n'est pas tout à fait un script d'administration :)

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 9 mois #2457 par Arnaud Petitjean
Bonjour Laurent,

Merci pour ces précisions utiles ;)

Je t'avouerais n'avoir rien compris aux fichiers de ressources associés aux Winforms; mais bon je n'ai pas trop cherché...

D'après ce que j'ai vu dans la dernière mouture du convertisseur de Winforms tu fais appelle à un exe pour convertir ce fichiers ? Peut-être devrions nous ouvrir un autre fil de discussion pour en parler ?

Arnaud

MVP PowerShell et créateur de ce magnifique forum :-)
Auteur de 6 livres PowerShell aux éditions ENI
Fondateur de la société Start-Scripting
Besoin d'une formation PowerShell ?

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 9 mois #2461 par Laurent Dardenne
Arnaud écrit:

Peut-être devrions nous ouvrir un autre fil de discussion pour en parler ?

Je suis d'accord, si tu veux des détails sur les fichier de resources et leurs implémentation sous Convert-Form pas de pb.
Je te laisse ouvrir le post ;)

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Plus d'informations
il y a 17 ans 8 mois #2507 par Laurent Dardenne
Correction d'une erreur dans le test suivant :
[code:1]
if ($_.\&quot;Content Type\&quot; -ne \&quot;\&quot;«»)
[/code:1]
on doit tester sur la valeur $null :
[code:1]
if ($_.\&quot;Content Type\&quot; -ne $null)
[/code:1]
Sinon la hastable contient des entrées vides...
Arnaud écrit:

D'après ce que j'ai vu dans la dernière mouture du convertisseur de Winforms tu fais appelle à un exe pour convertir ce fichiers ?

Pour info :

Pour définir ce qu'est une ressource (msdn.microsoft.com/fr-fr/library/f45fce5x.aspx ) :
«Une ressource est une donnée non exécutable qui est déployée logiquement avec une application. Une ressource peut être affichée dans une application sous la forme d'un message d'erreur ou comme faisant partie de l'interface utilisateur. Les ressources peuvent contenir des données sous plusieurs formes, telles que des chaînes, des images et des objets rendus persistants. Le stockage de vos données dans un fichier de ressources vous permet de changer les données sans avoir à recompiler l'intégralité de votre application. Pour écrire des objets rendus persistants dans un fichier de ressources, les objets doivent être sérialisables.»

Pour le script Convert-Form, il faut regarder la fonction CompileRessources dans le fichier PackageConvert-Form.ps1.
Cette fonction permet à l'aide de l'outil du sdk .net Resgen.exe de compiler un fichier de déclaration de ressources (.resx) en un fichier binaire (.resources).
Les deux sont structurés, le premier est un fichier xml

&lt;?xml version=\&quot;1.0\&quot; encoding=\&quot;utf-8\&quot;?&gt;
&lt;root&gt;
&lt;!--
Microsoft ResX Schema
...
&lt;data name=\&quot;button1.Image\&quot; type=\&quot;System.Drawing.Bitmap, System.Drawing\&quot; mimetype=\&quot;application/x-microsoft.net.object.bytearray.base64\&quot;&gt;
...

Le second est un fichier binaire contenant +- une hastable, l'accés à une resource se faisant par un nom.
On peut voir avec un éditeur HEX que le début du fichier binaire contient les clés puis les données.

Donc lors de la conception d'un projet Winform sous Visual Studio, l'ajout d'une image dans un composant crée une entrée dans le fichier de resources (.rsx).
Comme ici on n'utilise pas le code compilé mais le code C# du designer on doit créer ce fichier de resource (binaire) sous PowerShell.

Dans le script principal on recherche les occurences de la classe ComponentResourceManager :
[code:1]
#Contrôle la présence d'un composant de gestion de ressources (images graphique principalement)
if ($IsUsedResources -eq $false){
$crMgr=[regex]::match($Components[$i],\&quot;\s= new System\.ComponentModel\.ComponentResourceManager\(typeof\((.*)\)\);$\&quot;«»)
if ($crMgr.success){
$IsUsedResources = $True
$Components[$i]=AjouteGestionRessources
continue
}
[/code:1]
A partir de là on sait si un fichier WinForm utilise ou non un fichier de resource. Comme il existe un fichier de resource par WinForm on connaît directement le nom du fichier à générer.

Lors de la génération du fichier .ps1 on place en début de script l'appel de la création d'une hastable avec les données du fichier de ressource, voir la function AjouteGestionRessources :
[code:1]
#Gestion du fichier des ressources
`$Reader = new-Object System.Resources.ResourceReader(\&quot;`$RessourcesPath\&quot;«»)
`$Ressources=@{}
`$Reader.GetEnumerator()|% {`$Ressources.(`$_.Name)=`$_.value}
[/code:1]
Reste à insérer les accès aux ressources :
[code:1]
#Traite les ressources images
If ($IsUsedResources)
{ #Todo : factoriser l'expression
$Ligne = $Ligne -replace \&quot;^(.*)= (\(\(System.Drawing.Image\)\(resources.GetObject\(`\&quot;«»)(.*)`\&quot;\)\)\)$\&quot;, '$1= [System.Drawing.Image] $Ressources[\&quot;$3\&quot;]'
$Ligne = $Ligne -replace \&quot;^(.*)= (\(\(System.Drawing.Icon\)\(resources.GetObject\(`\&quot;«»)(.*)`\&quot;\)\)\)$\&quot;, '$1= [System.Drawing.Icon] $Ressources[\&quot;$3\&quot;]'
}
[/code:1]
Ici $1 et $3 sont des références au groupes de l'expression réguliéres (cf. parenthèses) et non pas à des variables PS.
Donc le code C# suivant
[code:1]
this.button1.Image = ((System.Drawing.Image)(resources.GetObject(\&quot;button1.Image\&quot;«»)));
[/code:1]
devient
[code:1]
$button1.Image = [System.Drawing.Image] $Ressources[\&quot;button1.Image\&quot;]
[/code:1]
Visual Studio caste la ressource en une instance de classe image car toutes les images sont vues, à partir du fichier de ressource, comme des Bitmap.
D'où la méthode Get-ImageFormat

Un fichier de ressource pouvant être utilisé pour la localisation :
[code:1]
#Test-Localisation
#passer une hashtable à convert
$htEnglish=@{Bienvenue=\&quot;Hello\&quot;}
$htGerman=@{Bienvenue=\&quot;Hallo\&quot;}
$htSpanish=@{Bienvenue=\&quot;Hola\&quot;}
$htFrench=@{Bienvenue=\&quot;Salut\&quot;}

$resName=\&quot;Eng\&quot;
$FileName=(join-path $pwd $resName+\&quot;.resources\&quot;«»)

$htEnglish|ConvertTo-Resource -FromHashTable|Create-Resource $FileName
$Msg=Read-Resources $FileName
$Msg.\&quot;Bienvenue\&quot; #Affiche Hello
[/code:1]
-$FromHashTable indique que l'on crée une ressource pour chaque éléments des objets de type HashTable.
Dans ce cas l'objet Hashtable ne pourra pas être reconstruit via Read-Resources. Par défaut pour les objets de type HashTable on crée une seule ressource.

On peut utiliser les fichiers satellite mais mon approche moins académique simplifie, je pense, la mise en oeuvre.
Quitte a utiliser une information de culture au lieu d'un nom arbitraire.
C'est ce propose +- la version 2 de PowerShell dans cet exemple .

Voilà, j'ai ajouté ce texte dans la documentation pour la prochaine version de Convert-Form.<br><br>Message édité par: Laurent Dardenne, à: 24/06/08 21:36

Tutoriels PowerShell

Connexion ou Créer un compte pour participer à la conversation.

Temps de génération de la page : 0.056 secondes
Propulsé par Kunena