Question [fonction]Génération d'assembly à partir d'une TLB
- Laurent Dardenne
- Auteur du sujet
- Hors Ligne
- Modérateur
-
Réduire
Plus d'informations
- Messages : 6298
- Remerciements reçus 68
il y a 11 ans 1 mois #12903
par Laurent Dardenne
Tutoriels PowerShell
Voici une fonction de création d'un assembly interop à partir d'une librairie de type (.TLB ).
Elle utilise en interne cette fonction et peut être couplé avec celle-ci .
Cett fonction est de préférence destinée aux développeurs, en tout cas doit être utilisée sur un poste disposant du SDK Windows(en particulier l'utilitaire TlbImp.exe).
L'invite de commande Visual Studio définie par défaut une variable d'environnement nommée WindowsSdkDir qui pointe sur le répertoire du SDK.
Cette fonction en dépend, le projet PSCX permet de l'importer dans la session PowerShell :
[code:1]
Import-VisualStudioVars 2010 #PSCX 3.0
[/code:1]
Vous pouvez la créé ainsi :
[code:1]
New-Item Env: -Name WindowsSdk -Value (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows' -Name 'CurrentInstallFolder').CurrentInstallFolder
[/code:1]
Le code de la fonction
[code:1]
Function ConvertTo-InteropAssembly {
[cmdletBinding()]
#Convertie une librairie de type (COM) en un assembly (.NET)
Param (
[Parameter(Position=0, Mandatory=$true,ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]$TlbPath,
#Par défaut utilise le nom IDL de la library précisée dans la TLB
#Si aucun nom de fichier n'est précisé, on récupére le nom IDL
#que l'on préfixe avec 'Interop.'
[Parameter(Position=1)]
[ValidateNotNullOrEmpty()]
[string]$Destination,
#Par défaut utilise le nom IDL de la TLB
[Parameter(Position=2)]
[string]$Namespace,
[Parameter(Position=3)]
[ValidateNotNullOrEmpty()]
[string]$keyfile,
#Par défaut utilise le numéro de version de la TLB
[Parameter(Position=4)]
[ValidateNotNullOrEmpty()]
[Version]$AssemblyVersion=\"0.0.0.0\",
[switch] $Primary
)
begin {
$TlbImpParseur={
#Parse le résultat d'exécution du programme TlbImp.exe
$Line=$_
switch -regex ($Line) {
' : warning (?<Code>.*[^:]) : (?<Message>.*)' {Write-Warning (\"{0} : {1}\" -f $Matches.Code,$Matches.Message)}
' : error (?<Code>.*[^:]) : (?<Message>.*)' {Write-Error (\"TlbImp.exe : {0} : {1}\" -f $Matches.Code,$Matches.Message)}
'^TlbImp : (?<Message>(?!warning|error).*)' {Write-Verbose (\"{0}\" -f $Matches.Message)}
#On affecte le nom de l'assembly généré automatiquement à la variable $OutFileName définie dans la portée de l'appelant
'Type library imported to ((?<FileName>.*)$)' {(Get-variable OutFileName -scope 1).Value=$Matches.FileName}
} #switch
}#code du parseur
}#begin
process {
if (-Not (Test-path env:WindowsSdkDir))
{Throw \"La variable d'environnement WindowsSdkDir n'est pas déclarée.\"}
if (-Not (Test-Path $TlbPath))
{ Write-Error \"Le paramètre TlbPath référence un fichier inexistant : $TlbPath\" }
else
{
$isDestination=$false
$Tlbimp=Join-Path ${env:WindowsSdkDir} \"bin\TlbImp.exe\"
#Sur les frameworks plus récent tlbimp propose de nouveaux paramètres
$cmd=\"&`\"$Tlbimp`\" `\"$TlbPath`\" /nologo\"
if ($Namespace.Trim() -ne [string]::Empty)
{ $cmd +=\" /namespace:$Namespace \" }
if ($Destination.Trim() -ne [string]::Empty)
{
$cmd +=\" /out:`\"$Destination`\" \"
$isDestination=$true
}
if ($AssemblyVersion -ne \"0.0.0.0\"«»)
{ $cmd +=\" /asmversion:$AssemblyVersion \" }
if ($Primary)
{ $cmd +=\" /primary \" }
if ($KeyFile.Trim() -ne [string]::Empty)
{
if ((Test-Path $KeyFile))
{ $cmd +=\" /keyfile:$KeyFile \" }
else
{ Throw \"Le paramètre KeyFile référence un fichier inexistant: $KeyFile\" }
}
#Doit être la dernière instruction
$cmd +=\" 2>&1\"
#Création de la variable référencée dans le code $TlbImpParseur
$OutFileName=\"*\"
Write-Debug \"Commande exécutée :`r`n $cmd\"
#On s'assure que le runspace pointe sur le FS
$isNotLocationInFS=(Get-Location).Provider.Name -ne 'FileSystem'
if ($isNotLocationInFS)
{ $Location=(Get-PSProvider 'FileSystem').Home }
else
{ $Location=Get-Location }
#Génération de l'assembly à partir d'une librairie de type (COM)
Invoke-ConsoleProgram $cmd $TlbImpParseur $Location
#Si besoin récupère le nom de fichier généré automatiquement
#En cas d'erreur $OutFileName vaut '*'
if (-not $isDestination -and ($OutFileName -ne '*'))
{
Write-Debug \"TlbImp à généré le fichier $OutFileName\"
$NewFileName=\"$Location\Interop.$OutFileName\"
Write-Debug \"Renommage du fichier '$NewFileName'.\"
if (Test-Path $NewFileName)
{
Write-Debug \"Suppression du fichier '$NewFileName'.\"
Remove-Item $NewFileName -Force
}
Rename-Item \"$Location\$OutFileName\" $NewFileName
if ($isNotLocationInFS)
{ Write-Warning \"Génération dans le répertoire $Location\" }
}
}
}#process
} #ConvertTo-InteropAssembly
[/code:1]
Un exemple d'utilisation :
[code:1]
Import-VisualStudioVars 2010 #PSCX 3.0
Set-Location C:\Temp
$Error.clear()
$WarningPreference='Continue'
ConvertTo-InteropAssembly -TlbPath 'C:\Windows\system32\activeds.tlb' -ErrorVariable tlbError -WarningVariable tlbWarning
$tlbWarning
$tlbError
#La collection $Error n'est pas impactée par l'exécution du process TlbImp.exe, exécution redirigeant le flux d'erreur
$WarningPreference='SilentlyContinue'
ConvertTo-InteropAssembly -TlbPath 'C:\Windows\system32\activeds.tlb' -ErrorVariable tlbError -WarningVariable tlbWarning
$tlbError
$tlbWarning
[/code:1]
Le code est encore en phase de test, mais est fonctionnel pour des besoins simples.
Elle utilise en interne cette fonction et peut être couplé avec celle-ci .
Cett fonction est de préférence destinée aux développeurs, en tout cas doit être utilisée sur un poste disposant du SDK Windows(en particulier l'utilitaire TlbImp.exe).
L'invite de commande Visual Studio définie par défaut une variable d'environnement nommée WindowsSdkDir qui pointe sur le répertoire du SDK.
Cette fonction en dépend, le projet PSCX permet de l'importer dans la session PowerShell :
[code:1]
Import-VisualStudioVars 2010 #PSCX 3.0
[/code:1]
Vous pouvez la créé ainsi :
[code:1]
New-Item Env: -Name WindowsSdk -Value (Get-ItemProperty 'HKLM:\SOFTWARE\Microsoft\Microsoft SDKs\Windows' -Name 'CurrentInstallFolder').CurrentInstallFolder
[/code:1]
Le code de la fonction
[code:1]
Function ConvertTo-InteropAssembly {
[cmdletBinding()]
#Convertie une librairie de type (COM) en un assembly (.NET)
Param (
[Parameter(Position=0, Mandatory=$true,ValueFromPipeline = $true)]
[ValidateNotNullOrEmpty()]
[string]$TlbPath,
#Par défaut utilise le nom IDL de la library précisée dans la TLB
#Si aucun nom de fichier n'est précisé, on récupére le nom IDL
#que l'on préfixe avec 'Interop.'
[Parameter(Position=1)]
[ValidateNotNullOrEmpty()]
[string]$Destination,
#Par défaut utilise le nom IDL de la TLB
[Parameter(Position=2)]
[string]$Namespace,
[Parameter(Position=3)]
[ValidateNotNullOrEmpty()]
[string]$keyfile,
#Par défaut utilise le numéro de version de la TLB
[Parameter(Position=4)]
[ValidateNotNullOrEmpty()]
[Version]$AssemblyVersion=\"0.0.0.0\",
[switch] $Primary
)
begin {
$TlbImpParseur={
#Parse le résultat d'exécution du programme TlbImp.exe
$Line=$_
switch -regex ($Line) {
' : warning (?<Code>.*[^:]) : (?<Message>.*)' {Write-Warning (\"{0} : {1}\" -f $Matches.Code,$Matches.Message)}
' : error (?<Code>.*[^:]) : (?<Message>.*)' {Write-Error (\"TlbImp.exe : {0} : {1}\" -f $Matches.Code,$Matches.Message)}
'^TlbImp : (?<Message>(?!warning|error).*)' {Write-Verbose (\"{0}\" -f $Matches.Message)}
#On affecte le nom de l'assembly généré automatiquement à la variable $OutFileName définie dans la portée de l'appelant
'Type library imported to ((?<FileName>.*)$)' {(Get-variable OutFileName -scope 1).Value=$Matches.FileName}
} #switch
}#code du parseur
}#begin
process {
if (-Not (Test-path env:WindowsSdkDir))
{Throw \"La variable d'environnement WindowsSdkDir n'est pas déclarée.\"}
if (-Not (Test-Path $TlbPath))
{ Write-Error \"Le paramètre TlbPath référence un fichier inexistant : $TlbPath\" }
else
{
$isDestination=$false
$Tlbimp=Join-Path ${env:WindowsSdkDir} \"bin\TlbImp.exe\"
#Sur les frameworks plus récent tlbimp propose de nouveaux paramètres
$cmd=\"&`\"$Tlbimp`\" `\"$TlbPath`\" /nologo\"
if ($Namespace.Trim() -ne [string]::Empty)
{ $cmd +=\" /namespace:$Namespace \" }
if ($Destination.Trim() -ne [string]::Empty)
{
$cmd +=\" /out:`\"$Destination`\" \"
$isDestination=$true
}
if ($AssemblyVersion -ne \"0.0.0.0\"«»)
{ $cmd +=\" /asmversion:$AssemblyVersion \" }
if ($Primary)
{ $cmd +=\" /primary \" }
if ($KeyFile.Trim() -ne [string]::Empty)
{
if ((Test-Path $KeyFile))
{ $cmd +=\" /keyfile:$KeyFile \" }
else
{ Throw \"Le paramètre KeyFile référence un fichier inexistant: $KeyFile\" }
}
#Doit être la dernière instruction
$cmd +=\" 2>&1\"
#Création de la variable référencée dans le code $TlbImpParseur
$OutFileName=\"*\"
Write-Debug \"Commande exécutée :`r`n $cmd\"
#On s'assure que le runspace pointe sur le FS
$isNotLocationInFS=(Get-Location).Provider.Name -ne 'FileSystem'
if ($isNotLocationInFS)
{ $Location=(Get-PSProvider 'FileSystem').Home }
else
{ $Location=Get-Location }
#Génération de l'assembly à partir d'une librairie de type (COM)
Invoke-ConsoleProgram $cmd $TlbImpParseur $Location
#Si besoin récupère le nom de fichier généré automatiquement
#En cas d'erreur $OutFileName vaut '*'
if (-not $isDestination -and ($OutFileName -ne '*'))
{
Write-Debug \"TlbImp à généré le fichier $OutFileName\"
$NewFileName=\"$Location\Interop.$OutFileName\"
Write-Debug \"Renommage du fichier '$NewFileName'.\"
if (Test-Path $NewFileName)
{
Write-Debug \"Suppression du fichier '$NewFileName'.\"
Remove-Item $NewFileName -Force
}
Rename-Item \"$Location\$OutFileName\" $NewFileName
if ($isNotLocationInFS)
{ Write-Warning \"Génération dans le répertoire $Location\" }
}
}
}#process
} #ConvertTo-InteropAssembly
[/code:1]
Un exemple d'utilisation :
[code:1]
Import-VisualStudioVars 2010 #PSCX 3.0
Set-Location C:\Temp
$Error.clear()
$WarningPreference='Continue'
ConvertTo-InteropAssembly -TlbPath 'C:\Windows\system32\activeds.tlb' -ErrorVariable tlbError -WarningVariable tlbWarning
$tlbWarning
$tlbError
#La collection $Error n'est pas impactée par l'exécution du process TlbImp.exe, exécution redirigeant le flux d'erreur
$WarningPreference='SilentlyContinue'
ConvertTo-InteropAssembly -TlbPath 'C:\Windows\system32\activeds.tlb' -ErrorVariable tlbError -WarningVariable tlbWarning
$tlbError
$tlbWarning
[/code:1]
Le code est encore en phase de test, mais est fonctionnel pour des besoins simples.
Tutoriels PowerShell
Connexion ou Créer un compte pour participer à la conversation.
Temps de génération de la page : 0.068 secondes
- Vous êtes ici :
-
Accueil
-
forum
-
PowerShell
-
Contributions à la communauté
- [fonction]Génération d'assembly à partir d'une TLB