首页 文章

强制USB拇指驱动器在继续之前安装

提问于
浏览
1

我正在使用Windows 7上的Visual Studio 2008在C#中编写更新程序 . 我希望用户插入USB拇指驱动器,如果程序在驱动器上找到驱动器和更新,则它会自动复制它们 . 我希望在启动时只检查一次,然后执行一个不知道更新的程序(更新确实需要在程序关闭时发生) .

我的问题是在安装拇指驱动器之前正在运行更新程序,因此计算机检测到没有拇指驱动器且没有更新并且过早地移动 . 我希望尽可能快地运行所有内容,但我需要在检测之前强制安装任何拇指驱动器 . 一切都必须是自动的,没有来自用户的输入 .

这可能在c#中吗?

编辑更详细:

我目前在启动时运行批处理文件(实际上作为Windows 7 shell,但我不确定这会有所不同) . 批处理文件运行更新检查然后执行实际程序 . 如果用户在启动时卡住了USB驱动器,那么我希望更新程序能够查看驱动器并复制任何新文件 .

目前的编码如下:

DriveInfo[] ListDrives = DriveInfo.GetDrives();
 foreach (DriveInfo Drive in ListDrives)
 {
      if(Drive.DriveType == DriveType.Removable)
      {
           // double check it's valid and copy over stuff
      }
 }

但它目前在启动时找不到驱动器 . 如果我以后运行它然后一切都很好 . 我假设因为我这么早就运行更新程序它没有机会装载,但我不想等待N秒,如果我没有,因为在正常情况下这只是死时间 .

如果我可以做到这一点,那么从容易起来就比不断监视某个事件然后关闭所有内容并进行更新要简单得多 .

3 回答

  • 1

    我会建议一个类似下面的解决方案:

    using System;
    using System.Collections.Generic;
    using System.Diagnostics;
    using System.IO;
    using System.Threading;
    
    /// <summary>
    /// Represents our program class which contains the entry point of our application.
    /// </summary>
    public class Program
    {
        /// <summary>
        /// Represents the entry point of our application.
        /// </summary>
        /// <param name="args">Possibly spcified command line arguments.</param>
        public static void Main(string[] args)
        {
            RemovableDriveWatcher rdw = new RemovableDriveWatcher();   // Create a new instance of the RemoveableDriveWatcher class.
            rdw.NewDriveFound += NewDriveFound;                        // Connect to the "NewDriveFound" event.
            rdw.DriveRemoved += DriveRemoved;                          // Connect to the "DriveRemoved" event.
            rdw.Start();                                               // Start watching.
    
            // Do something here...
            Console.ReadLine();
    
            rdw.Stop();                                                // Stop watching.
        }
    
        /// <summary>
        /// Is executed when a new drive has been found.
        /// </summary>
        /// <param name="sender">The sender of this event.</param>
        /// <param name="e">The event arguments containing the changed drive.</param>
        private static void NewDriveFound(object sender, RemovableDriveWatcherEventArgs e)
        {
            Console.WriteLine(string.Format("Found a new drive, the name is: {0}", e.ChangedDrive.Name));
        }
    
        /// <summary>
        /// Is executed when a drive has been removed.
        /// </summary>
        /// <param name="sender">The sender of this event.</param>
        /// <param name="e">The event arguments containing the changed drive.</param>
        private static void DriveRemoved(object sender, RemovableDriveWatcherEventArgs e)
        {
            Console.WriteLine(string.Format("The drive with the name {0} has been removed.", e.ChangedDrive.Name));
        }
    }
    

    RemoveableDriveWatcher类如下所示:

    /// <summary>
    /// Repesents a watcher class for removable drives.
    /// </summary>
    public class RemovableDriveWatcher
    {
        /// <summary>
        /// Represents the watcher thread which watches for new drives.
        /// </summary>
        private Thread watcherThread;
    
        /// <summary>
        /// Continas all found logical drives of this system.
        /// </summary>
        private List<DriveInfo> foundDrives;
    
        /// <summary>
        /// Initializes a new instance of the <see cref="RemovableDriveWatcher"/> class.
        /// </summary>
        public RemovableDriveWatcher()
        {
            this.foundDrives = new List<DriveInfo>();
            this.watcherThread = new Thread(new ThreadStart(ScanLogicalDrives));
            this.WaitBetweenScansDelay = 1000;
        }
    
        /// <summary>
        /// Is fired if a new drive has been detected.
        /// </summary>
        public event EventHandler<RemovableDriveWatcherEventArgs> NewDriveFound;
    
        /// <summary>
        /// Is fired if a drive has been removed.
        /// </summary>
        public event EventHandler<RemovableDriveWatcherEventArgs> DriveRemoved;
    
        /// <summary>
        /// Gets or sets the delay in ms between two scans.
        /// </summary>
        public int WaitBetweenScansDelay
        {
            get;
            set;
        }
    
        /// <summary>
        /// Starts the watcher.
        /// </summary>
        public void Start()
        {
            if (!this.watcherThread.IsAlive)
            {
                this.watcherThread.Start();
            }
        }
    
        /// <summary>
        /// Stops the watcher.
        /// </summary>
        public void Stop()
        {
            if (this.watcherThread.IsAlive)
            {
                this.watcherThread.Abort();
                this.watcherThread.Join();
            }
        }
    
        /// <summary>
        /// Scans for logical drives and fires an event every time a new
        /// drive has been found or a drive was removed.
        /// </summary>
        private void ScanLogicalDrives()
        {
            DriveInfo[] drives;
    
            do
            {
                drives = DriveInfo.GetDrives();
    
                // Check for new drives
                foreach (DriveInfo drive in drives)
                {
                    if (!(drive.DriveType == DriveType.Removable))
                    {
                        continue;
                    }
    
                    if (!drive.IsReady)
                    {
                        continue;
                    }
    
                    if (!this.foundDrives.ContainsWithName(drive))
                    {
                        this.foundDrives.Add(drive);
    
                        if (this.NewDriveFound != null)
                        {
                            this.NewDriveFound(this, new RemovableDriveWatcherEventArgs(drives, drive));
                        }
                    }
                }
    
                // Check for removed drives
                for (int i = this.foundDrives.Count - 1; i >= 0; i--)
                {
                    DriveInfo drive = this.foundDrives[i];
                    if (!drives.ContainsWithName(drive))
                    {
                        if (this.DriveRemoved != null)
                        {
                            this.DriveRemoved(this, new RemovableDriveWatcherEventArgs(drives, drive));
                        }
    
                        this.foundDrives.RemoveWithName(drive);
                    }
                }
    
                // Sleep
                Thread.Sleep(this.WaitBetweenScansDelay);
            }
            while (true);
        }
    }
    

    要使一切顺利,您需要使用RemovableDriveWatcherEventArgs:

    /// <summary>
    /// Represents the RemovableDriveWatcherEventArgs
    /// </summary>
    public class RemovableDriveWatcherEventArgs : EventArgs
    {
        /// <summary>
        /// Initializes a new instance of the <see cref="RemovableDriveWatcherEventArgs"/> class.
        /// </summary>
        /// <param name="allDrives">All currently available logical drives in the system.</param>
        /// <param name="changedDrive">The changed drive.</param>
        public RemovableDriveWatcherEventArgs(DriveInfo[] allDrives, DriveInfo changedDrive)
        {
            this.Drives = allDrives;
            this.ChangedDrive = changedDrive;
        }
    
        /// <summary>
        /// Gets the changed logical drive that has either been detected or removed.
        /// </summary>
        public DriveInfo ChangedDrive { get; private set; }
    
        /// <summary>
        /// Gets all currently available logical drives.
        /// </summary>
        public DriveInfo[] Drives { get; private set; }
    }
    

    当然还有扩展:

    /// <summary>
    /// Contains extensions used by the RemovableDriveWatcher class.
    /// </summary>
    public static class RemovableDriveWatcherExtensions
    {
        /// <summary>
        /// Extends the DiveInfo[] by the ContainsWithName method.
        /// </summary>
        /// <param name="all">The array where we want to find the specified instance.</param>
        /// <param name="search">The instance which we want to find in the array.</param>
        /// <returns>TRUE if the specified instance was found, FALSE if the specified instance was not found.</returns>
        public static bool ContainsWithName(this DriveInfo[] all, DriveInfo search)
        {
            for (int i = 0; i < all.Length; i++)
            {
                if (all[i].Name == search.Name)
                {
                    return true;
                }
            }
    
            return false;
        }
    
        /// <summary>
        /// Extends the List<DriveInfo> by the ContainsWithName method.
        /// </summary>
        /// <param name="all">The array where we want to find the specified instance.</param>
        /// <param name="search">The instance which we want to find in the list.</param>
        /// <returns>TRUE if the specified instance was found, FALSE if the specified instance was not found.</returns>
        public static bool ContainsWithName(this List<DriveInfo> all, DriveInfo search)
        {
            for (int i = 0; i < all.Count; i++)
            {
                if (all[i].Name == search.Name)
                {
                    return true;
                }
            }
    
            return false;
        }
    
        /// <summary>
        /// Extends the List<DriveInfo> by the RemoveWithName method.
        /// </summary>
        /// <param name="all">The array where we want to removed the specified instance.</param>
        /// <param name="search">The instance which we want to remove in the list.</param>
        public static void RemoveWithName(this List<DriveInfo> all, DriveInfo search)
        {
            for (int i = 0; i < all.Count; i++)
            {
                if (all[i].Name == search.Name)
                {
                    all.RemoveAt(i);
                    return;
                }
            }
        }
    }
    

    我希望这有点帮助 .

  • 2

    你没有提供太多细节,但似乎你可以调用DriveInfo.GetDrives(),它返回一个DriveInfo []类型的数组

    DriveInfo有一个IsReady()方法 . 大概一旦你检查驱动器准备就绪,你可以在USB驱动器()上寻找一个众所周知的文件来验证他们是否安装了正确的USB

    您可以循环轮询直到找到所需内容,但如果您在60秒内找不到所需内容,则需要通知用户您找不到所需的USB驱动器 .

  • 1

    我没有在if语句中看到一个现成的检查 . 根据MSDN:

    IsReady指示驱动器是否准备就绪 . 例如,它指示CD是否在CD驱动器中,或者可移动存储设备是否已准备好进行读/写操作 . 如果您未测试驱动器是否准备就绪,并且尚未就绪,则使用DriveInfo查询驱动器将引发IOException .

    你在检查IOException吗?我没有看到IsReady事件,因此您可能必须通过spinwait或挂钩到较低级别的Windows API来查找指示驱动器就绪的事件 . 这是同时的想法:

    try
    {
        DriveInfo[] ListDrives = DriveInfo.GetDrives();
         foreach (DriveInfo Drive in ListDrives)
         {
              if(!Drive.IsReady)//spin
    
              if(Drive.DriveType == DriveType.Removable)
              {
                   // double check it's valid and copy over stuff
              }
         }
    }
    catch(IOException ex)//...
    

    我现在没办法测试这个 . 请告诉我它是如何工作的,或者我需要了解更多细节 .

    但是,因为你在启动时开始这个过程,所以总是有可能 IsReady 不够,再一次你可能需要找到别的东西(我想象的是Windows API) . 我还没有发现任何说明效果的文档 .

相关问题