我遇到Restart Manager API的一個奇怪問題:RmGetlist()。 爲了模擬一個文件鎖定的情況下,我想提出使用下列第三方文件鎖定工具:當使用Ez文件鎖定器鎖定文件但使用另一個文件鎖定實用程序時,RmGetList()API失敗
的Ez文件櫃 - http://www.xoslab.com/efl.html -
文件櫃 http://www.jensscheffler.de/filelocker
奇怪這裏的問題是, ,這兩個實用程序都會鎖定某個文件,但是,RMGetList()會因第一個文件鎖定實用程序(Ez文件鎖定)導致Access拒絕錯誤(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");``
}
}
}
優秀分析!爲了糾正語法並提高可讀性,我重寫了這些內容,並在頂部添加了一個技術性較低的摘要,以便對Windows內部不太熟悉的讀者獲益。我希望這會得到您的批准。如果您同意該摘要是準確的,並且在重寫時沒有犯任何錯誤,我們可以刪除該免責聲明。或者當然你可能希望恢復整個編輯;將不會採取任何冒犯行爲。 :-) –
@哈里約翰斯頓 - 非常感謝你。你真的都明白正確和準確的編輯答案 - 使其更具可讀性。不幸的是,英語是我的弱點 – RbMm