2016-08-03 17 views
0

Ich bin in einer seltsamen Situation. Ich habe eine ziemlich große Anzahl von PowerShell-Modulen und -Funktionen erhalten, und es ist meine Aufgabe, diese zu einer ausführbaren Datei zusammenzufügen. Die Anforderungen legen fest, dass es sich um eine einzelne eigenständige ausführbare Datei ohne Installationsprogramm handeln muss und dass .net 3.5 möglicherweise die einzige Abhängigkeit darstellt. Das Windows Management Framework ist keine Ausnahme und es kann nicht davon ausgegangen werden, dass es auf dem Computer vorhanden ist. Um dies zu umgehen, habe ich System.Management.Automation als Referenz hinzugefügt und es zu einer eingebetteten Ressource zusammen mit allen PowerShell-Moduldateien gemacht und sie zur Laufzeit aus der Reflektion geladen. Dies scheint in Ordnung zu sein, aber ich habe einige Fehler, die ich nicht zu verstehen scheint, und denke, dass es etwas mit diesem System zu tun haben könnte.C#: ArgumentException beim Aufruf von System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace()

Also hier ist das Problem: Wenn ich beginne, Dinge zu initialisieren, um den PowerShell-Befehl auszuführen, erhalte ich einen seltsamen Fehler, den ich nicht kontrollieren kann. Hier

ist der Code:

public static void RunCommand(object objcommand) 
    { 
     //create a script block for toolbox once, get the embeded resource, convert from byte array to string, make scriptblock from string 
     ScriptBlock toolbox = System.Management.Automation.ScriptBlock.Create(System.Text.Encoding.Default.GetString(Properties.Resources.toolbox)); 
     string command = (string)objcommand; 
     //get the module name 
     string modname = options.Commands[command]["module"]; 
     //get the module from the embeded resources, convert to string, convert to scriptblock 
     var module = System.Management.Automation.ScriptBlock.Create(new System.IO.StreamReader(myasm.GetManifestResourceStream("piramids.Resources." + modname + ".psm1")).ReadToEnd()); 
     using (var powerShell = PowerShell.Create()) 
     { 
      System.Management.Automation.Runspaces.Runspace rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(); //i think this line triggers the exception 
      rs.Open(); 
      powerShell.Runspace = rs; 


      //make the necesary powershell modules of the command availible 
      powerShell.AddCommand("new-module").AddParameter("ScriptBlock", toolbox).Invoke(); 
      powerShell.AddCommand("new-module").AddParameter("ScriptBlock", module).Invoke(); 


      //if inethistory, make dlls availible 
      if (modname.Equals("inethistory")) 
      { 
       powerShell.AddCommand("add-type").AddParameter("Path", sqldll).Invoke(); 
       powerShell.AddCommand("add-type").AddParameter("Path", esentdll).Invoke(); 
      } 



      ICollection<PSObject> output = new List<PSObject>(0); 
      try { 
       output = powerShell.AddCommand("get-" + command).AddCommand(format).AddCommand("out-string").Invoke();//pipeline.Invoke(); 
      } catch (System.Management.Automation.RuntimeException e) 
      { 
       Console.Error.WriteLine("An Error occured while executing '" + command + "'"); 
       Console.Error.WriteLine(e.Message); 
      } 
     //do stuff with the results 

und hier ist der Stack-Trace:

Unhandled Exception: System.ArgumentException: The path is not of a legal form. 
    at System.IO.Path.NormalizePathFast(String path, Boolean fullCheck) 
    at System.IO.Path.NormalizePath(String path, Boolean fullCheck) 
    at System.IO.Path.GetFullPathInternal(String path) 
    at System.IO.Path.GetFullPath(String path) 
    at System.Diagnostics.FileVersionInfo.GetFullPathWithAssert(String fileName) 
    at System.Diagnostics.FileVersionInfo.GetVersionInfo(String fileName) 
    at System.Management.Automation.PSVersionInfo.GetPSVersionTable() 
    at System.Management.Automation.PSVersionInfo.get_PSVersion() 
    at Microsoft.PowerShell.DefaultHost..ctor(CultureInfo currentCulture, CultureInfo currentUICulture) 
    at System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace() 
    at piramids.Program.RunCommand(Object objcommand) 
    at piramids.Program.Main(String[] args) 

ich diese Linie glauben ist, wo die Ausnahme auftritt:

System.Management.Automation.Runspaces.Runspace rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(); 

Die CreateRunspace Methode ist nicht dokumentiert, um irgendwelche Ausnahmen zu werfen, und diese Ausnahme kommt von so vielen Ebenen, dass ich keine Ahnung habe was Art von Pfad, den dieses Ding prüft, da ich nie eine Funktion aufgerufen habe, die nach einem Pfad gefragt hat.

Ich bin ratlos. Hat jemand eine Idee, was das verursachen könnte?

EDIT: Nach etwas graben, hier ist was ich gefunden habe. PSVersionTable ist ein statisches Feld von VersionInfo, daher wird der statische Konstruktor aufgerufen, wenn das erste Mal get für dieses Feld aufgerufen wird. Der statische Konstruktor ruft eine interne Methode namens GetBuildVersion auf, die versucht, den Assembly-Speicherort von PSVersionInfo abzurufen. Nach This documentation page:

Wenn die Anordnung aus einem Byte-Array geladen wird, wie beispielsweise, wenn die Last (Byte []) -Methodenüberladung Verwendung der zurückgegebene Wert eine leere Zeichenfolge („“).

Ich lade von einem Byte-Array, so dass dies eine leere Zeichenfolge wird. Aber GetBuildVersion verwendet diesen Speicherort, um FileVersionInfo.GetVersionInfo auszuführen, das den Pfad mit Path.GetFullPath überprüft. Nach This documentation page:

Argument:
der Weg dort

So eine Zeichenfolge der Länge Null ist, ist das Problem. Jetzt lautet die Frage: Wie weise ich einer Assembly, die aus einem Byte-Array geladen wurde, einen Speicherort zu? Möge Gott mir gnädig sein.

+0

Welche Linie löst die Ausnahme aus? – briantist

+0

Entschuldigung, diese: System.Management.Automation.Runspaces.Runspace rs = System.Management.Automation.Runspaces.RunspaceFactory.CreateRunspace(); – Sandles

+0

Die Verwendung von reflector auf GetPSVersionTable() ergibt: "string location = Assembly.GetExecutingAssembly(). Location; Zeichenfolge fileVersion = FileVersionInfo.GetVersionInfo (location) .FileVersion;". Führen Sie Ihr Programm von einem "speziellen" Ort aus? –

Antwort

0

Ich bin überhaupt nicht davon überzeugt, dass es sogar im entferntesten vernünftig ist zu erwarten, dass der PowerShell-Code ohne die Installation von WMF funktioniert. Wenn ich mit dieser Anfrage angesprochen würde, würde ich antworten, dass der gesamte Code in einer anderen .NET-Sprache (dh C#) neu erstellt werden muss.

Noch können Sie vielleicht sehen, ob es diese statische Methode ist. Sie müssen PowerShell den Code fürchten, fürchte ich. Der PowerShell-Beschleuniger ist nur eine einfache Möglichkeit für mich, die Assembly System.Management.Automation aufzurufen.Die Klasse ist nicht öffentlich und die Methode in der Klasse ist auch nicht öffentlich.

$ verInfo = [PowerShell] .Assembly.GetTypes() | Name des Zielobjekts -eq 'PSVersionInfo' $ verInfo.GetMethod ('get_PSVersion', [System.Reflection.BindingFlags] 'Nicht öffentlich, statisch'). Invoke ($ null, [System.Reflection.BindingFlags] 'Nicht öffentlich, statisch' , $ null, @(), $ null)

Chris

Verwandte Themen