Si la fonction Add-Type est appelée pour ajouter un extrait de code C # dans une fonction, le "type" sera-t-il récupéré une fois que la fonction aura fini de s'exécuter? Ou le type existera-t-il toujours en mémoire car il faisait partie d'un assembly (virtuel) chargé dans l'AppDomain? (Étant ainsi une "fuite de mémoire")

Dans la définition Lock-WorkStation ci-dessous, Add-Type est utilisé pour ajouter un code écrit en C #:

function Lock-WorkStation {
    $signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@

    $name = "Win32LockWorkStation"
    $LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace Win32Functions -PassThru
    $LockWorkStation::LockWorkStation() | Out-Null
}

Ma question est la suivante: si cette fonction est appelée plusieurs types, elle analyse et ajoute constamment le code C # en tant qu'assemblage (virtuel). (Ou est-il ramassé?)

Est-il préférable de l'écrire comme :

Function Lock-WorkStation {
    if (!$Global:LockWorkStation) {
        $signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
        $name = "Win32LockWorkStation"
        $global:LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace Win32Functions -PassThru
    }

    $global:LockWorkStation::LockWorkStation() | Out-Null
}

Pour que le code C # ne soit instancié en tant qu'assembly qu'une seule fois?

1
Tahir Hassan 5 avril 2017 à 01:24

2 réponses

Meilleure réponse

Merci Mathias pour ta réponse. Ma question, cependant, était de savoir si l'appel à Add-Type instancie le type à chaque fois qu'il est appelé. J'ai regardé la documentation, qui dit:

Le nom du type et l'espace de noms doivent être uniques au sein d'une session. Vous ne pouvez pas décharger un type ou le modifier. Si vous devez modifier le code d'un type, vous devez modifier le nom ou démarrer une nouvelle session Windows PowerShell. Sinon, la commande échoue. (Documentation Add-Type)

Add-Type instanciera le type de la première fois qu'il est appelé . Lors des prochains appels avec les mêmes arguments , parce que le type existe déjà, il ne fera rien . Par conséquent, la seule raison pour inclure une condition if sur l'instruction Add-Type, est pour des raisons d'efficacité, car un appel à Add-Type a la surcharge de vérifier si le type existe déjà.

Votre condition if:

-not ($LockWorkStation = "$namespace.$name" -as [type])

IMHO, n'est pas efficace car il utilise l'interpolation de chaîne pour calculer le nom du type, puis il vérifie si le type existe, puis il affecte le type à une variable, chaque fois qu'il s'exécute.

Au lieu de cela, vous pouvez définir la variable de type une fois (la portée étant Script:). L'instruction if peut vérifier si elle est nulle, et si oui, l'instancier:

function Lock-WorkStation {
    if ($Script:Win32LockWorkStation -eq $null) {
        $namespace = 'Win32Functions'
        $name = 'Win32LockWorkStation'

        $signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
        $Script:Win32LockWorkStation = Add-Type -Namespace $namespace -Name $name -MemberDefinition $signature -PassThru
    }

    $Script:Win32LockWorkStation::LockWorkStation() | Out-Null
}

Si vous le souhaitez, vous pouvez consulter ma comparaison de performances de différentes manières d'utiliser Add-Type dans une fonction.

1
Tahir Hassan 9 avril 2017 à 06:00

Testez si le type résultant existe déjà:

function Lock-WorkStation {
    $name = 'Win32LockWorkStation'
    $namespace = 'Win32Functions'
    $signature = @'
[DllImport("user32.dll", SetLastError = true)]
public static extern bool LockWorkStation();
'@
    if(-not ($LockWorkStation = "$namespace.$name" -as [type])){
        $LockWorkStation = Add-Type -MemberDefinition $signature -Name $name -Namespace $namespace -PassThru
    }
    $LockWorkStation::LockWorkStation() | Out-Null
}
1
Mathias R. Jessen 4 avril 2017 à 22:31