用C关闭Windows Server 2012上的开放网络文件#
问题描述:
有什么办法强制关闭Server 2012上特定文件的任何实例?用C关闭Windows Server 2012上的开放网络文件#
为了讨论各种情形,调用链接到文件D:\Shares\Shared\Sharedfile.exe
我有C#代码拷贝最新版本的程序到这个目录,其中往往有在白天使用该程序的人。关闭打开的文件句柄并替换文件运行良好,因为这意味着下次用户打开程序时,它们会有所有最新的更改。
然而,它从服务器上的计算机管理中得到了一点单调,所以我想知道是否有办法从C#代码做到这一点?
我试过这个,但它没有我需要的正确的重载。也许在我可以使用的File
课程中有什么?
编辑的C#代码以关闭该文件将不主机服务器上运行。
[DllImport("Netapi32.dll", SetLastError=true, CharSet = CharSet.Unicode)]
public static extern int NetFileClose(string servername, int id);
答
您可以包装NetFileClose
API,这也需要包装的NetFileEnum
API。类似这样的:
[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
struct FILE_INFO_3 {
public int fi3_id;
public int fi3_permissions;
public int fi3_num_locks;
public string fi3_pathname;
public string fi3_username;
}
static class NativeMethods {
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public extern static int NetFileEnum(
string servername,
string basepath,
string username,
int level,
out IntPtr bufptr,
int prefmaxlen,
out int entriesread,
out int totalentries,
ref IntPtr resume_handle
);
[DllImport("netapi32.dll", CharSet = CharSet.Unicode)]
public extern static int NetFileClose(string servername, int fileid);
[DllImport("netapi32.dll")]
public extern static int NetApiBufferFree(IntPtr buffer);
}
漂亮难看的签名,对不对?让我们围绕它围绕一点点管理爱。
class RemoteFile {
public RemoteFile(string serverName, int id, string path, string userName) {
ServerName = serverName;
Id = id;
Path = path;
UserName = userName;
}
public string ServerName { get; }
public int Id { get; }
public string Path { get; }
public string UserName { get; }
public void Close() {
int result = NativeMethods.NetFileClose(ServerName, Id);
if (result != 0) {
// handle error decently, omitted for laziness
throw new Exception($"Error: {result}");
}
}
}
IEnumerable<RemoteFile> EnumRemoteFiles(string serverName, string basePath = null) {
int entriesRead;
int totalEntries;
IntPtr resumeHandle = IntPtr.Zero;
IntPtr fileEntriesPtr = IntPtr.Zero;
try {
int result = NativeMethods.NetFileEnum(
servername: serverName,
basepath: basePath,
username: null,
level: 3,
bufptr: out fileEntriesPtr,
prefmaxlen: -1,
entriesread: out entriesRead,
totalentries: out totalEntries,
resume_handle: ref resumeHandle
);
if (result != 0) {
// handle error decently, omitted for laziness
throw new Exception($"Error: {result}");
}
for (int i = 0; i != entriesRead; ++i) {
FILE_INFO_3 fileInfo = (FILE_INFO_3) Marshal.PtrToStructure(
fileEntriesPtr + i * Marshal.SizeOf(typeof(FILE_INFO_3)),
typeof(FILE_INFO_3)
);
yield return new RemoteFile(
serverName,
fileInfo.fi3_id,
fileInfo.fi3_pathname,
fileInfo.fi3_username
);
}
} finally {
if (fileEntriesPtr != IntPtr.Zero) {
NativeMethods.NetApiBufferFree(fileEntriesPtr);
}
}
}
现在关闭一个特定的文件很简单:关闭所有打开的实例。
foreach (var file in EnumRemoteFiles(server, path)) {
Console.WriteLine($"Closing {file.Path} at {file.ServerName} (opened by {file.UserName})");
file.Close();
}
请注意,这段代码并没有完全准备好生产,特别是错误处理很糟糕。另外,在我的测试中,看起来文件路径可能会受到一些破坏,具体取决于它们是如何打开的(例如文件显示为C:\\Path\File
,在驱动器根目录后面有一个额外的反斜杠),因此您可能需要先进行标准化验证名称。不过,这覆盖了地面。
[此问题](http://*.com/q/10945105/15498)从另一个方向着眼于问题 - 寻找避免在应用程序运行时锁定文件的方法 - 也许这可能是一种替代方法进场? –