PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Wie dir Kommando in C# absetzen?


Elemental
2005-06-14, 16:58:22
Gibt es eine elegante Methode ein dir Kommando in C# abzusetzen?

Ich versuche eine Liste der files im GAC zu kriegen und wollte das mit "dir" tun:


class Class1
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main(string[] args)
{
//
// TODO: Add code to start application here
//
StreamWriter sw = null;
sw = File.CreateText(@"d:\GACFiles.txt");

string strGACFolder = GetWindowsDirectory() + "\\assembly";

string strOutput=string.Empty;
CallCommand("cmd", "/c dir /S " + strGACFolder, ref strOutput);

int i=0;
}

[DllImport("kernel32.dll",SetLastError=true)]
private static extern uint GetWindowsDirectory(StringBuilder lpBuffer, uint usize);

/// <summary>
/// Gets the path to the windows directory
/// </summary>
/// <returns>path to windows directory</returns>
public static string GetWindowsDirectory()
{
const int MAX_PATH = 260;

StringBuilder buffer = new StringBuilder(MAX_PATH+1);

if(GetWindowsDirectory(buffer, MAX_PATH+1)>1)
{
return buffer.ToString();
}
else
{
throw new Exception("Windows-Error " + Marshal.GetLastWin32Error() + "while retrieving the windows directory");
}
}

static private void CallCommand(string program, string arguments, ref string output)
{
StreamReader srOut;
StreamReader srErr;
ProcessStartInfo psi = new ProcessStartInfo(program, arguments);
psi.UseShellExecute = false;
psi.RedirectStandardOutput = true;
psi.RedirectStandardError = true;
psi.CreateNoWindow = false;
try
{
Process p = Process.Start(psi);
srOut = p.StandardOutput;
srErr = p.StandardError;
if (p != null)
{
p.WaitForExit();
output = srOut.ReadToEnd() + "\n" + srErr.ReadToEnd();
}
}
catch (Exception ex)
{
throw;
}
}
}


Ich starte also cmd.exe mit "dir als Parameter. Allerdings beendet sich der Prozess nicht, obwohl ich als Parameter von cmd.exe auch /C angebe.

Ich weiss momentan echt nicht weiter...
Kann man das vielleicht ganz anders machen?

mfG
Elemental

ScottManDeath
2005-06-14, 17:57:45
using System;
using System.IO;
class Test
{
public static void Main()
{
try
{
string[] dirs = Directory.GetFiles(@"c:\", "*.*");
Console.WriteLine("The number of files starting with c is {0}.", dirs.Length);
foreach (string dir in dirs)
{
Console.WriteLine(dir);
}
}
catch (Exception e)
{
Console.WriteLine("The process failed: {0}", e.ToString());
}
}
}



Aus der Hilfe kopiert

Elemental
2005-06-14, 21:24:45
Tja, so hatte ich das zuerst auch probiert, aber wenn ich "DirectoryInfo.GetFiles()" auf "c:\windows\assembly" mache, dann bekomme ich immer nur "Desktop.ini" geliefert. (Obwohl die doch eigentlich garnicht im GAC ist :confused: ).

Deshalb kam ich ja überhaupt auf die Idee mit dem "dir" Kommando...


mfG
Elemental

Xmas
2005-06-14, 22:57:16
Und hast du mal in der Kommandozeile "dir C:\Windows\assembly" eingegeben? ;)

Schau dir doch erst mal die Verzeichnisstruktur des GAC an bevor du mit dir oder GetFiles (besser hier: GetDirectories ;)) herumprobierst.

Elemental
2005-06-15, 08:47:45
Ja, "dir /S c:\windows\assembly" liefert "schönen" Output ;)

Mit Directory.GetDirectories krieg ich immerhin 4 folder:
- "C:\WINDOWS\assembly\GAC"
- "C:\WINDOWS\assembly\NativeImages1_v1.1.4322"
- "C:\WINDOWS\assembly\temp"
- "C:\WINDOWS\assembly\tmp"


Muss ich mich da jetzt selber durch die Verzeichnisstruktur kämpfen? Also in jedem Verzeichnis überprüfen , ob es noch Unterverzeichnisse gibt und dann in jedem Verzeichnis GetFiles aufrufen?
Is ja garnicht umständlich...

Aber danke für den tip. Ich versuch das jetzt mal so.


mfG
Elemental

clm[k1]
2005-06-15, 09:19:29
Muss ich mich da jetzt selber durch die Verzeichnisstruktur kämpfen? Also in jedem Verzeichnis überprüfen , ob es noch Unterverzeichnisse gibt und dann in jedem Verzeichnis GetFiles aufrufen?
Is ja garnicht umständlich...


Kann man doch recht einfach durch Rekursion lösen....


just my 2 cent
clm[k1]

Elemental
2005-06-15, 10:11:54
']Kann man doch recht einfach durch Rekursion lösen....

just my 2 cent
clm[k1]


Ja, dacht ich auch erst:


[STAThread]
static void Main(string[] args)
{
string strGACFolder = GetWindowsDirectory() + "\\assembly";

string[] arrGAC = GetAllSubDirectories(strGACFolder);

int i=0;
}

public static string[] GetAllSubDirectories(string strDirectory)
{
string[] arrDirs = Directory.GetDirectories(strDirectory);

foreach(string strDir in arrDirs)
{
string[] arrSubdirs = GetAllSubDirectories(strDir);

int iArrayIndex = arrDirs.Length;

foreach(string strSubDir in arrSubdirs)
{
arrDirs[iArrayIndex] = strSubDir;
iArrayIndex ++;
}
}

return arrDirs;
}


Endet nur immer mit der System.IndexOutOfRangeException "Index was outside the bounds of the array".
Kann ein array nur 151 elemente aufnehmen?
Bei

arrDirs[152] = strSubDir;

krachts immer. Auch wenn ich die Arrays mit "new string[1000]" erzeuge.

Hab mir auch schon selber ne StringCollection Klasse gebaut und damit versucht. Dann kam immer "collection has been modified...".
Irgendwie steh ich grad aufm schlauch... :D


edit: Argh, Anfängerfehler. "Collection was modified; enumeration operation may not execute" sagt eigentlich alles. Man sollte die collection, über die man gerade im foreach loop geht, nicht verändern :D

Elemental
2005-06-15, 10:51:21
Kaum zu glauben, dass ich dafür den ganzen Vormittag gebraucht hab ;D


public static ArrayList GetAllSubDirectories(string strDirectory)
{
ArrayList arrResults = new ArrayList();

ArrayList arrDirs = new ArrayList();
arrDirs.AddRange(Directory.GetDirectories(strDirectory));
arrResults.AddRange(arrDirs);

foreach(string strDir in arrDirs)
{
arrResults.AddRange(GetAllSubDirectories(strDir));
}

return arrResults;
}