C#从本地目录打开程序

时间:2015-03-04 13:02:18

标签: c#

我对C#几乎没有经验,但我非常愿意学习。我正在尝试使用启动可执行文件的按钮创建应用程序。该应用程序从USB闪存驱动器运行。让我们说闪存驱动器在我的电脑上有driveletter(e :)。我想从bin目录运行一个名为rkill.exe的程序。

private void opschonen_RKill_Click(object sender, EventArgs e)
    {
        var process_RKill = new Process
        {
            StartInfo = new ProcessStartInfo
            {
                FileName = "/bin/rkill.exe"
            }
        };
        process_RKill.Start();
        process_RKill.WaitForExit();
    }

然而,这不起作用。如果我从根启动应用程序,它确实有效。我不能指向一个驱动器,因为不是每台计算机都将驱动器分配给E:

我做错了什么?我认为这很简单,因为我只是一个初学者。

4 个答案:

答案 0 :(得分:5)

const string relativePath = "bin/rkill.exe";

//Check for idle, removable drives
var drives = DriveInfo.GetDrives()
                      .Where(drive => drive.IsReady
                             && drive.DriveType == DriveType.Removable);

foreach (var drive in drives)
{
    //Get the full filename for the application
    var rootDir = drive.RootDirectory.FullName;
    var fileName = Path.Combine(rootDir, relativePath);

    //If it does not exist, skip this drive
    if (!File.Exists(fileName)) continue;

    //Execute the application and wait for it to exit
    var process = new Process
    {
        StartInfo = new ProcessStartInfo
        {
            FileName = fileName
        }
    };

    process.Start();
    process.WaitForExit();
}

答案 1 :(得分:0)

编辑 Emile Pels的解决方案似乎更加优化。假设它有效,我建议通过我快速而肮脏的修复来选择它:)

鉴于它可以从root(如你所说)工作,问题是你当前正在使用相对路径。 它仅在相对路径实际解析时起作用,即当您的应用程序位于根目录中时。

要让它在其他位置工作,您需要使用绝对路径。这意味着您将需要一个驱动器号(除非使用环境变量,这似乎超出了范围)。

我可以想到一些解决方法来找到正确的驱动器。

您的应用程序是否遍历每个可能的驱动器号。 不要只是尝试为每个驱动器运行.exe 。在尝试运行它之前,请检查该文件是否存在。如果是这样,你可以非常确定你正在寻找正确的驱动器。

using System.IO;

public static string LookForDrive(string filepath) //filepath = "\\bin\\myApp.exe")
{
    List<string> possibleLetters = new List<string>() { "A", "B", "C" }; //and so on...

    foreach(string driveLetter in possibleLetters)
    {
        var testPath = String.Format("{0}:\\{1}", driveLetter, filepath);

        if( File.Exists( testPath ) )
        {
            return testPath,
        }
    }

    //If you get here, no drive letter was valid.

    throw new Exception("Could not find the specified file on any possible drive.");
}

以上只是我扔在一起的一个快速的东西。它可能会进一步优化,但我希望目的很明确。

答案 2 :(得分:0)

您可以查看可移动驱动器的地址。然后使用地址构建完整路径。请注意,在运行进程之前,可以使用多个可移动驱动器,以检查驱动器上是否存在exe:

        var myExe = "/bin/rkill.exe";
        // Find removable drives
        var driveDirectories = 
            DriveInfo.GetDrives()
            .Where(d => d.DriveType == DriveType.Removable)
            .Select(d => d.RootDirectory.FullName);

        foreach (var directory in driveDirectories)
        {
            // create full path
            var fullPath = Path.Combine(directory, myExe);

            // check if path exists
            if (File.Exists(fullPath))
            {
                // execute
                var process_RKill = new Process
                {
                    StartInfo = new ProcessStartInfo
                    {
                        FileName = fullPath;
                    }
                };
                process_RKill.Start();
                process_RKill.WaitForExit();
                // don't try other drives after successful execution
                return;
            }
        }

答案 3 :(得分:0)

当您从驱动器本身运行应用程序时,您可以使用方法返回驱动器号:

private static string GetCurrentDriveLetter()
{
    return Path.GetPathRoot(Environment.CurrentDirectory); // Alternatively, if you believe the working directory may be different
    // return Path.GetPathRoot(Assembly.GetExecutingAssembly().Location);
}

然后应用你当前的逻辑,虽然重写为使用()以确保它被处置:

using (Process p = new Process())
            {
                string executable = Path.Combine(GetCurrentDriveLetter(), "/bin/rkill.exe"); // This is preferable to simple string concatenation because it helps prevent some possible issues that may arise otherwise
                p.StartInfo = new ProcessStartInfo(executable);
                //p.StartInfo.UseShellExecute = false; // < Uncomment these two if you see a pop up CLI window
                //p.StartInfo.CreateNoWindow = true;   // <
                p.Start();
                p.WaitForExit();
            }