powershell exécute une commande externe n'acceptant pas le paramètre

j'exécute le code suivant en essayant d'exécuter le 7z.exe commande pour décompresser les fichiers.

$ dir contient l'entrée utilisateur du chemin vers le fichier zip qui peut contenir des espaces bien sûr! et $dirtemp2 ci-dessous est un dir que j'ai créé précédemment.

    Get-ChildItem -path $dir -Filter *.zip | 
    ForEach-Object { 
         $zip_path = """" + $dir + "" + $_.name + """"
         $output = " -o""$dirtemp2"""
         &7z e $zip_path $output
    }

quand je l'exécute, Je reçois ce qui suit de 7z.exe

7-Zip [64] 9.20 Copyright (c) 1999-2010 Igor Pavlov 2010-11-18

Archives de traitement: C:test dirtest.zip

Pas de fichiers à des processus de

des Fichiers: 0 Taille: 0 Comprimé: 50219965

si je copie alors la valeur de $zip_path et de $output pour former ma propre ligne cmd cela fonctionne!

par exemple : 7z e "c:test dirtest.zip "- o"c:test sortie 151920920"

maintenant, je peux reproduire le même message "Pas de fichiers à traiter" que j'obtiens lorsque j'exécute dans powershell en utilisant le suivant cmd dans cli.

7z e "c:test dirtest.zip "o"c:test sortie 151920920"

il semble donc que powershell supprime le dash char de l'option my-O. et OUI, il doit être -o"C:test sortie" et pas -o "c:test sortie" avec 7z.exe il n'y a pas d'espace entre le paramètre-o et la valeur.

je suis perplexe, je fais quelque chose de mal, ou devrais-je le faire d'une manière différente? toute suggestion ou aide merci

3
demandé sur john johnson 2013-09-11 19:49:27

3 réponses

Je ne peux jamais obtenir que L'expression Invoke (alias = &) fonctionne correctement non plus, donc j'ai appris à utiliser un objet process

    ZExe = (Get-Command -CommandType Application  -Name 7z )
    ZArgs = @(
        ('-o"{0}\{1}"' -f $dir, $_.Name), 
        ('"{0}\{1}"' -f $dir, 'temp2')
    )

    [Diagnostics.ProcessStartInfo]Zpsi = New-Object -TypeName:System.Diagnostics.ProcessStartInfo -Property:@{
        CreateNoWindow = $false;
        UseShellExecute = $false;
        Filename = ZExe.Path;
        Arguments = ZArgs;
        WindowStyle = 'Hidden';
        RedirectStandardOutput = $true
        RedirectStandardError = $true
        WorkingDirectory = $(Get-Location).Path
    }

    $proc = [System.Diagnostics.Process]::Start(zpsi)
    ZOut = $proc.StandardOutput
    ZErr = $proc.StandardError
    $proc.WaitForExit()
3
répondu Eris 2013-09-11 16:20:36

à l'Aide de l'excellent Process Explorer de la fenêtre Sysinternals suite j'ai pu observer de très intéressants comportement. J'ai un peu simplifié votre ligne de commande:

dir -Path $dir -Filter *.zip | 
  select FullName | 
  % { & 7za.exe e $_ "-o$dir\tmp" }

c'était en fait invoquer la ligne de commande suivante selon L'Explorateur de processus:

C:\tempza.exe @{FullName="C:\temp\test.zip"} -oC:\temp\test

disant à PowerShell d'étendre le nom complet la propriété la force à sortir du hashmap et la traite comme une chaîne régulière que 7-zip peut traiter:

dir -Path $dir -Filter *.zip | 
  select -ExpandProperty FullName | 
  % { & 7za.exe e $_ "-o$dir\tmp" }

il peut encore y avoir d'autres problèmes comme le traitement des espaces dans les noms de fichiers que je n'ai pas vraiment pris en considération ou pris en compte, mais j'ai pensé qu'il valait la peine d'ajouter une note que PowerShell (v2 dans ce cas) ne passait pas tout à fait les paramètres comme vous pourriez vous y attendre.

3
répondu Goyuix 2013-09-11 22:11:04

j'ai été en mesure de dupliquer la question exacte et essayé de nombreuses combinaisons échappant au -o commutateur et échapper à des citations " et ce qui ne l'est pas. Mais comme une réponse mentionnait SysInternals et j'ai utilisé ProcessMonitor pour trouver le format qu'il passait à 7z.exe. Les choses qui fonctionnent en ligne de commande ne fonctionnent pas à l'intérieur de powershell de la même manière. Par exemple, si j'essayais de construire des paramètres à L'intérieur de PowerShell tout comme cmdline, cela échouerait. I. e -o"C:\scripts\so\new folder" ne fonctionne pas. Mais si vous incluez -o switch inside quotes alors PowerShell passe la chaîne "-oC:\scripts\so\new folder" que 7z.exe est heureux d'accepter. Alors j'ai appris que 7z.exe accepterait les deux formats tels que

"C:\Program Files-zipz.exe" e "C:\scripts\so\new folder.zip" -o"C:\scripts\so\new folder"

et

"C:\Program Files-zipz.exe" e "C:\scripts\so\new folder.zip" "-oC:\scripts\so\new folder"

Et ces deux exemples contiennent des espaces.

[string]$pathtoexe = "C:\Program Files-Zipz.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"
Get-ChildItem -path $dir -Filter *.zip | % {        
    [array]$marguments = "e",$_.FullName,"-o$output";    
    & $pathtoexe $marguments 
}

une autre approche dans PS V3 est d'échapper à la fonction de parsing powershell. Vous pouvez utiliser la commande --% pour dites à powershell d'arrêter d'analyser d'autres commandes comme celle-ci.

$zipfile = "C:\scripts\so\newfolder.zip"
$destinationfolder = "C:\scripts\so\New Folder"
[string]$pathtoexe = "C:\Program Files-Zipz.exe"
& $pathtoexe --% e "C:\scripts\so\newfolder.zip" -o"C:\scripts\so\new folder"

en utilisant la syntaxe --% vous tapez des commandes exactement comme vous les taperiez en ligne de commande. J'ai testé cette logique et elle extrait des fichiers vers le dossier de destination.

pour en savoir plus sur --% vérifier PS> help about_parsing

Le problème avec cette approche est, après --% il n'est pas possible d'inclure la variable. La Solution à ce problème est simplement d'inclure les --% comme une autre variable de chaîne et passer comme ça. Et cette approche est similaire à celle de la ligne de commande qui ne fonctionnait pas à l'origine.

[string]$pathtoexe = "C:\Program Files-Zipz.exe"
$dir = "C:\scripts\so"
$output = "$dir\new folder"
Get-ChildItem -path $dir -Filter *.zip | % {        
$zipfile = $_.FullName;
[string]$formated = [System.String]::Concat("e ", """$zipfile"""," -o""$output""");
[string]$stopparser = '--%';
& $pathtoexe $stopparser $formated; 
}
3
répondu Mitul 2013-09-12 19:46:51