I'm struggling to create a WQL query for SCCM as I'm really new and rarely use it in a complex manner.
My goal is to list 3 things : Computer name - Display Name ("Google Chrome") - Display Version (of that Google Chrome entry)
I'm starting with this :
$SiteCode = "XXX"
$SiteServer = "XXX"
$query = #"
select SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
from SMS_R_System
inner join SMS_G_System_ADD_REMOVE_PROGRAMS
on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
"#
Get-WmiObject -namespace root\sms\site_$SiteCode -computer $SiteServer -query $query
The output is a bit strange to me :
__GENUS : 2
__CLASS : __GENERIC
__SUPERCLASS :
__DYNASTY : __GENERIC
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER : XXX
__NAMESPACE : root\sms\site_PR1
__PATH :
SMS_G_System_ADD_REMOVE_PROGRAMS : System.Management.ManagementBaseObject
SMS_R_System : System.Management.ManagementBaseObject
PSComputerName : XXX
What am I missing here? Again i'm really new at this so I must be missing a key part of the logic.
If I remove :
, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
The query works and shows me all the computers that have Chrome installed:
__GENUS : 2
__CLASS : SMS_R_System
__SUPERCLASS : SMS_Resource
__DYNASTY : SMS_BaseClass
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {SMS_Resource, SMS_BaseClass}
__SERVER : XXX
__NAMESPACE : root\sms\site_XXX
__PATH :
Name : PXXX
PSComputerName : XXX
but I want those 2 properties too, not just the computer name so I can confirm the version numbers.
Much appreciated.
To expand on my comments in an alternate way to handle the problem at hand:
$wmiParams = #{
Namespace = 'root/sms/site_XXX'
ComputerName = 'XXX'
Query = #'
SELECT SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
FROM SMS_R_System
INNER JOIN SMS_G_System_ADD_REMOVE_PROGRAMS
ON SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
WHERE SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
'#
}
$smsResults = Get-WmiObject #wmiParams
foreach ($object in $smsResults) {
[pscustomobject]#{
ComputerName = $object['SMS_R_System']['Name']
DisplayName = $object['SMS_G_System_ADD_REMOVE_PROGRAMS']['DisplayName']
Version = $object['SMS_G_System_ADD_REMOVE_PROGRAMS']['Version']
}
}
The answer is to simply "expand" the dictionaries like pointed out by #TheIncorrigible.
So here is how I ended up doing it using the Name/Expression method in Select-Object:
$query = #"
select SMS_R_System.Name, SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName, SMS_G_System_ADD_REMOVE_PROGRAMS.Version
from SMS_R_System
inner join SMS_G_System_ADD_REMOVE_PROGRAMS
on SMS_G_System_ADD_REMOVE_PROGRAMS.ResourceID = SMS_R_System.ResourceId
where SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName = "Google Chrome"
"#
Get-WmiObject -namespace root\sms\site_$SiteCode -computer $SiteServer -query $query | Select-Object #{name='ComputerName';expression={$_.SMS_R_System.Name} }, #{name='DisplayName';expression={$_.SMS_G_System_ADD_REMOVE_PROGRAMS.DisplayName} }, #{name='Version';expression={$_.SMS_G_System_ADD_REMOVE_PROGRAMS.Version} }
I want change RDP port with WMI method but my code doesn't work and I don't know why.
Invoke-WmiMethod -Class StdRegprov -Name SetDWORDvalue -ArgumentList 2147483650,"System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp", "PortNumber", 3354
I get this after execute in PowerShell:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 5
PSComputerName :
But nothing changed?
This right here indicates your problem:
ReturnValue : 5
Return code 5 means "access denied". Your user does not have permission to write to that registry location. You probably need to run the code "as administrator".
With that said, PowerShell provides direct access to the registry. You don't need WMI for that.
$reg = 'HKLM:\System\CurrentControlSet\Control\Terminal Server\WinStations\RDP-Tcp'
$name = 'PortNumber'
$value = 3354
New-ItemProperty -Path $reg -Name $name -Value $value -Type DWORD -Force | Out-Null
You still need to run this with a user who has write access to the registry key, though.
For reasons that should not impact the current question I need to run a script, with the definition and parameters outside the command, inside a different PowerShell instance, without using PSSessions, background jobs or files (I have working examples for PSSession, background jobs and .ps1 files and I'm aware they can replace what I'm trying to do, but I need a working example with powershell.exe -Command as well).
I looked at the help for powershell.exe, and it should support what I am trying to do, but I can't get it working with all that I need (script definition and parameters outside the command).
As a working example I have:
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command {Invoke-Command -ScriptBlock {
param($a1,$a2)
$a1*6
$a2*5} -Argumentlist #(8,'abc')}
I need to be able to at least move the -ArgumentList outside the command, like:
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command {Invoke-Command -ScriptBlock {
param($a1,$a2)
$a1*6
$a2*5} -Argumentlist #($args[0],$args[1])} -args #(8,'abc')
and even better have:
$script={
param($a1,$a2)
$a1*6
$a2*5}
$args=#(8,'abc')
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command $script -args $args
I already looked at the following similar questions, but couldn't find what I needed:
How to run a Powershell script from the command line and pass a directory as a parameter
How can I Start-Process powershell.exe with some string splitter?
Not sure if this helps I added a few things to your original script and changed $args to $z and it seemed to work.
$script={
param($a1 =1 ,$a2 = 2)
$a1*6
$a2*5
test-connection -Count 2 www.google.com
Write-Output $a1
Write-Output $a2
}
$z=#(8,'abc')
$abc = powershell.exe -WindowStyle Hidden -NonInteractive -Command $script -args $z
$abc
48
abcabcabcabcabc
PSComputerName : ok
IPV4Address :1.1.1.4
IPV6Address :
__GENUS : 2
__CLASS : Win32_PingStatus
__SUPERCLASS :
__DYNASTY : Win32_PingStatus
__RELPATH : Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressNames=FALSE,SourceRou
te="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
__PROPERTY_COUNT : 24
__DERIVATION : {}
__SERVER : ok
__NAMESPACE : root\cimv2
__PATH : \\ok\root\cimv2:Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressName
s=FALSE,SourceRoute="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
Address : www.google.com
BufferSize : 32
NoFragmentation : False
PrimaryAddressResolutionStatus : 0
ProtocolAddress :1.1.1.4
ProtocolAddressResolved :
RecordRoute : 0
ReplyInconsistency : False
ReplySize : 32
ResolveAddressNames : False
ResponseTime : 19
ResponseTimeToLive : 252
RouteRecord :
RouteRecordResolved :
SourceRoute :
SourceRouteType : 0
StatusCode : 0
Timeout : 4000
TimeStampRecord :
TimeStampRecordAddress :
TimeStampRecordAddressResolved :
TimestampRoute : 0
TimeToLive : 80
TypeofService : 0
PSComputerName : ok
IPV4Address :1.1.1.4
IPV6Address :
__GENUS : 2
__CLASS : Win32_PingStatus
__SUPERCLASS :
__DYNASTY : Win32_PingStatus
__RELPATH : Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressNames=FALSE,SourceRou
te="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
__PROPERTY_COUNT : 24
__DERIVATION : {}
__SERVER : ok
__NAMESPACE : root\cimv2
__PATH : \\ok\root\cimv2:Win32_PingStatus.Address="www.google.com",BufferSize=32,NoFragmentation=FALSE,RecordRoute=0,ResolveAddressName
s=FALSE,SourceRoute="",SourceRouteType=0,Timeout=4000,TimestampRoute=0,TimeToLive=80,TypeofService=0
Address : www.google.com
BufferSize : 32
NoFragmentation : False
PrimaryAddressResolutionStatus : 0
ProtocolAddress :1.1.1.4
ProtocolAddressResolved :
RecordRoute : 0
ReplyInconsistency : False
ReplySize : 32
ResolveAddressNames : False
ResponseTime : 21
ResponseTimeToLive : 252
RouteRecord :
RouteRecordResolved :
SourceRoute :
SourceRouteType : 0
StatusCode : 0
Timeout : 4000
TimeStampRecord :
TimeStampRecordAddress :
TimeStampRecordAddressResolved :
TimestampRoute : 0
TimeToLive : 80
TypeofService : 0
8
abc
This answer isn't 100% relevant to the original poster, because they are trying to run PowerShell from within PowerShell. I am trying to run it PowerShell from either a command prompt, or specifically WMI. A little background: the reason I'm trying to do this is because PowerShell remoting is not enabled on my target machine and I want to enable it. I can't use winrm because it requires user input. So, this works:
$x=Get-WmiObject -ComputerName "<computer name>" -Namespace "root\cimv2" -Class "Win32_Process" -List
$x.Create('C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command "& C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe -Command {Enable-PSRemoting}"',$null,$null)
Results:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ProcessId : 12508
ReturnValue : 0
PSComputerName :
I should probably post this in a different question, but this one came up on a google search for "how to pass scriptblock to powershell.exe", so I thought it would be useful here.
I'm trying to write a script which uninstalls Microsoft Office 2007 Enterprise by grabbing the IdentifyingNumber using Get-WmiObject -Class Win32_Product. I'm able to grab the IdentifyingNumber, but when I attempt to uninstall PowerShell outputs some information that I'm not sure what to do with. Is this not a proper way to utilize Uninstall()?
$2k7 = Get-WmiObject -Class Win32_Product | Where-Object { $_.IdentifyingNumber -match "{90120000-0030-0000-0000-0000000FF1CE}" }
if ($2k7 -ne $null) {
$2k7.Uninstall()
}
else {
write-host "nothing to see here"
}
Output...
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 1603
Error 1603 is a catch-all error used by Microsoft Installer when an unexpected failure is encountered.
I would verify that you're running your Powershell window with elevated privileges and that the program you intend to uninstall doesn't have any processes currently running.
I am trying to call the Rename method on the Win32_ComputerSytem class using Invoke-WMI method. Using this syntax works fine
(gwmi win32_ComputerSystem).Rename("NEWNAME")
This also works fine for demo purposes
Invoke-WmiMethod -path win32_process -Name create -ArgumentList notepad
However, when i try the following, I get an error
11 > Invoke-WmiMethod -path win32_computersystem -Name Rename -ArgumentList IwasRenamed
Invoke-WmiMethod : Invalid method Parameter(s)
At line:1 char:17
+ Invoke-WmiMethod <<<< -path win32_computersystem -Name Rename -ArgumentList IwasRenamed
+ CategoryInfo : InvalidOperation: (:) [Invoke-WmiMethod], ManagementExcepti
on
+ FullyQualifiedErrorId : InvokeWMIManagementException,Microsoft.PowerShell.Commands.
InvokeWmiMethod
What am I missing?
You need to specify an instance of the class Win32_ComputerSystem using the Path parameter:
PS C:\Users\ben> $path = "Win32_ComputerSystem.Name='OLDNAME'"
PS C:\Users\ben> Invoke-WmiMethod -Name Rename -Path $path -ArgumentList "NEWNAME"
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
Which is functionally equivalent to the gwmi Rename syntax that you referred to. This syntax implicitly retrieves an instance of the class Win32_ComputerSystem to call the method on:
PS C:\Users\ben> (gwmi win32_computersystem).rename("NEWNAME")
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
Here's another cool syntax:
PS C:\Users\ben> ([wmi]"Win32_ComputerSystem.Name='OLDNAME'").Rename("NEWNAME")
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 1
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ReturnValue : 0
The Rename method takes three parameters. I'm guessing Invoke-WmiMethod uses reflection to call the method, so you have to specify all three parameters. Try this:
[String]$newName = "IWasRenamed"
[String]$password = $null
[String]$username = $null
Invoke-WmiMethod -Path Win32_ComputerSystem -Name Rename -ArgumentList $newName, $password, $username