将TrueCrypt容器安装到驱动器盘符后,是否可以在批处理文件中确定装入驱动器号的容器,或者容器安装到哪个驱动器盘符?
在批处理文件中,我想将指定的TrueCrypt容器挂载到指定的驱动器号。如果容器已经安装或驱动器号不可用,则TrueCrypt错误,因此我只想在指定的容器尚未安装到指定的驱动器号时才运行TrueCrypt,也就是说,仅当操作没有时才运行TrueCrypt已经完成了。
任何建议都将不胜感激。
赏金摘要简而言之,您可以将卷C:\Vol1.tc
和C:\Vol2.tc
装入驱动器X
和Y
。您如何通过批处理文件或C#代码将C:\Vol1.tc
安装到驱动器X
和C:\Vol2.tc
来驱动Y
programaticaly?
答案 0 :(得分:9)
这样做的方法是直接向Truecrypt司机询问。 这可以通过DeviceIoControl功能实现。 实际上,这正是TrueCrypt GUI正在做的事情。
请注意,在c ++中更容易做到这一点。 You'll find a good article here
想法是调用DeviceIoControl
函数,询问TC_IOCTL_GET_MOUNTED_VOLUMES
您将获得一个结构,其中包含所有已安装的卷路径和驱动器号。
事实上,它是一个26元素阵列(每个可能的驱动器号一个),称为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 (e.g. 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);
}
答案 1 :(得分:1)
这是我到目前为止所做的:
我正在创建一个用c#编写的自定义应用程序,通知用户安装/卸载了哪些卷,如果已挂载,我需要通知用户驱动器。为了知道卷是否已安装,我有以下类:
注意我使用handle.exe
该程序可以在http://technet.microsoft.com/en-us/sysinternals/bb896655.aspx 下载,也可以从http://download.sysinternals.com/files/Handle.zip下载
我也相信你必须以管理员身份运行程序
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 ...的卷已挂载到驱动器号中了??
答案 2 :(得分:1)
只是为了扩展VeraCrypt的答案,修改自Gerard Walace的帖子:
在MSFT_Helpers.cs @ https://github.com/BananaAcid/Selfcontained-C-Sharp-WPF-compatible-utility-classes中使用TrueCrypt和VeraCrypt
此处的简单用法示例:http://github.com/BananaAcid/VeraCrypt-Cmd
public static class VcGetMounts
{
public static async Task<Dictionary<char, string>> getMounted()
{
return await Task.Run<Dictionary<char, string>>(() =>
{
var ret = new Dictionary<char, string>();
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 (e.g. 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);
}
答案 3 :(得分:0)
我不确定通过查询驱动器号来确定卷名,反之亦然。根据您的需要可以接受的解决方法是查询卷上的文件锁定。如果音量被锁定,安装的可能性很大。如果你愿意,你可以得到更多的幻想,并使用for / f检查它是否被系统进程专门锁定。
我应该提到,如果驱动器已经挂载,那么在调用truecrypt.exe时使用/ quit background和/ silent将会无声地失败。不确定是否只是你关注的错误 display 。不确定您是否注意到command line reference。
这是一个简单的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是驱动器号)。
答案 4 :(得分:0)
我可能过于简单了,但安装的驱动器上的驱动器标签是否独一无二?如果是这样,您可以使用简单的查找,例如:
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;
}
答案 5 :(得分:0)
只是为了确保我做到了这一点:您希望确保TrueCrypt通过脚本将某个卷安装到某个驱动器号,并且如果已经安装了卷,它将不会尝试执行任何操作。
也许有几种潜在的解决方案。我将尝试突出以下几个选项;让我知道是否值得进一步追求,我会继续研究和更新更多细节。
TrueCrypt支持"favorite volumes"。
从页面 - 在以下情况下使用收藏卷:
- 您的卷总是需要安装到特定的驱动器号。
- 当主机设备连接到计算机时(例如,容器),您需要自动挂载卷 位于USB闪存驱动器或外部USB硬盘驱动器上。
- 登录操作系统时,您需要自动挂载卷。
- 您的卷总是需要以只读或可移动媒体的形式安装。
值得注意的一些事情:
"TrueCrypt.exe /a favorites /quit"
自动安装您喜欢的卷,然后退出。您可能需要对此进行测试,因为truecrypt收藏页面会指出If it is already mounted, an Explorer window is opened for it.
如果您始终将音量装入某个驱动器号,您可以合理地假设其他任何内容都不会出现在该驱动器号上。
如果这是一个合理的假设,您可以随时使用PowerShell检查驱动器:
$DriveLetterToCheck = "s:"
$DriveLetterMounted = Test-Path $DriveLetterToCheck #true if it exists
if(!$DriveLetterMounted)
{
# Run your TrueCrypt mount command
}
如果我想到更好的东西,我会更新。如果我走在正确的轨道上,请告诉我。