确定已安装的TrueCrypt卷的驱动器号

将TrueCrypt容器安装到驱动器盘符后,是否可以在批处理文件中确定从哪个容器安装驱动器号,或者将容器安装到哪个驱动器盘符?

在批处理文件中,我想将指定的TrueCrypt容器挂载到指定的驱动器号。 如果容器已经安装或者驱动器号不可用,则TrueCrypt错误,所以我只想在指定的容器尚未安装到指定的驱动器号时才运行TrueCrypt,也就是说,仅当操作没有时才运行TrueCrypt已经完成了。

任何建议,将不胜感激。

编辑

赏金总结简而言之,您可以将卷C:\Vol1.tcC:\Vol2.tc安装到驱动器XY 你怎么能把C:\Vol1.tc安装到驱动器XC:\Vol2.tc以使用批处理文件或C#代码来驱动Y programaticaly?

一种方法是直接向Truecrypt司机询问。 这可以通过DeviceIoControlfunction实现。 实际上,这正是TrueCrypt GUI正在做的事情。

请注意,在c ++中更容易实现。 你会在这里找到一篇好文章 。

我们的想法是调用DeviceIoControl函数,询问TC_IOCTL_GET_MOUNTED_VOLUMES您将获得一个结构,其中包含所有已安装的卷路径和驱动器号。 事实上,它是一个26元素arrays(每个可能的驱动器号一个),称为wszVolume,它包含安装在其上的truecrypt卷的路径。

希望以下示例可以帮助您找到如何处理您的情况。

C#中的示例代码:

 class Program { static void Main(string[] args) { uint size = (uint)Marshal.SizeOf(typeof(MOUNT_LIST_STRUCT)); IntPtr buffer = Marshal.AllocHGlobal((int)size); uint bytesReturned; IntPtr _hdev = CreateFile("\\\\.\\TrueCrypt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); bool bResult = DeviceIoControl(_hdev, TC_IOCTL_GET_MOUNTED_VOLUMES, buffer, size, buffer, size, out bytesReturned, IntPtr.Zero); MOUNT_LIST_STRUCT mount = new MOUNT_LIST_STRUCT(); Marshal.PtrToStructure(buffer, mount); Marshal.FreeHGlobal(buffer); for (int i = 0; i < 26; i++) Console.WriteLine("{0}: => {1}", (char)('A' + i), mount.wszVolume[i]); } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] class MOUNT_LIST_STRUCT { public readonly UInt32 ulMountedDrives; /* Bitfield of all mounted drive letters */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly MOUNT_LIST_STRUCT_VOLUME_NAME[] wszVolume; /* Volume names of mounted volumes */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly UInt64[] diskLength; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly int[] ea; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly int[] volumeType; /* Volume type (eg PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */ } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct MOUNT_LIST_STRUCT_VOLUME_NAME { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 260)] public readonly char[] wszVolume; /* Volume names of mounted volumes */ public override string ToString() { return (new String(wszVolume)).TrimEnd('\0'); } } public static int CTL_CODE(int DeviceType, int Function, int Method, int Access) { return (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)); } private static readonly uint TC_IOCTL_GET_MOUNTED_VOLUMES = (uint)CTL_CODE(0x00000022, 0x800 + (6), 0, 0); [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile( [MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] FileAccess access, [MarshalAs(UnmanagedType.U4)] FileShare share, IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes, IntPtr templateFile); } 

这是我到目前为止:

我正在创建一个用c#编写的自定义应用程序,通知用户安装/卸载了哪些卷,如果已挂载,我需要告知用户驱动器。 为了知道卷是否已安装,我有以下类:

注意我使用handle.exe可以http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx或http://download.sysinternals.com/files/Handle 下载该程序 。压缩

另外我相信你必须以管理员身份运行该程序

 class TrueCryptHelp { // I have that program on the working directory // it can be downloaded from http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx const string HandleExeLocation = "handle.exe"; static string systemProcessFiles; static DateTime dateFilesLockedInfo = new DateTime(); static string SystemProcessFiles { get { if ((DateTime.Now - dateFilesLockedInfo).TotalSeconds > 2) { Process p = new Process(); var psi = new ProcessStartInfo(); psi.RedirectStandardOutput = true; psi.UseShellExecute = false; psi.FileName = HandleExeLocation; p.StartInfo = psi; p.Start(); var output = p.StandardOutput.ReadToEnd(); systemProcessFiles = string.Empty; foreach (Match m in Regex.Matches(output ?? "", @"(?sx) -{20} [^-] .+? -{20}")) { if (Regex.Match(m.Value ?? "", @"(?xi) -{10} [\s\r\n]+ System \s pid").Success) { if (Regex.Match(m.Value ?? "", @"(?xi) \) \s+ \\clfs \s* (\r|\n)").Success) { systemProcessFiles = m.Value.ToLower(); break; } } } } dateFilesLockedInfo = DateTime.Now; return systemProcessFiles; } } public static bool IsVolumeMounted(string volumeLocation) { //DriveInfo d = new System.IO.DriveInfo(volume.DriveLetter); //if (d == null) //return false; //if (d.DriveType != System.IO.DriveType.Fixed) //return false; //if ((d.DriveFormat ?? "").ToLower().Contains("fat") == false) //return false; if (SystemProcessFiles.Contains(volumeLocation.ToLower())) { return true; } else { return false; } } } 

然后,如果我想知道是否已安装位于C:\Users\Tono\Desktop\v1.tc ,我将调用该方法:

 var isVolMounted = TrueCryptHelp.IsVolumeMounted(@"A:\Users\Tono\Desktop\v1.tc"); 

现在我很想回答这个问题! 在我发布的课程中,我能够知道位于C:\ Users \ etc …的卷已经安装但是进入了什么驱动器号!?

只是为了扩展VeraCrypt的答案,修改自Gerard Walace的post:

MSFT_Helpers.cs中的TrueCrypt和VeraCrypt用法@ https://github.com/BananaAcid/Selfcontained-C-Sharp-WPF-compatible-utility-classes

这里简单的用法示例: http : //github.com/BananaAcid/VeraCrypt-Cmd

 public static class VcGetMounts { public static async Task> getMounted() { return await Task.Run>(() => { var ret = new Dictionary(); uint size = (uint)Marshal.SizeOf(typeof(MOUNT_LIST_STRUCT)); IntPtr buffer = Marshal.AllocHGlobal((int)size); uint bytesReturned; IntPtr _hdev = CreateFile("\\\\.\\VeraCrypt", FileAccess.ReadWrite, FileShare.ReadWrite, IntPtr.Zero, FileMode.Open, 0, IntPtr.Zero); bool bResult = DeviceIoControl(_hdev, TC_IOCTL_GET_MOUNTED_VOLUMES, buffer, size, buffer, size, out bytesReturned, IntPtr.Zero); // IMPORTANT! Otherwise, the struct fills up with random bytes from memory, if no VeraCrypt is available if (!bResult) return ret; MOUNT_LIST_STRUCT mount = new MOUNT_LIST_STRUCT(); Marshal.PtrToStructure(buffer, mount); Marshal.FreeHGlobal(buffer); for (int i = 0; i < 26; i++) if (mount.wszVolume[i].ToString().Length > 0) ret.Add((char)('A' + i), mount.wszVolume[i].ToString()); return ret; }); } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] class MOUNT_LIST_STRUCT { public readonly UInt32 ulMountedDrives; /* Bitfield of all mounted drive letters */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly MOUNT_LIST_STRUCT_VOLUME_NAME[] wszVolume; /* Volume names of mounted volumes */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly MOUNT_LIST_STRUCT_VOLUME_LABEL[] wszLabel; /* Volume labels of mounted volumes */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly MOUNT_LIST_STRUCT_VOLUME_ID[] volumeID; /* Volume labels of mounted volumes */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly UInt64[] diskLength; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly int[] ea; [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly int[] volumeType; /* Volume type (eg PROP_VOL_TYPE_OUTER, PROP_VOL_TYPE_OUTER_VOL_WRITE_PREVENTED, etc.) */ [MarshalAs(UnmanagedType.ByValArray, SizeConst = 26)] public readonly bool[] truecryptMode; } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct MOUNT_LIST_STRUCT_VOLUME_NAME { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 260)] public readonly char[] wszVolume; /* Volume names of mounted volumes */ public override string ToString() { return (new String(wszVolume)).TrimEnd('\0'); } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct MOUNT_LIST_STRUCT_VOLUME_ID { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 32)] public readonly char[] volumeID; /* Volume ids of mounted volumes */ public override string ToString() { return (new String(volumeID)).TrimEnd('\0'); } } [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Ansi, Pack = 1)] struct MOUNT_LIST_STRUCT_VOLUME_LABEL { [MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I2, SizeConst = 33)] public readonly char[] wszLabel; /* Volume labels of mounted volumes */ public override string ToString() { return (new String(wszLabel)).TrimEnd('\0'); } } public static int CTL_CODE(int DeviceType, int Function, int Method, int Access) { return (((DeviceType) << 16) | ((Access) << 14) | ((Function) << 2) | (Method)); } private static readonly uint TC_IOCTL_GET_MOUNTED_VOLUMES = (uint)CTL_CODE(0x00000022, 0x800 + (6), 0, 0); [DllImport("kernel32.dll", ExactSpelling = true, SetLastError = true, CharSet = CharSet.Auto)] static extern bool DeviceIoControl(IntPtr hDevice, uint dwIoControlCode, IntPtr lpInBuffer, uint nInBufferSize, IntPtr lpOutBuffer, uint nOutBufferSize, out uint lpBytesReturned, IntPtr lpOverlapped); [DllImport("kernel32.dll", CharSet = CharSet.Auto, SetLastError = true)] public static extern IntPtr CreateFile( [MarshalAs(UnmanagedType.LPTStr)] string filename, [MarshalAs(UnmanagedType.U4)] FileAccess access, [MarshalAs(UnmanagedType.U4)] FileShare share, IntPtr securityAttributes, // optional SECURITY_ATTRIBUTES struct or IntPtr.Zero [MarshalAs(UnmanagedType.U4)] FileMode creationDisposition, [MarshalAs(UnmanagedType.U4)] FileAttributes flagsAndAttributes, IntPtr templateFile); } 

我不确定通过查询驱动器号来确定卷名,反之亦然。 根据您的需要可以接受的解决方法是查询卷上的文件锁定。 如果音量被锁定,安装的可能性很大。 如果你愿意,你可以得到更多的幻想,并使用for / f检查它是否被系统进程专门锁定。

我应该提到,如果驱动器已经挂载,那么在调用truecrypt.exe时使用/ quit background和/ silent将会无声地失败。 不确定是否只是你关心的错误显示 。 不确定您是否注意到命令行参考 。

这是一个简单的cmd脚本,只有在尚未安装卷时才能安装卷,从而防止错误由truecrypt.exe触发。 它做了许多天真的假设,但应该给出一个想法。

 @echo off setlocal enableextensions enabledelayedexpansion :: Dependencies: Truecrypt obviously, and sysinternals handles.exe (live.sysinternals.com). :: To use command line arguments instead of static assignments like these, reference %1 %2 from within script.. set driveletter=x set yourvolume=c:\temp\your_volume.vol set yourpassword=your_password set truecrypt_loc=c:\program files\truecrypt\truecrypt.exe set handle_loc=c:\temp\handle.exe :: - check if volume already mounted "%handle_loc%" -a "%yourvolume%" /accepteula >nul if %errorlevel% EQU 0 echo This volume is already mounted. && goto :EOF :: - check if drive letter is in use if exist %driveletter% echo This drive is already mounted. && goto :EOF :: - mount tc volume to a specified drive letter :: silent flag suppresses errors being displayed to user "%truecrypt_loc%" /letter %driveletter% /password "%yourpassword%" /volume "%yourvolume%" /mountoption rm /quit background /silent :: - check if drive letter is in use if exist %driveletter%:\ echo Drive was mounted successfully as %driveletter%: && goto :EOF echo Drive could not be mounted. 

请注意,由于某些版本的TrueCrypt可能存在错误,因此从GUI中卸载会导致驱动器号在将来的安装中不可用。 一种解决方法是使用以下命令从命令行卸载:truecrypt.exe / q / dx(其中x是驱动器号)。

我可能过于简单了,但安装的驱动器上的驱动器标签是否独一无二? 如果是这样,您可以使用简单的查找,例如:

 private string GetDriveLetter(string volumeLabel) { string driveLetter = ""; DriveInfo[] dis = DriveInfo.GetDrives(); foreach (DriveInfo di in dis) { var dt = di.DriveType; if (dt == DriveType.Fixed || dt == DriveType.Removable) { if (di.VolumeLabel == volumeLabel) { driveLetter = di.Name.Substring(0, 1).ToUpper(); break; } } } return driveLetter; } 

只是为了确保我有这个权利:你想确保TrueCrypt通过脚本将某个卷安装到某个驱动器盘符,并且如果已经安装了卷,它将不会尝试执行任何操作。

也许有几种可能的解 我将尝试突出以下几个选项; 让我知道是否值得进一步追求,我将继续研究和更新更多细节。

选项1:collections夹和自动安装

TrueCrypt支持“最喜欢的卷” 。

从页面 – 在以下情况下使用collections卷:

  • 您有一个总是需要安装到特定驱动器号的卷。
  • 当主机设备连接到计算机时(例如,位于USB闪存驱动器或外部USB硬盘驱动器上的容器),您需要自动安装卷。
  • 登录操作系统时,您有一个需要自动挂载的卷。
  • 您的卷总是需要作为只读或可移动介质安装。

有些事情值得注意:

  • 一个特殊的标签可以应用于每个喜欢的卷 – 可以很方便
  • 您可以运行"TrueCrypt.exe /a favorites /quit"来自动安装您喜欢的卷,然后退出。 您可能需要对此进行测试,因为truecryptcollections页面指出If it is already mounted, an Explorer window is opened for it.

选项2:仅检查驱动器号

如果您始终将卷装入某个驱动器号,您可以合理地假设其他任何内容都不会出现在该驱动器号上。

如果这是一个合理的假设,您可以随时使用PowerShell检查驱动器:

 $DriveLetterToCheck = "s:" $DriveLetterMounted = Test-Path $DriveLetterToCheck #true if it exists if(!$DriveLetterMounted) { # Run your TrueCrypt mount command } 

如果我想到更好的东西,我会更新。 如果我走在正确的轨道上,请告诉我。