- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我在使用 Restart Manager API 时遇到了一个奇怪的问题:RmGetlist()。
为了模拟文件锁定场景,我正在使用以下第 3 方文件锁定实用程序:
Ez 文件柜
- http://www.xoslab.com/efl.html -
文件柜
http://www.jensscheffler.de/filelocker
这里奇怪的问题是,这两个实用程序都锁定了某个文件,但是,RMGetList() 使用第一个文件锁定实用程序(Ez File lock)失败并出现访问被拒绝错误(5),而它与第二个文件锁定实用程序一起使用。
这里可能有什么问题? 为什么 RmGetList() 会在一个文件锁定实用程序上失败,但在另一个文件锁定实用程序上工作?
以下是正在使用的代码:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Security;
using System.IO;
using System.Windows.Forms;
namespace RMSession
{
class Program
{
public static void GetProcessesUsingFiles(string[] filePaths)
{
uint sessionHandle;
int error = NativeMethods.RmStartSession(out sessionHandle, 0, Guid.NewGuid().ToString("N"));
if (error == 0)
{
try
{
error = NativeMethods.RmRegisterResources(sessionHandle, (uint)filePaths.Length, filePaths, 0, null, 0, null);
if (error == 0)
{
RM_PROCESS_INFO[] processInfo = null;
uint pnProcInfoNeeded = 0, pnProcInfo = 0, lpdwRebootReasons = RmRebootReasonNone;
error = NativeMethods.RmGetList(sessionHandle, out pnProcInfoNeeded, ref pnProcInfo, null, ref lpdwRebootReasons);
while (error == ERROR_MORE_DATA)
{
processInfo = new RM_PROCESS_INFO[pnProcInfoNeeded];
pnProcInfo = (uint)processInfo.Length;
error = NativeMethods.RmGetList(sessionHandle, out pnProcInfoNeeded, ref pnProcInfo, processInfo, ref lpdwRebootReasons);
}
if (error == 0 && processInfo != null)
{
for (var i = 0; i < pnProcInfo; i++)
{
RM_PROCESS_INFO procInfo = processInfo[i];
Process proc = null;
try
{
proc = Process.GetProcessById(procInfo.Process.dwProcessId);
}
catch (ArgumentException)
{
// Eat exceptions for processes which are no longer running.
}
if (proc != null)
{
//yield return proc;
}
}
}
}
}
finally
{
NativeMethods.RmEndSession(sessionHandle);
}
}
}
private const int RmRebootReasonNone = 0;
private const int CCH_RM_MAX_APP_NAME = 255;
private const int CCH_RM_MAX_SVC_NAME = 63;
private const int ERROR_MORE_DATA = 234;
[StructLayout(LayoutKind.Sequential)]
private struct RM_UNIQUE_PROCESS
{
public int dwProcessId;
public System.Runtime.InteropServices.ComTypes.FILETIME ProcessStartTime;
}
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
private struct RM_PROCESS_INFO
{
public RM_UNIQUE_PROCESS Process;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_APP_NAME + 1)]
public string strAppName;
[MarshalAs(UnmanagedType.ByValTStr, SizeConst = CCH_RM_MAX_SVC_NAME + 1)]
public string strServiceShortName;
public RM_APP_TYPE ApplicationType;
public uint AppStatus;
public uint TSSessionId;
[MarshalAs(UnmanagedType.Bool)]
public bool bRestartable;
}
private enum RM_APP_TYPE
{
RmUnknownApp = 0,
RmMainWindow = 1,
RmOtherWindow = 2,
RmService = 3,
RmExplorer = 4,
RmConsole = 5,
RmCritical = 1000
}
[SuppressUnmanagedCodeSecurity]
private static class NativeMethods
{
/// <summary>
/// Starts a new Restart Manager session.
/// </summary>
/// <param name="pSessionHandle">A pointer to the handle of a Restart Manager session. The session handle can be passed in subsequent calls to the Restart Manager API.</param>
/// <param name="dwSessionFlags">Reserved must be 0.</param>
/// <param name="strSessionKey">A null-terminated string that contains the session key to the new session. A GUID will work nicely.</param>
/// <returns>Error code. 0 is successful.</returns>
[DllImport("RSTRTMGR.DLL", CharSet = CharSet.Unicode, PreserveSig = true, SetLastError = true, ExactSpelling = true)]
public static extern int RmStartSession(out uint pSessionHandle, int dwSessionFlags, string strSessionKey);
/// <summary>
/// Ends the Restart Manager session.
/// </summary>
/// <param name="pSessionHandle">A handle to an existing Restart Manager session.</param>
/// <returns>Error code. 0 is successful.</returns>
[DllImport("RSTRTMGR.DLL")]
public static extern int RmEndSession(uint pSessionHandle);
/// <summary>
/// Registers resources to a Restart Manager session.
/// </summary>
/// <param name="pSessionHandle">A handle to an existing Restart Manager session.</param>
/// <param name="nFiles">The number of files being registered.</param>
/// <param name="rgsFilenames">An array of strings of full filename paths.</param>
/// <param name="nApplications">The number of processes being registered.</param>
/// <param name="rgApplications">An array of RM_UNIQUE_PROCESS structures. </param>
/// <param name="nServices">The number of services to be registered.</param>
/// <param name="rgsServiceNames">An array of null-terminated strings of service short names.</param>
/// <returns>Error code. 0 is successful.</returns>
[DllImport("RSTRTMGR.DLL", CharSet = CharSet.Unicode)]
public static extern int RmRegisterResources(uint pSessionHandle, uint nFiles, string[] rgsFilenames, uint nApplications, [In] RM_UNIQUE_PROCESS[] rgApplications, uint nServices, string[] rgsServiceNames);
/// <summary>
/// Gets a list of all applications and services that are currently using resources that have been registered with the Restart Manager session.
/// </summary>
/// <param name="dwSessionHandle">A handle to an existing Restart Manager session.</param>
/// <param name="pnProcInfoNeeded">A pointer to an array size necessary to receive RM_PROCESS_INFO structures</param>
/// <param name="pnProcInfo">A pointer to the total number of RM_PROCESS_INFO structures in an array and number of structures filled.</param>
/// <param name="rgAffectedApps">An array of RM_PROCESS_INFO structures that list the applications and services using resources that have been registered with the session.</param>
/// <param name="lpdwRebootReasons">Pointer to location that receives a value of the RM_REBOOT_REASON enumeration that describes the reason a system restart is needed.</param>
/// <returns>Error code. 0 is successful.</returns>
[DllImport("RSTRTMGR.DLL")]
public static extern int RmGetList(uint dwSessionHandle, out uint pnProcInfoNeeded, ref uint pnProcInfo, [In, Out] RM_PROCESS_INFO[] rgAffectedApps, ref uint lpdwRebootReasons);
}
static void Main(string[] args)
{
Console.WriteLine("Starting...");
string[] file1 = new string[1];
MessageBox.Show("Debug C#");
file1[0] = @"C:\ProcessMonitor.zip";
//DirectoryInfo dirInfo = new DirectoryInfo(folder);
GetProcessesUsingFiles(file1);
Console.WriteLine("End");``
}
}
}
最佳答案
Easy File Locker 只是在这个词的非正式意义上“锁定”文件,即它保护文件不被访问,但它不是通过获得文件锁定来做到这一点。相反,它使用了一种低级技术(文件系统过滤器驱动程序),该技术与防病毒软件保护其文件免受任何未经授权的访问的方式大体相似。 Restart Manager API 不打算也不会处理这种情况。
您的应用程序几乎肯定也不需要处理这种情况。这意味着 Easy File Locker 不是满足您特定需求的合适工具;把它扔掉。
Why would RmGetList() fail with one file locking utility but work with another?
RmGetList
在内部工作。在您的情况下,我们为它提供一个文件名,它的输出是
RM_PROCESS_INFO
的数组结构。为了构建这个数组,Windows 必须确定哪些进程正在使用该文件。但是 Windows 是如何做到这一点的呢?
ZwQueryInformationFile
(由
ntdll.dll
导出)可以返回很多关于文件的信息。
FILE_INFORMATION_CLASS
中的选项之一枚举是
FileProcessIdsUsingFileInformation
A FILE_PROCESS_IDS_USING_FILE_INFORMATION structure. This value is reserved for system use. This value is available starting with Windows Vista.
wdm.h
(这是 Windows WDK 中众所周知的文件)我们发现
typedef struct _FILE_PROCESS_IDS_USING_FILE_INFORMATION {
ULONG NumberOfProcessIdsInList;
ULONG_PTR ProcessIdList[1];
} FILE_PROCESS_IDS_USING_FILE_INFORMATION, *PFILE_PROCESS_IDS_USING_FILE_INFORMATION;
FILE_READ_ATTRIBUTES
打开文件访问(对于这个信息类来说已经足够了)ZwQueryInformationFile(..,FileProcessIdsUsingFileInformation);
如果 NumberOfProcessIdsInList
!= 0 走ProcessIdList
ProcessId
打开进程, 查询 ProcessStartTime
(看GetProcessTimes
) 和其他要填写的属性RM_PROCESS_INFO
CreateFile
与
dwShareMode = 0
.这会在文件上获得排他锁,确保任何使用
dwDesiredAccess
打开文件的尝试
FILE_READ_DATA
或
FILE_WRITE_DATA
或
DELETE
将失败并显示
ERROR_SHARING_VIOLATION
.但是,它不会阻止我们使用
dwDesiredAccess = FILE_READ_ATTRIBUTES
打开文件。 ,因此对 RmGetList() 的调用仍然可以正常工作。
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\xlkfs
) 来限制对文件的访问。此驱动程序返回
STATUS_ACCESS_DENIED
(转换为 Win32
ERROR_ACCESS_DENIED
)用于打开文件的任何尝试。因此,您会收到错误
ERROR_ACCESS_DENIED
当
RmGetList
尝试在步骤 (1) 中打开文件,并且(因为 API 不知道如何处理)此错误代码会返回给您。
关于winapi - 当使用 Ez 文件锁定器锁定文件但与另一个文件锁定实用程序一起使用时,RmGetList() API 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41348500/
是否可以禁用 ez-vcard 设置 PROPID? 我使用 ez-vcard 检查我的应用程序的一些强制参数。我有一个包含多个电子名片的输入文件,我想将它们每个存储在我的数据库中。这是我的 Java
安装 eZPublish 6 后出现问题。当我尝试使用用户名 admin 和默认密码 (publish) 连接 localhost:8000/app.php/ez 时,出现此错误: 日志 [2016-
我在使用 Restart Manager API 时遇到了一个奇怪的问题:RmGetlist()。 为了模拟文件锁定场景,我正在使用以下第 3 方文件锁定实用程序: Ez 文件柜 - http://w
我正在使用 [EZ-VCards 库][1] 在 Java Web 应用程序中生成一些 VCard 数据。 除了编码问题之外,它工作正常并且使用起来非常简单。这些值是使用 UTF-8 编写的(我使用十
我正在尝试使用 Android ez vcard library从我的对象创建 vcf 文件。我的问题是我不知道如何实例化 VCard 的 List,如下所示: List vcards = null
我正在使用 ezvcard 库从我自己的应用程序中导出联系人数据。我的问题是,无法在我的股票联系人应用程序中读取导出的 vcard。这是输出: BEGIN:VCARD VERSION:4.0 N:;U
嗨我想知道我是否可以在 ez publish 模板中使用 PHP 函数。如果有人知道如何使用它。任何提示都会很棒。 例如:- 我想在 ez-publish 模板中使用 str_replace() PH
这是一个非常特殊的问题,我不确定 stackoverflow 是否是提出这个问题的合适平台,但我还是尝试了...... 我目前正在编写 JSR-80 的实现(javax.usb) 并且刚刚发现有可用的
我正在使用 ez-vcard ( https://github.com/mangstadt/ez-vcard ) 来解析 VCARD 字符串。例如 VCARD 字符串之一是 "BEGIN:VCARD\
我正在尝试弄清楚如何在 GBA 大小的 EZ Flash 3 合 1 卡中对 PSRAM 进行编程。基本上重复 GBA Exploader 和其他程序所做的事情。 如果我选择一个 block 并对其进
我尝试使用由 AnalogDevices 实现的 BF537 EZ-KIT 进行数字图像处理 - 2D DCT/IDCT(图像压缩)实验。 提及“简历”: 我构建项目; 使用图像查看器将黑白图像 (*
我是一名优秀的程序员,十分优秀!