Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/282.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 使用C强制关闭Windows Server 2012上打开的网络文件#_C#_File_Windows Server 2012 R2 - Fatal编程技术网

C# 使用C强制关闭Windows Server 2012上打开的网络文件#

C# 使用C强制关闭Windows Server 2012上打开的网络文件#,c#,file,windows-server-2012-r2,C#,File,Windows Server 2012 R2,有没有办法强制关闭Server 2012上特定文件的任何实例 出于参数考虑,请调用文件D:\Shares\Shared\Sharedfile.exe的链接 我有一个C#代码,它将程序的最新版本复制到这个目录中,这个目录经常有人在白天使用这个程序。关闭打开的文件句柄并替换文件效果很好,因为这只意味着用户下次打开程序时,他们拥有所有最新的更改 然而,从服务器上的计算机管理来做这件事有点单调,所以我想知道是否有一种方法可以从C代码来做这件事 我试过了,但是它没有我需要的正确的重载。在文件类中是否有我可

有没有办法强制关闭Server 2012上特定文件的任何实例

出于参数考虑,请调用文件
D:\Shares\Shared\Sharedfile.exe的链接

我有一个C#代码,它将程序的最新版本复制到这个目录中,这个目录经常有人在白天使用这个程序。关闭打开的文件句柄并替换文件效果很好,因为这只意味着用户下次打开程序时,他们拥有所有最新的更改

然而,从服务器上的计算机管理来做这件事有点单调,所以我想知道是否有一种方法可以从C代码来做这件事

我试过了,但是它没有我需要的正确的重载。在
文件
类中是否有我可以使用的东西

编辑用于关闭文件的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);
        }
    }
}

请注意,这段代码还没有完全准备好生产,特别是错误处理非常糟糕。此外,在我的测试中,文件路径可能会受到一些损坏,具体取决于它们的打开方式(例如文件显示为
C:\\Path\file
,在驱动器根目录后有一个额外的反斜杠),因此您可能需要在验证名称之前进行规范化。尽管如此,这还是涵盖了问题所在。

从其他方向查找问题,以避免在应用程序运行时锁定文件-也许这可能是一种替代方法?很好,这就是我所寻找的。它还可以很好地用于模拟,因此非常有用(我使用了Minimod.Impersonator)
foreach (var file in EnumRemoteFiles(server, path)) {
    Console.WriteLine($"Closing {file.Path} at {file.ServerName} (opened by {file.UserName})");
    file.Close();
}