我正在尝试导出和导入WMI类。到目前为止,一切都很好,并且我能够以正确的格式导出WMI类:

Function Export-WMIDetailsHC {
    [CmdletBinding()]
    Param (
        [Parameter(Mandatory)]
        [String]$Namespace,
        [Parameter(Mandatory)]
        [String]$ClassName,
        [ValidateScript({
            if (($_ -like '*.mof') -and (Test-Path -LiteralPath (Split-Path $_) -PathType Container)) {$true}
            else {throw "The path must end with the extension '.MOF' and the path location must exist."}
        })]
        [String]$Path
    )

    Process {
        Try {
            [System.Management.Textformat]$MOF = 'mof'

            if ($WmiClass = Get-WmiObject -Namespace $Namespace -ClassName $ClassName -List -EA Stop) {
                Write-Verbose "Namespace '$Namespace' ClassName '$ClassName'"
                $Result += "`n" + ('#PRAGMA NAMESPACE("\\\\.\\' + ($Namespace.Split('\') -join '\\') + '")') + "`n"
                $Result += $WMIClass.GetText($MOF)
            }
            else {
                Write-Verbose "No WMI class found with name '$ClassName' in namespace '$Namespace'"
            }

            if ($Result) {
                $Result = $Result = '#PRAGMA AUTORECOVER' + "`n" + $Result
                if ($Path) {
                    $Result | Out-File -LiteralPath $Path # Encoding is special 'UCS-2 LE BOM'
                    Get-Item $Path
                    Write-Verbose "Exported WMI details to MOF file '$Path'"
                }
                else {
                    $Result
                }
            }
        }
        Catch {
            throw "Exporting WMI details to the MOF file '$Path' for class '$ClassName' in namespace '$Namespace' failed: $_"
        }
    }
}

要将生成的MOF文件导入WMI文件中,可以使用以下命令:
$Path = 'C:\Temp\MyMof.mof'
$MofComp = Get-Item 'C:\Windows\System32\wbem\mofcomp.exe'
Invoke-expression "& $MofComp $Path"

但是,我想知道是否可以在变量而不是文件路径上运行mofcomp.exe?这样,就无需在步骤之间创建临时文件,并且可以立即使用Export-WMIDetailsHC的输出。

这可能吗?谢谢您的帮助。

最佳答案

this answer中,我创建了Bash的process substitution的穷人版本,该版本提供了一种从命令输出中创建临时临时文件并返回该临时文件路径的方法。

在Bash中,该临时文件会自动清除,而不幸的是,我的仿真需要显式清除。

请注意,这是一种通用机制,可与(仅)从文件获取输入的任何命令配合使用,例如mofcomp.exe

应用于您的方案时,将按以下方式使用它(cfConvertTo-TempFile函数的别名,定义如下):

# Use `cf()` to save the script block's output to a temporary *.mof file
# and return that file's path.
& 'C:\Windows\System32\wbem\mofcomp.exe' (cf -Extension .mof { Export-WMIDetailsHC ... })
cf  # clean up temporary file

为了方便起见,我将在此处重新打印函数定义,但是可以在linked answer中找到更多背景信息。
# Define a succinct alias.
set-alias cf ConvertTo-TempFile
function ConvertTo-TempFile {
  [CmdletBinding(DefaultParameterSetName='Cleanup')]
  param(
      [Parameter(ParameterSetName='Standard', Mandatory=$true, Position=0)]
      [ScriptBlock] $ScriptBlock
    , [Parameter(ParameterSetName='Standard', Position=1)]
      [string] $LiteralPath
    , [Parameter(ParameterSetName='Standard')]
      [string] $Extension
    , [Parameter(ParameterSetName='Standard')]
      [switch] $NoBOM
  )

  $prevFilePath = Test-Path variable:__cttfFilePath
  if ($PSCmdlet.ParameterSetName -eq 'Cleanup') {
    if ($prevFilePath) {
      Write-Verbose "Removing temp. file: $__cttfFilePath"
      Remove-Item -ErrorAction SilentlyContinue $__cttfFilePath
      Remove-Variable -Scope Script  __cttfFilePath
    } else {
      Write-Verbose "Nothing to clean up."
    }
  } else { # script block specified
    if ($Extension -and $Extension -notlike '.*') { $Extension = ".$Extension" }
    if ($LiteralPath) {
      # Since we'll be using a .NET framework classes directly,
      # we must sync .NET's notion of the current dir. with PowerShell's.
      [Environment]::CurrentDirectory = $pwd
      if ([System.IO.Directory]::Exists($LiteralPath)) {
        $script:__cttfFilePath = [IO.Path]::Combine($LiteralPath, [IO.Path]::GetRandomFileName() + $Extension)
        Write-Verbose "Creating file with random name in specified folder: '$__cttfFilePath'."
      } else { # presumptive path to a *file* specified
        if (-not [System.IO.Directory]::Exists((Split-Path $LiteralPath))) {
          Throw "Output folder '$(Split-Path $LiteralPath)' must exist."
        }
        $script:__cttfFilePath = $LiteralPath
        Write-Verbose "Using explicitly specified file path: '$__cttfFilePath'."
      }
    } else { # Create temp. file in the user's temporary folder.
      if (-not $prevFilePath) {
        if ($Extension) {
          $script:__cttfFilePath = [IO.Path]::Combine([IO.Path]::GetTempPath(), [IO.Path]::GetRandomFileName() + $Extension)
        } else {
          $script:__cttfFilePath = [IO.Path]::GetTempFilename()
        }
        Write-Verbose "Creating temp. file: $__cttfFilePath"
      } else {
        Write-Verbose "Reusing temp. file: $__cttfFilePath"
      }
    }
    if ($NoBOM) { # UTF8 file *without* BOM
      # Note: Out-File, sadly, doesn't support creating UTF8-encoded files
      #       *without a BOM*, so we must use the .NET framework.
      #       [IO.StreamWriter] by default writes UTF-8 files without a BOM.
      $sw = New-Object IO.StreamWriter $__cttfFilePath
      try {
          . $ScriptBlock | Out-String -Stream | % { $sw.WriteLine($_) }
      } finally { $sw.Close() }
    } else { # UTF8 file *with* BOM
      . $ScriptBlock | Out-File -Encoding utf8 $__cttfFilePath
    }
    return $__cttfFilePath
  }
}

10-05 20:00
查看更多