gpt4 book ai didi

c# - 使用 OpenVirtualDisk() 返回错误代码 2 "File not Found"Windows 10

转载 作者:太空宇宙 更新时间:2023-11-03 12:14:43 25 4
gpt4 key购买 nike

大家晚上好。我希望社区能够帮助解决我的 C# 编程小问题。我在这里要说的是,我对 C# 编程还很陌生,从 Borland Pascal 开始学习曲线非常陡峭!

我目前正在尝试使用虚拟磁盘 API(如 MSDN 网站上的 here 所述),转换为 c#(希望保持在托管上下文中)。

我已经设法让 OpenVirtualDisk() 接受第一个参数,但它在第二个参数上失败(我想打开和附加的所述 ISO 的文件路径。)从大量研究中我声明了参数“路径”作为字符串,以允许 CLR 最适合函数签名。

该应用程序目前正在提升权限下运行(通过 Visual Studio 2017)

以下是我的dllImport:

        [DllImport("VirtDisk.dll", EntryPoint = "OpenVirtualDisk", CharSet = CharSet.Ansi, ThrowOnUnmappableChar = true ,SetLastError = true)]
public extern static Int64 OpenVirtualDisk(
[In] ref _VIRTUAL_STORAGE_TYPE PVIRTUAL_STORAGE_TYPE,
string Path,
_VIRTUAL_DISK_ACCESS_MASK LVIRTUAL_DISK_ACCESS_MASK,
long OPEN_VIRTUAL_DISK_FLAG,
[In, Optional] ref OPEN_VIRTUAL_DISK_PARAMTERS POPEN_VIRTUAL_DISK_PARAMTERS,
ref IntPtr pHandle);

所有其他常量、枚举和结构都按照 VirtDisk.h 的规定声明,如果需要可以提供。

这是我用来调用 OpenVirtualDisk 的所有代码(如您所见,我正在使用 File.Exists() 来确保文件在开始任何工作之前存在):

        private void button1_Click(object sender, EventArgs e)
{
IntPtr pHandle = IntPtr.Zero;
Int64 RetVal = 0;
string VirtualDiskPath = @"F:\Images\Windows10.ISO";
_VIRTUAL_DISK_ACCESS_MASK VIRTUAL_DISK_ACCESS;
Int64 VIRTUAL_DISK_FLAG;
_VIRTUAL_STORAGE_TYPE VIRTUAL_STORAGE_TYPE;

if (File.Exists(VirtualDiskPath))
{

VIRTUAL_DISK_ACCESS = _VIRTUAL_DISK_ACCESS_MASK.VIRTUAL_DISK_ACCESS_ATTACH_ALL;
VIRTUAL_DISK_FLAG = OPEN_VIRTUAL_DISK_FLAG_NONE;

VIRTUAL_STORAGE_TYPE.DeviceId = VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
VIRTUAL_STORAGE_TYPE.VendorId = VENDORMICROSOFT;

IntPtr VirtualStorPtr = IntPtr.Zero;
VirtualStorPtr = Marshal.AllocHGlobal(Marshal.SizeOf(VIRTUAL_STORAGE_TYPE));
Marshal.StructureToPtr(VIRTUAL_STORAGE_TYPE, VirtualStorPtr, true);

IntPtr VirtualDiskVer = IntPtr.Zero;
OPEN_VIRTUAL_DISK_PARAMTERS OPEN_VIRTUAL_DISK_PARAM;
OPEN_VIRTUAL_DISK_PARAM = new OPEN_VIRTUAL_DISK_PARAMTERS
{
version = OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1,
version1 = new OPEN_VIRTUAL_DISK_PARAMTERS1
{
RWDepth = 0
}
};

VirtualDiskVer = Marshal.AllocHGlobal(Marshal.SizeOf(OPEN_VIRTUAL_DISK_PARAM));
Marshal.StructureToPtr(OPEN_VIRTUAL_DISK_PARAM, VirtualDiskVer, true);

RetVal = OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE,
VirtualDiskPath,
VIRTUAL_DISK_ACCESS,
VIRTUAL_DISK_FLAG,
ref OPEN_VIRTUAL_DISK_PARAM,
ref pHandle);
if ((RetVal == 0))
{
MessageBox.Show("OpenVirtualDisk() has succeded in opening the file: \r\n" +
VirtualDiskPath + "\r\nWith the file Handle: " + pHandle.ToString());
}
else
{
MessageBox.Show("OpenVirtualDisk() failed to open the file: " +
VirtualDiskPath + ",\r\nWith Error Code: " + Marshal.GetLastWin32Error().ToString() +
"\r\nReturn Value: " + RetVal.ToString());
}
Marshal.FreeHGlobal(VirtualStorPtr);

}
}

到目前为止,每次尝试的 RetVal 为 87“无效参数”,GetLastWin32Error 报告 1008“无效 token ”,或者 RetVal 为 2“找不到文件”,GetLastWin32Error 报告相同。

谁能发现我哪里出错了?

提前致谢。

里奇

注意,这是我一直在基于 Windows Imaging API (Wimgapi.h) 用 c# 构建的恢复套件的一部分。如果需要,这是为了允许安装 Windows(任何版本,只要它是 64 位)。它将在 WinPE(Windows 10,.Net 版本 5.4.2)上运行,我什至尝试使用 FileIOPermssion 允许该进程完全访问文件。

故障已经解决,如下评论。 FILE_ACCESS_MASK 需要更改为 FILE_ACCESS_MASK_RO,但 DLLimport 声明也需要进行调整。 DLLImport 现在显示为:

[DllImport("virtdisk.dll"CharSet = CharSet.UNICODE, ThrowOnUnmappableChar = true ,SetLastError = true)] 公共(public)外部静态 Int64 OpenVirtualDisk( [在] ref _VIRTUAL_STORAGE_TYPE PVIRTUAL_STORAGE_TYPE, 字符串路径, [在]_VIRTUAL_DISK_ACCESS_MASK LVIRTUAL_DISK_ACCESS_MASK, [输入] 长 OPEN_VIRTUAL_DISK_FLAG, [在,可选] ref OPEN_VIRTUAL_DISK_PARAMTERS POPEN_VIRTUAL_DISK_PARAMTERS, [在] ref IntPtr pHandle);

最佳答案

我以前打开过虚拟 ISO,我会为您发布我的代码:

public static class NativeMethods
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "Warning is bogus.")]
[DllImport("virtdisk.dll", CharSet = CharSet.Unicode)]
public static extern Int32 OpenVirtualDisk(ref VIRTUAL_STORAGE_TYPE VirtualStorageType,
string Path,
VIRTUAL_DISK_ACCESS_MASK VirtualDiskAccessMask,
OPEN_VIRTUAL_DISK_FLAG Flags,
ref OPEN_VIRTUAL_DISK_PARAMETERS Parameters,
ref VirtualDiskSafeHandle Handle);

public static readonly Guid VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT = new Guid("EC984AEC-A0F9-47e9-901F-71415A66345B");
public const int OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT = 1;

public const Int32 ERROR_SUCCESS = 0;
public const Int32 ERROR_FILE_CORRUPT = 1392;
public const Int32 ERROR_FILE_NOT_FOUND = 2;
public const Int32 ERROR_PATH_NOT_FOUND = 3;
public const Int32 ERROR_ACCESS_DENIED = 5;

/// CD or DVD image file device type. (.iso file)
/// </summary>
public const int VIRTUAL_STORAGE_TYPE_DEVICE_ISO = 1;

/// <summary>
/// Device type is unknown or not valid.
/// </summary>
public const int VIRTUAL_STORAGE_TYPE_DEVICE_UNKNOWN = 0;

/// <summary>
/// Virtual hard disk device type. (.vhd file)
/// </summary>
public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHD = 2;

/// <summary>
/// VHDX format virtual hard disk device type. (.vhdx file)
/// </summary>
public const int VIRTUAL_STORAGE_TYPE_DEVICE_VHDX = 3;

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct VIRTUAL_STORAGE_TYPE
{
/// <summary>
/// Device type identifier.
/// </summary>
public Int32 DeviceId; //ULONG

/// <summary>
/// Vendor-unique identifier.
/// </summary>
public Guid VendorId; //GUID
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OPEN_VIRTUAL_DISK_PARAMETERS
{
/// <summary>
/// An OPEN_VIRTUAL_DISK_VERSION enumeration that specifies the version of the OPEN_VIRTUAL_DISK_PARAMETERS structure being passed to or from the VHD functions.
/// </summary>
public OPEN_VIRTUAL_DISK_VERSION Version; //OPEN_VIRTUAL_DISK_VERSION

/// <summary>
/// A structure.
/// </summary>
public OPEN_VIRTUAL_DISK_PARAMETERS_Version1 Version1;
}

public enum OPEN_VIRTUAL_DISK_VERSION : int
{
/// <summary>
/// </summary>
OPEN_VIRTUAL_DISK_VERSION_UNSPECIFIED = 0,

/// <summary>
/// </summary>
OPEN_VIRTUAL_DISK_VERSION_1 = 1
}

[Flags]
public enum VirtualDiskAccessMask : int
{
/// <summary>
/// Open the virtual disk for read-only attach access. The caller must have READ access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail.
/// </summary>
AttachReadOnly = 0x00010000,
/// <summary>
/// Open the virtual disk for read-write attaching access. The caller must have (READ | WRITE) access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail. If the virtual disk is part of a differencing chain, the disk for this request cannot be less than the RWDepth specified during the prior open request for that differencing chain.
/// </summary>
AttachReadWrite = 0x00020000,
/// <summary>
/// Open the virtual disk to allow detaching of an attached virtual disk. The caller must have (FILE_READ_ATTRIBUTES | FILE_READ_DATA) access to the virtual disk image file.
/// </summary>
Detach = 0x00040000,
/// <summary>
/// Information retrieval access to the VHD. The caller must have READ access to the virtual disk image file.
/// </summary>
GetInfo = 0x00080000,
/// <summary>
/// VHD creation access.
/// </summary>
Create = 0x00100000,
/// <summary>
/// Open the VHD to perform offline meta-operations. The caller must have (READ | WRITE) access to the virtual disk image file, up to RWDepth if working with a differencing chain. If the VHD is part of a differencing chain, the backing store (host volume) is opened in RW exclusive mode up to RWDepth.
/// </summary>
MetaOperations = 0x00200000,
/// <summary>
/// Allows unrestricted access to the VHD. The caller must have unrestricted access rights to the virtual disk image file.
/// </summary>
All = 0x003f0000,
}

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
public struct OPEN_VIRTUAL_DISK_PARAMETERS_Version1
{
/// <summary>
/// Indicates the number of stores, beginning with the child, of the backing store chain to open as read/write. The remaining stores in the differencing chain will be opened read-only. This is necessary for merge operations to succeed.
/// </summary>
public Int32 RWDepth; //ULONG
}

public enum OPEN_VIRTUAL_DISK_FLAG : int
{
/// <summary>
/// No flag specified.
/// </summary>
OPEN_VIRTUAL_DISK_FLAG_NONE = 0x00000000,

/// <summary>
/// Open the backing store without opening any differencing-chain parents. Used to correct broken parent links.
/// </summary>
OPEN_VIRTUAL_DISK_FLAG_NO_PARENTS = 0x00000001,

/// <summary>
/// Reserved.
/// </summary>
OPEN_VIRTUAL_DISK_FLAG_BLANK_FILE = 0x00000002,

/// <summary>
/// Reserved.
/// </summary>
OPEN_VIRTUAL_DISK_FLAG_BOOT_DRIVE = 0x00000004
}

public enum VIRTUAL_DISK_ACCESS_MASK : int
{
/// <summary>
/// Open the virtual disk for read-only attach access. The caller must have READ access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail.
/// </summary>
VIRTUAL_DISK_ACCESS_ATTACH_RO = 0x00010000,

/// <summary>
/// Open the virtual disk for read-write attaching access. The caller must have (READ | WRITE) access to the virtual disk image file. If used in a request to open a virtual disk that is already open, the other handles must be limited to either VIRTUAL_DISK_ACCESS_DETACH or VIRTUAL_DISK_ACCESS_GET_INFO access, otherwise the open request with this flag will fail. If the virtual disk is part of a differencing chain, the disk for this request cannot be less than the RWDepth specified during the prior open request for that differencing chain.
/// </summary>
VIRTUAL_DISK_ACCESS_ATTACH_RW = 0x00020000,

/// <summary>
/// Open the virtual disk to allow detaching of an attached virtual disk. The caller must have (FILE_READ_ATTRIBUTES | FILE_READ_DATA) access to the virtual disk image file.
/// </summary>
VIRTUAL_DISK_ACCESS_DETACH = 0x00040000,

/// <summary>
/// Information retrieval access to the VHD. The caller must have READ access to the virtual disk image file.
/// </summary>
VIRTUAL_DISK_ACCESS_GET_INFO = 0x00080000,

/// <summary>
/// VHD creation access.
/// </summary>
VIRTUAL_DISK_ACCESS_CREATE = 0x00100000,

/// <summary>
/// Open the VHD to perform offline meta-operations. The caller must have (READ | WRITE) access to the virtual disk image file, up to RWDepth if working with a differencing chain. If the VHD is part of a differencing chain, the backing store (host volume) is opened in RW exclusive mode up to RWDepth.
/// </summary>
VIRTUAL_DISK_ACCESS_METAOPS = 0x00200000,

/// <summary>
/// Reserved.
/// </summary>
VIRTUAL_DISK_ACCESS_READ = 0x000d0000,

/// <summary>
/// Allows unrestricted access to the VHD. The caller must have unrestricted access rights to the virtual disk image file.
/// </summary>
VIRTUAL_DISK_ACCESS_ALL = 0x003f0000,

/// <summary>
/// Reserved.
/// </summary>
VIRTUAL_DISK_ACCESS_WRITABLE = 0x00320000
}

}

[SecurityPermission(SecurityAction.Demand)]
public class VirtualDiskSafeHandle : SafeHandle
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Security", "CA5122:PInvokesShouldNotBeSafeCriticalFxCopRule", Justification = "Warning is bogus.")]
[DllImportAttribute("kernel32.dll", SetLastError = true)]
[return: MarshalAsAttribute(UnmanagedType.Bool)]
public static extern Boolean CloseHandle(IntPtr hObject);

public VirtualDiskSafeHandle()
: base(IntPtr.Zero, true)
{
}

public override bool IsInvalid
{
get { return (this.IsClosed) || (base.handle == IntPtr.Zero); }
}

public override string ToString()
{
return this.handle.ToString();
}

protected override bool ReleaseHandle()
{
return CloseHandle(handle);
}

public IntPtr Handle
{
get { return handle; }
}
}

要使用它,创建一个像这样的方法:

private VirtualDiskSafeHandle OpenIso(string fileName, NativeMethods.VirtualDiskAccessMask fileAccessMask)
{
var parameters = new NativeMethods.OPEN_VIRTUAL_DISK_PARAMETERS();
parameters.Version = NativeMethods.OPEN_VIRTUAL_DISK_VERSION.OPEN_VIRTUAL_DISK_VERSION_1;
parameters.Version1.RWDepth = NativeMethods.OPEN_VIRTUAL_DISK_RW_DEPTH_DEFAULT;

var storageType = new NativeMethods.VIRTUAL_STORAGE_TYPE();
storageType.DeviceId = NativeMethods.VIRTUAL_STORAGE_TYPE_DEVICE_ISO;
storageType.VendorId = NativeMethods.VIRTUAL_STORAGE_TYPE_VENDOR_MICROSOFT;

fileAccessMask = ((fileAccessMask & NativeMethods.VirtualDiskAccessMask.GetInfo) == NativeMethods.VirtualDiskAccessMask.GetInfo) ? NativeMethods.VirtualDiskAccessMask.GetInfo : 0;
fileAccessMask |= NativeMethods.VirtualDiskAccessMask.AttachReadOnly;

VirtualDiskSafeHandle handle = new VirtualDiskSafeHandle();

int res = NativeMethods.OpenVirtualDisk(ref storageType, fileName,
(NativeMethods.VIRTUAL_DISK_ACCESS_MASK) fileAccessMask,
NativeMethods.OPEN_VIRTUAL_DISK_FLAG.OPEN_VIRTUAL_DISK_FLAG_NONE, ref parameters, ref handle);

if (res == NativeMethods.ERROR_SUCCESS)
{
return handle;
}
else
{
handle.SetHandleAsInvalid();
if ((res == NativeMethods.ERROR_FILE_NOT_FOUND) || (res == NativeMethods.ERROR_PATH_NOT_FOUND))
{
throw new FileNotFoundException("File not found.");
}
else if (res == NativeMethods.ERROR_ACCESS_DENIED)
{
throw new IOException("Access is denied.");
}
else if (res == NativeMethods.ERROR_FILE_CORRUPT)
{
throw new InvalidDataException("File type not recognized.");
}
else
{
throw new Win32Exception(res);
}
}
}

然后在整个程序中,您可以简单地执行以下操作:

VirtualDiskSafeHandle handle = OpenIso(@"c:\IsoLocation\Isoname.iso", NativeMethods.VirtualDiskAccessMask.All);
MessageBox.Show($"Handle = {handle.Handle}");

希望这对您有所帮助!

关于c# - 使用 OpenVirtualDisk() 返回错误代码 2 "File not Found"Windows 10,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50376333/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com