如何创建 Powershell 自定义对象,例如 'Import-CSV'



我正在尝试从Microsoft访问中拉出一张表,并且看起来像PowerShell中的Import-CSV表,如果CSV文件中的每个列成为自定义对象的属性,而行中的项目成为属性值。我唯一取得的成功是:

$ColumnCount = 0;
$contactObject = new-object PSObject;
if ($rs.RecordCount -ne 0) {
    do { 
        $rs.MoveFirst()
        $valueArray = @();
        do {
            foreach ($columnHeader in $rs.fields.item($ColumnCount).name) {
                $value = $rs.Fields.Item($columnHeader).Value;
                $valueArray += $value      
            }
            $rs.MoveNext()
        } until ($rs.EOF -eq $True)
        $contactObject | Add-Member -MemberType NoteProperty -Name $columnHeader -Value $valueArray;    
        $ColumnCount++
    } until ($ColumnCount -eq $rs.fields.count)
}

,它输出了以下内容:

EquipmentPackageID      ElementID           ArchitectureID    Delete                         
------------------      ---------           --------------    ------                         
{117, 117, 126, 126...} {32, 32, 32, 32...} {-1, 1, -1, 1...} {False, False, False, False...}

但我不想要单个数组。

我希望这一切基本上都是一个桌子。而且,此功能必须能够接受访问的不同尺寸和命名表。因此,我无法创建针对此4列表量身定制的自定义对象。

powershell v3.0 的基本模式是这样的:

$MyFiles = Get-ChildItem C:Windows | ForEach-Object {
    [pscustomobject]@{
        Name = $_.Name;
        FullName = $_.FullName;
        CreationDate = $_.CreationTime.Date;
    }
}

另外,避免这种模式:

$Array = @()
$x | ForEach-Object {
   $Record = [...]
   $Array += $Record
}

基本.NET阵列无法调整大小。这意味着$Array += [...]必须制作一个全新的数组,复制所有内容,然后销毁旧数组。数组的变化越大,此操作越昂贵,它消耗的内存就越多,并且脚本的速度越慢。它将任何普通的O(n)复杂度循环变成O(n^2)复杂度环。

这意味着您应该这样做:

$Array = $x | ForEach-Object { [...] }

或以下:

$Array = New-Object -TypeName System.Collections.ArrayList;
$x | ForEach-Object {
   $Record = [...]
   $Array.Add($Record)
}

这是一个动态拉动标头的示例。在这种情况下,它将在C:Windows中的前10个文件中拉出类型字符串和DateTime的所有属性。

# Get the data
$Data = Get-ChildItem C:Windows -File | Select-Object -First 10;
# Get the headers that meet our criteria
# It's not important what this code is doing, it's just establishing headers 
# dynamically
$Headers = $Data[0].PSObject.Properties |
    Where-Object TypeNameOfValue -in @('System.String', 'System.DateTime') | 
    Select-Object -ExpandProperty Name;
# Iterate through the Data
$Results = $Data | ForEach-Object {
    # Create a hash table to save the properties in.
    $Record = @{};
    # For each header, create a property in the hash table and assign it the corresponding value from the object in the stream
    foreach ($Header in $Headers) {
        $Record.$Header = $_.$Header;
    }
    # Convert the hash table we've saved to a PSCustomObject
    [PSCustomObject]$Record;
}

不幸的是,我不知道$rs是什么或如何创建一个。我认为这就像ADO RecordSet一样,但是您的逻辑使我有些逃脱。 (也就是说,如果$rs.MoveFirst()做到了我记得的RecordSet.MoveFirst(),则看起来像是错误的循环,但我可能会误解。)

这里的想法是相同的。

$resultsArray =  New-Object -TypeName System.Collections.ArrayList;
$ColumnCount = 0;
$contactObject = New-Object PSObject;
if ($rs.RecordCount -ne 0){
$rs.MoveFirst()
Do {
$ColumnCount = 0;
Do{ 
$columnHeader = $rs.fields.item($ColumnCount).name
$value = $rs.Fields.Item($columnHeader).Value;
$contactObject | add-member -membertype NoteProperty  -name $columnHeader  -
Value $value;  
$columncount++
}until($ColumnCount -eq $rs.fields.count)
  
 $resultsArray.add($contactObject) 
$rs.MoveNext()         
 $contactObject= New-Object PSObject; 
  
} until ($rs.EOF -eq $True)
      
   
}
}
   $resultsarray 

我做到了!诀窍是将记录添加到数组,然后清除对象,添加成员,添加到数组,清除对象.....棒极了!

相关内容

最新更新