I'm trying to use WMI to retrieve network adapter information on remote servers.
I've ran a few Get-WmiObject commands with various degrees of success.
This line works fine:
Invoke-Command $serverName -ScriptBlock {Get-WmiObject
Win32_networkadapterconfiguration | where {$_.Index -eq 7}}
When I try to introduce a variable to the command it returns nothing:
$Variable = 7
Invoke-Command $serverName -ScriptBlock {Get-WmiObject
Win32_networkadapterconfiguration | where {$_.Index -eq $Variable}}
Any idea why the command with the variable would fail?
Related
I am trying to script a powershell function manage-bde.exe (bitlocker) to add a key protector to systems without TPM. For some reason GPO is not working. I have not had any luck getting powershell to add the protector remotely. I can log on to the endpoint and use the built in wizard to encrypt and save the key to our repository but for some reason remote automated scripting eludes me. My question is really more of guidance. Can powershell only be used, to remotely manage systems with TPM? I have bitlocker enabled and encrypted on systems without but I have had to do it manually.
Start-Transcript -Path ".\bitlockertranscript.txt" -Force
foreach ($Computer in $List) {
if (test-Connection -ComputerName $Computer -Count 1 -Quiet ) {
Get-ADComputer -Identity $Computer -Property * | Select Name,OperatingSystem
Get-WmiObject -class Win32_Tpm -namespace root\CIMV2\Security\MicrosoftTpm -computername $Computer | fl IsActivated_InitialValue, IsEnabled_InitialValue, IsOwned_InitialValue
$BitLocker = Get-WmiObject -ComputerName $Computer -Namespace Root\cimv2\Security\MicrosoftVolumeEncryption -Class Win32_EncryptableVolume
$id = $BitLocker.GetKeyProtectors(3).volumekeyprotectorid | Select -First 1
manage-bde.exe -cn $Computer -protectors -adbackup c:
manage-bde.exe -on C: -cn $Computer
Invoke-GPUpdate -Target $computer
} else
{"No Connection to $Computer"
}
}
Stop-Transcript
I've been attempting to pass a variable in Powershell using Invoke-Command, however, every example I've found doesn't seem to work when using Get-CimInstance. This is the basic code I'm using is:
$Computer = (Read-Host "Enter Computer Name")
$User = (Read-Host "Enter User Name")
$Cred = (Get-Credential -Message "Enter Credentials" )
Invoke-Command -ComputerName $Computer -Credential $Cred -ScriptBlock {(Get-CimInstance -Class Win32_UserProfile -Filter 'LocalPath like "%$User"').LocalPath.split('\')[-1] | Remove-CimInstance}
When I run that I get a null value:
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : DBServer
I've also tried using the -ArgumentList flag, but that doesn't work either and I get the null value error again:
Invoke-Command -ComputerName $Computer -Credential $Cred -ScriptBlock {(Get-CimInstance -Class Win32_UserProfile -Filter 'LocalPath like "%$using:User"').LocalPath.split('\')[-1] | Remove-CimInstance} -ArgumentList $User
or:
Invoke-Command -ComputerName $Computer -Credential $Cred -ScriptBlock {(Get-CimInstance -Class Win32_UserProfile -Filter 'LocalPath like "%$args[0]"').LocalPath.split('\')[-1] | Remove-CimInstance} -ArgumentList $User
My best guess is that the -Filter flag is causing the issue. Though it works just fine if run locally. Also in my test case some usernames start with a dollar sign (ie $fredsmith) which may be an issue as well.
The doublequotes have to be on the outside to interpret the variable.
$user = 'joe'
"localpath like '%$user%'"
localpath like '%joe%'
This worked for me at an elevated prompt with the winrm service running:
invoke-command localhost {
get-wmiobject win32_userprofile -filter "localpath like '%$using:user%'" }
Or with no quoting issues:
invoke-command localhost {
get-ciminstance win32_userprofile | where localpath -match $using:user |
remove-ciminstance -whatif }
invoke-command localhost { param($user)
get-wmiobject win32_userprofile | where localpath -match $user } -args $user
invoke-command localhost {
get-wmiobject win32_userprofile | where localpath -match $args[0] } -args $user
I want to sometimes check some info from our servers in domains. In this example, I am trying to remotely get windows versions (just one server, currently without loop):
$cr=Get-Credential "domain\adm_user"
$computer="serverA"
Invoke-Command { Get-WmiObject -Class Win32_OperatingSystem -Namespace root/cimv2 -Computer $computer -Credential $cr | Format-List -Property Name, OSArchitecture, SerialNumber} -AsJob -ComputerName .
Get-Job | Wait-Job
Get-Job | Receive-Job
Output:
Cannot validate argument on parameter 'ComputerName'. The argument is null or empty. Supply an argument that is not null or empty and then try the command again.
Seems, that scriptblock {} cannot see variable $computer.
When I replace variable -computer $computer to name of server, it is working.
For variable expansion inside Invoke-Command use a param block and specify arguments:
$computer = 'localhost'
Invoke-Command {param($computer) Get-WmiObject Win32_OperatingSystem -Computername $computer } -ArgumentList $computer
Working on PS v5.
I am trying to disable a service running on 250+ PCs. I would like to have a PowerShell script I can execute on a random PC in the network and let it disable a service on every PC I specify in an txt file. It's always the same service. The script should also ask for the credential of the PC that it is trying to connect to.
This is a Script to set DNS on every PC in computer.txt. It asks me for the "administrator" password for every PC.
function Set-DNSWINS {
#Get NICS via WMI
$remoteuser = get-credential $_\administrator
$NICs = Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Credential $remoteuser -ComputerName $_ -Filter "IPEnabled=TRUE"
Get-WmiObject -Class Win32_NetworkAdapterConfiguration -Credential $remoteuser -ComputerName $_ -Filter "IPEnabled=TRUE"
foreach($NIC in $NICs) {
$DNSServers = "192.168.3.12","192.168.0.77"
$NIC.SetDNSServerSearchOrder($DNSServers)
$NIC.SetDynamicDNSRegistration("TRUE")
#$NIC.SetWINSServer("12.345.67.890", "12.345.67.891")
}
}
function Get-FileName {
$computer = Read-Host "Dateiname mit Computernamen"
return $computer
}
Get-Content computer.txt | ForEach-Object {Set-DNSWINS}
You can stop a service from the commandline using
net stop "servicename"
or in PowerShell
Stop-Service "serviceName"
There are probably better ways to automate this across multiple machines than your script.
Can use Set-Service to disable a service and Invoke-Command to run it remotely. Note you need to run Enable-PSRemoting on the remote computer and configure WSMAN to allow connecting to the remote PC:
function MyFunction{
$remoteuser = get-credential $_\administrator
$service = "MyService"
Invoke-Command -computer $_ -credential $remoteuser -scriptblock {
Stop-Service $service
Set-Service $service -startuptype Disabled
}
}
function Get-FileName {
$computer = Read-Host "Dateiname mit Computernamen"
return $computer
}
Get-Content computer.txt | ForEach-Object {MyFunction}
The only way I can find to get an instance of the StdRegProv WMI class in Powershell is
$StdRegProv = Get-WmiObject -List -Namespace root\default -ComputerName "my_computer" -Credential $cred | where { $_.Name -eq "StdRegProv" }
I need to go this route because I want to supply a credential. Naively I would have expected the following to work:
$StdRegProv = Get-WmiObject -Class StdRegProv -Namespace root\default -ComputerName "my_computer" -Credential $cred
but it doesn't - why can't you get at StdRegProv in this way?
As far as I understand, Get-WmiObject returns existing instances of a class. If there are no instances, you get an empty collection. (But don't quote me on this because it's just a guess - I haven't looked at Get-WmiObject code.)
Anyway, you can use:
[WMIClass]"root\default:StdRegProv"
to instantiate the class. Or, if it has to be gwmi:
Get-WmiObject -List -Namespace "root\default" -ComputerName "my_computer" `
| Where-Object {$_.Name -eq "StdRegProv"}
Source: Powershell remote registry access via WMI.