将mofcomp.exe与变量而不是文件一起使用

时间:2016-04-27 13:10:54

标签: powershell variables

我正在尝试导出和导入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: $_"
        }
    }
}

要在WMI reporesitory中导回生成的MOF文件,可以使用以下命令:

$Path = 'C:\Temp\MyMof.mof'
$MofComp = Get-Item 'C:\Windows\System32\wbem\mofcomp.exe'
Invoke-expression "& $MofComp $Path"

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

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

2 个答案:

答案 0 :(得分:1)

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

在Bash中,这个临时文件会自动清理,而不幸的是,我的模拟需要进行明确的清理。

请注意,这是一个泛型机制,可以使用(仅)从文件中获取输入的任何命令 - 例如mofcomp.exe

应用于您的方案,您可以按如下方式使用它(cf是函数ConvertTo-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
  }
}

答案 1 :(得分:0)

如果您只是添加AUTORECOVER编译指示,那么您可以这样调用它:

mofcomp filename.mof -Autorecover

根据MSDN的this文章:

  

MOF编译器位于%Windir%\ System32 \ wbem目录中。必须将MOF文件指定为MOF编译器的参数。如果要在必须自动恢复CIM存储库的情况下自动重新编译MOF文件,还可以指定自动恢复开关。有关更多信息,请键入Mofcomp /?在命令提示符下。

因此,根据该引用,您必须指定文件路径。

要更改名称空间,您不能只在PowerShell中调用Set-WmiInstance -NameSpace "MyNameSpace"吗?我可能不完全理解这一点,但是你是否试图以实例或抽象类为目标?

您唯一的选择可能是将文件保存在某个位置,例如$env:TEMP,然后在完成后将其删除。