【问题标题】:C# Opening a program from a local directoryC# 从本地目录打开程序
【发布时间】:2015-05-05 11:40:25
【问题描述】:

我在 C# 方面几乎没有经验,但我非常愿意学习。我正在尝试使用启动可执行文件的按钮创建一个应用程序。该应用程序从 USB 闪存驱动器运行。假设闪存驱动器在我的计算机上有驱动器号 (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:

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

【问题讨论】:

  • 提及exe的完整路径可能会解决问题。
  • 谢谢,但我没有完整路径,因为我无法提供驱动器号。
  • bin/ 文件夹是否在驱动器的根目录中?
  • 使用System.Reflection.Assembly.GetExecutingAssembly().LocationSystem.IO.Path.GetDirectoryName

标签: c#


【解决方案1】:
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();
}

【讨论】:

    【解决方案2】:

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

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

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

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

    您的应用程序是否对每个可能的驱动器号进行了迭代。 不要只是尝试为每个驱动器运行 .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.");
    }
    

    以上只是我快速整理的内容。它可能可以进一步优化,但我希望意图明确。

    【讨论】:

      【解决方案3】:

      您可以查看可移动驱动器的地址。然后使用地址构造完整路径。请注意,可能有多个可移动驱动器,因此在运行进程之前检查驱动器上是否存在您的 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;
                  }
              }
      

      【讨论】:

        【解决方案4】:

        由于您将从驱动器本身运行应用程序,因此您可以让一个方法返回驱动器号:

        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() 重新编写以确保它已被处理:

        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();
                    }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2012-01-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-03
          • 1970-01-01
          相关资源
          最近更新 更多