以编程方式获取锁定excel工作簿的用户

 青春快乐的勇哥 发布于 2022-12-19 16:03

我正在使用C#framework 4.5,netoffice 1.6和sharpdevelop 4.4.1来操作位于网络共享中的excel工作簿,从Outlook中.

在某些时候,我需要更改工作簿对象(ewb)的文件访问权限,以便像这样读写:

ewb.ChangeFileAccess(Excel.Enums.XlFileAccess.xlReadWrite, System.Reflection.Missing.Value, true);

在更改文件访问权限之前,我检查文件是否在服务器上被锁定.如果文件被锁定,我将通知用户稍后重试该操作.

现在,我想在通知中包含锁定excel文件的用户名.我搜索了msdn,netoffice论坛等等,但还没有找到解决方案.我知道,如果你打开excel文件readwrite,它会将用户的名字存储在xlsx文件中.如何通过c#访问该特定信息?

编辑:我最终这样做:

public string GetExcelFileOwner(string path, NetOffice.ExcelApi.Enums.XlFileFormat ffmt) {
        string tempmark = "~$";
        if(ffmt==NetOffice.ExcelApi.Enums.XlFileFormat.xlExcel8) {
            tempmark = "";
        }
        string uspath = Path.Combine(Path.GetDirectoryName(path), tempmark + Path.GetFileName(path));
        if (!File.Exists(uspath)) return "";
        var sharing = FileShare.ReadWrite | FileShare.Delete;
        using (var fs = new FileStream(uspath, FileMode.Open, FileAccess.Read, sharing))
        using (var br = new BinaryReader(fs, Encoding.Default)) {
            if(ffmt==NetOffice.ExcelApi.Enums.XlFileFormat.xlExcel8) {
                byte[] ByteBuffer = new byte[500];
                br.BaseStream.Seek(150, SeekOrigin.Begin);
                br.Read(ByteBuffer, 0, 500);
                return matchRegex(System.Text.Encoding.UTF8.GetString(ByteBuffer), @"(?=\w\w\w)([\w, ]+)").Trim();
            }
            else {
                return br.ReadString();
            }
        }
    }

    private static string matchRegex(string txt, string rgx) {
        Regex r;
        Match m;
        try {
            r = new Regex(rgx, RegexOptions.IgnoreCase);
            m = r.Match(txt);
            if (m.Success) {
                return m.Groups[1].Value.ToString();
            }
            else {
                return "";
            }
        }
        catch {
            return "";
        }
    }

我们使用excel 2003和excel 2007+文件格式(.xls和.xlsx).对于.xls,我必须查看.xls文件本身.对于.xlsx,锁定用户存储在〜$ temp文件中.我知道,对于.xls文件,它是脏代码,但我不知道.xls文件格式是如何构造的.因此,我只读了一堆字节,其中包含ascii用户名并执行正则表达式来提取该用户名.

1 个回答
  • 它会将用户名存储在xlsx文件中

    不,不是.xlsx文件.Excel创建另一个文件来存储用户名.它打开了隐藏文件属性,因此您通常无法使用资源管理器查看它.

    它通常与原始文件具有相同的名称,但前缀为~$.因此,对于一个名为的文件,test.xlsx您将获得一个名为的文件~$test.xlsx.它是一个二进制文件,包含在默认代码页和utf-16中编码的用户名.十六进制转储以显示它的外观:

    0000000000: 0C 48 61 6E 73 20 50 61 ? 73 73 61 6E 74 20 20 20  ?Hans Passant
    0000000010: 20 20 20 20 20 20 20 20 ? 20 20 20 20 20 20 20 20
    0000000020: 20 20 20 20 20 20 20 20 ? 20 20 20 20 20 20 20 20
    0000000030: 20 20 20 20 20 20 20 0C ? 00 48 00 61 00 6E 00 73         ? H a n s
    0000000040: 00 20 00 50 00 61 00 73 ? 00 73 00 61 00 6E 00 74     P a s s a n t
    0000000050: 00 20 00 20 00 20 00 20 ? 00 20 00 20 00 20 00 20
    0000000060: 00 20 00 20 00 20 00 20 ? 00 20 00 20 00 20 00 20
    0000000070: 00 20 00 20 00 20 00 20 ? 00 20 00 20 00 20 00 20
    0000000080: 00 20 00 20 00 20 00 20 ? 00 20 00 20 00 20 00 20
    0000000090: 00 20 00 20 00 20 00 20 ? 00 20 00 20 00 20 00 20
    00000000A0: 00 20 00 20 00          ?
    

    文件中的奇数0x0C字是字符串长度(不是字节),后跟54个字符来存储用户名,用空格填充.最简单的方法是使用BinaryReader.ReadString():

    public static string GetExcelFileOwner(string path) {
        string uspath = Path.Combine(Path.GetDirectoryName(path), "~$" + Path.GetFileName(path));
        if (!File.Exists(uspath)) return "";
        var sharing = FileShare.ReadWrite | FileShare.Delete;
        using (var fs = new FileStream(uspath, FileMode.Open, FileAccess.Read, sharing))
        using (var br = new BinaryReader(fs, Encoding.Default)) {
            return br.ReadString();
        }
    }
    

    但是,不一定是最正确的方法,如果8位编码在您的语言环境中不能正常工作,您可能希望改进代码并尝试找到utf-16字符串(不使用ReadString).Seek()首先偏移0x37.确保正确使用该方法,它具有隐式竞争条件,因此请确保仅在操作失败使用它并且期望无论如何返回空字符串.我不能保证这种方法在所有Excel版本上都能正常工作,包括未来的版本,我只在工作站类机器上测试过Office 2013.

    2022-12-19 16:04 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有