【问题标题】:Checking Who has an Excel File Open In Powershell检查谁在 Powershell 中打开了 Excel 文件
【发布时间】:2016-01-19 19:57:00
【问题描述】:

我在win7 64位上使用Powershell 4.0,我想看看谁打开了excel文件,或者即使文件打开了。

示例。我在网络驱动器 B 上有 excel 文件“test”。如果有人打开“test”,我知道这将创建一个类似于“~$test.xls”的 excel 锁定文件。 到目前为止,我已经使用 Test-path 来验证 excel 锁定文件是否存在。然后我相信我可以使用 Get-Acl 找到该文件的所有者。有没有更简单的方法来找出谁打开了 excel 文件?或者我检查锁定文件所有权的解决方法是否有效?

【问题讨论】:

  • 您是否尝试使用 powershell 检查所有者?请添加您尝试过的内容以及阻碍您的内容,以便我们帮助调试(您可以编辑您的问题)
  • 我认为没有“更简单”的方法,除非您使用的是 Windows 8 并且可以访问 Get-SmbOpenFile cmdlet。我认为您的解决方法会足够好。虽然我确信存在更清洁的解决方案,但它不会是一个简短或简单的解决方案。

标签: excel powershell


【解决方案1】:

我仍然使用基于 Netapi32 的函数来实现这一点。

Add-Type -TypeDefinition @" 
using System; 
using System.Runtime.InteropServices;

public class Netapi 
{ 

    [DllImport("Netapi32.dll",CharSet=CharSet.Unicode)] 
    public static extern int NetApiBufferFree(IntPtr buffer); 

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    public struct FILE_INFO_3
    {
        public uint FileID;
        public uint Permissions;
        public uint NumLocks;
        [MarshalAs(UnmanagedType.LPWStr)] public string Path;
        [MarshalAs(UnmanagedType.LPWStr)] public string User;
    }

    [DllImport("Netapi32.dll",CharSet=CharSet.Unicode)] 
    public static extern uint NetFileEnum(
        [In,MarshalAs(UnmanagedType.LPWStr)] string server,
        [In,MarshalAs(UnmanagedType.LPWStr)] string path,
        [In,MarshalAs(UnmanagedType.LPWStr)] string user,
        int level,
        out IntPtr bufptr, 
        int prefmaxlen,
        ref Int32 entriesread, 
        ref Int32 totalentries, 
        ref Int32 resume_handle); 

}
"@ 

function Get-OpenFiles
{
    [CmdletBinding()]   
    param ( [string]$Server = "localhost", 
            [string]$User = $null,
            [string]$Path = $null)

    $struct = New-Object netapi+FILE_INFO_3 
    $buffer = 0
    $entries = 0
    $total = 0
    $handle = 0
    $Level=3 # used to define the type of struct we want, i.e. FILE_INFO_3

    $ret = [Netapi]::NetFileEnum($server, $path, $user, $level,
                                  [ref]$buffer, -1,
                                  [ref]$entries, [ref]$total,
                                  [ref]$handle) 

    $files = @()
    if (!$ret)
    {
        $offset = $buffer.ToInt64()
        $increment = [System.Runtime.Interopservices.Marshal]::SizeOf([System.Type]$struct.GetType())

        for ($i = 0; $i -lt $entries; $i++)
        {
            $ptr = New-Object system.Intptr -ArgumentList $offset
            $files += [system.runtime.interopservices.marshal]::PtrToStructure($ptr, [System.Type]$struct.GetType())

            $offset = $ptr.ToInt64()
            $offset += $increment
        }
    }
    else
    {
        Write-Output ([ComponentModel.Win32Exception][Int32]$ret).Message

        if ($ret -eq 1208)
        {
            # Error Code labeled "Extended Error" requires the buffer to be freed
            [Void][Netapi]::NetApiBufferFree($buffer)
        }
    }

    $files
}

然后你可以调用 Get-OpenFiles 并传递一个特定的路径名​​:

Get-OpenFiles -Path C:\Temp\EXCEL.XLSX


FileID      : 205
Permissions : 35
NumLocks    : 0
Path        : C:\Temp\EXCEL.XLSX
User        : mickyb

使用Get-OpenFiles -Path C:\Temp 也可以:

FileID      : 205
Permissions : 35
NumLocks    : 0
Path        : C:\Temp\EXCEL.XLSX
User        : mickyb

FileID      : 213
Permissions : 51
NumLocks    : 0
Path        : C:\Temp\~$Excel.xlsx
User        : mickyb

您还可以查看特定用户是否打开了文件:

Get-OpenFiles -User mickyb

【讨论】:

  • 这段代码的奇怪之处在于该函数有效,但使用 Get-OpenFiles -path C:\wmw 后我没有得到任何输入从执行后的代码。它完成并空白。
  • 是的,如果它没有找到打开的文件,它就会这样做。
【解决方案2】:

如果您将锁定文件的内容复制到控制台,它应该包含锁定文件的用户的名称。您可能必须复制锁定文件才能读取它。我不熟悉 PowerShell,但我认为它具有 DOS 批处理文件的所有功能,并且可以创建类似于我在下面编写的技术。

这是我添加到我的SendTo 文件夹的批处理文件,它允许我右键单击 Excel 文件,它会告诉我谁锁定了文件。我已经用.xlsx.xlsm 文件对此进行了测试。

@echo off
REM ===================================================================
REM  Put this in your SendTo folder and it will let you right-click 
REM  on an .xlsx/.xlsm  file and show you the user name in the lock file
REM 
REM  If an Excel file is locked, look to see if a hidden lock file exists.  If
REM  the file is found, make a local temp copy of it and display the contents which 
REM  should be the name of the user holding the lock.
REM ===================================================================

setlocal
set file="%1"

REM Make sure the file has a compatible extension.
if  "%~x1"==".xlsx"   goto :ExtensionIsValidExcel
if  "%~x1"==".xlsm"   goto :ExtensionIsValidExcel

echo.
echo "%~n1%~x1" is not a supported file type.
echo.
pause
exit


:ExtensionIsValidExcel

REM  If an Excel file is locked, look to see if a hidden lock file exists.  If
REM  the file is found, make a local temp copy of it and display the contents which 
REM  should be the name of the user holding the lock.

IF EXIST %~dp1~$%~n1%~x1 ( 
    ECHO f | Xcopy %~dp1~$%~n1%~x1 "%TEMP%\~temp.txt" /H /R /Y /F
    attrib -h -s %TEMP%\~temp.txt

    cls
    ECHO.
    ECHO The Excel file "%~n1%~x1" file is locked by:
    ECHO.
    REM copy the file to the console to show the user name.
    copy %TEMP%\~temp.txt con | Find /v "file(s) copied" 
    del %TEMP%\~temp.txt
) Else (
    cls
    ECHO.
    ECHO The Excel file "%~n1%~x1" file is not locked in a way this was expecting.
)
ECHO.
ECHO.
pause

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2015-11-28
    • 2015-12-22
    • 1970-01-01
    • 2015-08-02
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多