且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

检查谁有一个Excel文件在Powershell中打开

更新时间:2023-11-25 16:20:58

我仍然使用基于Netapi32的功能实现这一点。 / p>

  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权限;
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(Unma nagedType.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);

}
@

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

$ struct =新对象netapi + FILE_INFO_3
$ buffer = 0
$ entries = 0
$ total = 0
$ handle = 0
$ Level = 3#用于定义我们想要的结构类型,即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())

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

$ offset = $ ptr.ToInt64()
$ offset + = $ increment
}
}
else
{
写输出([ ComponentModel.Win32Exception] [Int32] $ ret).Message

if($ ret -eq 1208)
{
#标记为扩展错误的错误代码要求缓冲区为freed
[Void] [Netapi] :: NetApiBufferFree($ buffer)
}
}

$ files
}

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

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


文件ID:205
权限:35
NumLocks:0
路径:C:\Temp\EXCEL.XLSX
用户:mickyb

U唱 Get-OpenFiles -Path C:\Temp 也可以:

  FileID:205 
权限:35
NumLocks:0
路径:C:\Temp\EXCEL.XLSX
用户:mickyb

FileID :213
权限:51
NumLocks:0
路径:C:\Temp\〜$ Excel.xlsx
用户:mickyb

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

  Get-OpenFiles -User mickyb 


Im using Powershell 4.0 on win7 64 bit, I want to see who has an excel file open, or even if the file is open.

Example. I have the excel file "test" on network drive B. If one person opens "test" I understand that will create an excel lock file looking like this "~$test.xls". So far I have used Test-path to verify that the excel lock file exists. Then I believe I can use Get-Acl to find the owner of that file. Is there a simpler way to find out who has an excel file open? Or will my workaround for checking the ownership of the lock file work?

I still use Netapi32 based functions for achieving this.

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
}

Then you can call the Get-OpenFiles and pass a specific path name:

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


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

Using Get-OpenFiles -Path C:\Temp works too:

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

You could also see if a specific user has files open:

Get-OpenFiles -User mickyb