Author Posts

March 21, 2016 at 12:44 am

Hi, I has written PowerShell function which creates registry entry on remote computer(s). Path where entry is created depends on whether remote computer runs 32-bit or 64-bit Windows. In BEGIN block of advanced function I have following lines:


$property = @{
Path = "" #empty string, it will take value depending on OS architecture of remote pc
Name = "WindowsLogonLocal"
PropertyType = "String"
Value = "LCL-AAA-FORCE-4651"
}

In PROCESS block I have following lines (in foreach loop):


$param = @{
ComputerName = $Computer
Class = 'Win32_OperatingSystem'
}

if((Get-WmiObject @param).OSArchitecture -eq '32-bit') {
$property.Set_Item("Path","HKLM:\software\pexim\config")
}

if((Get-WmiObject @param).OSArchitecture -eq '64-bit') {
$property.Set_Item("Path","HKLM:\software\wow6432node\pexim\config")
}

Invoke-Command -ComputerName $Computer -ScriptBlock {
New-ItemProperty @using:property
}

I want to optimize this. Remote computers run PowerShell v2 but I would like to avoid using Get-WmiObject since WMI is almost thing of the past. I could use Invoke-Command -ComputerName $Computer -ScriptBlock {[System.Environment]::Is64BitOperatingSystem} to test if remote computer runs 32-bit or 64-bit Windows but then I would have two Invoke-Command lines.

March 21, 2016 at 1:31 am

Not true. If you use the -ScriptBlock (or its alias -Command) parameter, you can run a multiple commands within the block. Or you can use the -FilePath parameter to specify a local script to be run on the remote system.

March 21, 2016 at 4:13 am

I did not mean two lines inside script block but two lines with Invoke-Command cmdlet:

$isOS32bit = Invoke-Command -ComputerName $Computer -ScriptBlock {-not[System.Environment]::Is64BitOperatingSystem
}
if($isOS32bit) {$property.Set_Item("Path","HKLM:\software\pexim\config")}
else {$property.Set_Item("Path","HKLM:\software\wow6432node\pexim\config")}
Invoke-Command -ComputerName $Computer -ScriptBlock {
New-ItemProperty @using:property
}

March 21, 2016 at 4:35 am

First of all, don't expect WMI (or CIM) to become "a thing of the past" anytime soon. A lot of PowerShell stuff relies heavily on these technologies, and it is perfectly fine to utilize it in your code (all a matter of taste).

I think you misunderstood Bob's comment. What he is saying is that what you try to achieve, you can do with a single call to Invoke-Command by using a ScriptBlock with several lines of code.

You might do something like this (untested):

Invoke-Command -ComputerName $Computer -ScriptBlock {

    $property = $using:property
    
    # If x64 (64bit) system
    if ($env:PROCESSOR_ARCHITECTURE -eq 'AMD64')
    {
    
        $property.Set_Item('Path','HKLM:\software\wow6432node\pexim\config')
    
    }
    # If x86 (32bit) system
    else
    {
    
        $property.Set_Item('Path','HKLM:\software\pexim\config')
    
    }
    
    New-ItemProperty @property
}

March 21, 2016 at 4:44 am

Ok, so it is perfectly normal to assign value of local variable to variable in remote session and continue using it ($property = $using:property) or modify it. Speaking of WMI (not CIM), I am limited to use WMI (DCOM) or CIM (over DCOM) since my remote clients are running Windows 7 which comes with PowerShell v2. WSMAN can not be used and DCOM (RPC) is not ideal communication protocol.