我对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:
我做错了什么?我认为这很简单,因为我只是一个初学者。
答案 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();
}