Powershell and TPM how to manage bitlocker? - powershell

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

Related

Get-WmiObject Win32_networkadapterconfiguration

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?

Kill Process On List Of remote Workgroup Servers

I have a list of 5 Servers and for specific reasons they are not on the domain. The credentials among them are the same.
I am trying to remotely kill any instance of a process on the machines. For this website I have change the process to notepad.exe
I am having issues trying to determine how to successfully connect to these boxes.
I am running
$StartCheck = Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }
$StartCheck | FT * -a;$StartCheck | FT * -a | out-file -FilePath $logfile -Append
and Here.
(Get-WmiObject Win32_Process -Computer $Servers |
Where-Object { $ProcessNames -contains $_.Name }).Terminate() | out-null
I am faced with the following error
Get-WmiObject : Access is denied. (Exception from HRESULT: 0x80070005
(E_ACCESSDENIED))
At C:\Users\first.last\Desktop\Kill All Traffic Managers.PS1:67 char:13
+ $EndCheck = Get-WmiObject Win32_Process -Computer $Servers |
+
What is the easiest way to enter the credentials?
Add this to your script and change usernname and P#ssw0rd
$account = "username"
$PASSWORD = ConvertTo-SecureString P#ssw0rd -AsPlainText -Force
$UNPASSWORD = New-Object System.Management.Automation.PsCredential $account, $PASSWORD
Also change your
Get-WmiObject Win32_Process -Computer $Servers`
for
Get-WmiObject Win32_Process -Computer $Servers -Credential $UNPASSWORD

Powershell Wait-process until installation complete [duplicate]

As part of a backup operation, I am running the 7zip command to compress a folder into a single .7z file. No problems there as I am using the InVoke-WMIMethod.
Example:
$zip = "cmd /c $irFolder\7za.exe a $somedirectory.7z $somedirectory"
"InVoke-WmiMethod -class Win32_process -name Create -ArgumentList $zip -ComputerName $remotehost"
My problem comes in as my script continues, the 7za.exe process hasn't completed. I am then attempting to copy the item off of the remote system and it is either incomplete or fails.
Can someone point me in the direction to figure out how to identify if the 7za.exe process is still running, wait until it is dead, then proceed with the rest of my script?
I can grasp pulling the process from the remote system via...
get-wmiobject -class Win32_Process -ComputerName $remotehost | Where-Object $_.ProcessName -eq "7za.exe"}
Not sure how to turn that into usable info for my issue.
Answer UPDATE: (thx to nudge by #dugas)
This will do it with some feedback for those that need it...
do {(Write-Host "Waiting..."),(Start-Sleep -Seconds 5)}
until ((Get-WMIobject -Class Win32_process -Filter "Name='7za.exe'" -ComputerName $target | where {$_.Name -eq "7za.exe"}).ProcessID -eq $null)
You can invoke the Wait-Process cmdlet on the remote computer with the Invoke-Command cmdlet. Example:
$process = Invoke-WmiMethod -Class Win32_Process -Name create -ArgumentList notepad -ComputerName RemoteComputer
Invoke-Command -ComputerName RemoteComputer -ScriptBlock { param($processId) Wait-Process -ProcessId $processId } -ArgumentList $process.ProcessId
Since you mentioned using Invoke-Command is not an option, another option is polling.
Example:
$process = Invoke-WmiMethod -Class Win32_Process -Name create -ArgumentList notepad -ComputerName hgodasvccr01
$processId = $process.ProcessId
$runningCheck = { Get-WmiObject -Class Win32_Process -Filter "ProcessId='$processId'" -ComputerName hgodasvccr01 -ErrorAction SilentlyContinue | ? { ($_.ProcessName -eq 'notepad.exe') } }
while ($null -ne (& $runningCheck))
{
Start-Sleep -m 250
}
Write-Host "Process: $processId is not longer running"
You should be able to do it with a do... while loop that just sleeps until the process is finished.
do {
"waiting"
start-sleep 10
} while (gwmi -class win32_process -ComputerName $remotehost | Where ProcessName -eq "7za.exe")

Stopping & Restarting Services Remotely Using Set-Service

I've got a list of 10-15 services that I routinely need to restart on 6 servers. I have a script that calls a list of services, then calls a list of the servers, and then stops all the services:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Set-Service -Status Stopped
I then have another separate script to start them up again:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Set-Service -Status Running
I've checked around and can't seem to find a way of putting this into a single script. As I understand, Set-Service only has the ability to Stop, Start & Pause services, not restart them at the same time.
Any ideas? I might be missing something completely obvious.
To restart services simply use Restart-Service:
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
Get-Service -Name $Services -ComputerName $Machines | Restart-Service
Since according to the comments PowerShell v6 has removed support for remote access from the *-Service cmdlets you need to resort to Invoke-Command for remote execution when running v6 or newer, like this:
Invoke-Command -Computer $Machines -ScriptBlock {
Get-Service -Name $using:Services -ErrorAction SilentlyContinue |
Restart-Service
}
or like this:
Invoke-Command -Computer $Machines -ScriptBlock {
Restart-Service $using:Services -ErrorAction SilentlyContinue
}
Another option would be WMI:
$fltr = ($Services | ForEach-Object { 'Name="{0}"' -f $_ }) -join ' or '
Get-WmiObject Win32_Service -Computer $Machines -Filter $fltr | ForEach-Object {
$_.StopService()
$_.StartService()
}
I am with Ansgar, this should work
$Services = Get-Content -Path "C:\Powershell\Services.txt"
$Machines = Get-Content -Path "C:\Powershell\Machines.txt"
foreach ($service in $services){
foreach ($computer in $Machines){
Invoke-Command -ComputerName $computer -ScriptBlock{
Restart-Service -DisplayName $service}
}
}
it is a little messy but should give you a starting point
Sorry I forgot to take time to explain what is going on, so you import each of your txt docs and then it will process for each service and each computer and restart the services.
You can try this single liner command:
Get-Content .\services.txt | %{Get-WmiObject -Class Win32_Service -ComputerName (Get-Content .\computers.txt) -Filter "Name='$_'"} | %{$_.StopService()}; Get-Content .\services.txt | %{Get-WmiObject -Class Win32_Service -ComputerName (Get-Content .\computers.txt) -Filter "Name='$_'"} | %{$_.StartService()}

Powershell - Check on Remote Process, if done continue

As part of a backup operation, I am running the 7zip command to compress a folder into a single .7z file. No problems there as I am using the InVoke-WMIMethod.
Example:
$zip = "cmd /c $irFolder\7za.exe a $somedirectory.7z $somedirectory"
"InVoke-WmiMethod -class Win32_process -name Create -ArgumentList $zip -ComputerName $remotehost"
My problem comes in as my script continues, the 7za.exe process hasn't completed. I am then attempting to copy the item off of the remote system and it is either incomplete or fails.
Can someone point me in the direction to figure out how to identify if the 7za.exe process is still running, wait until it is dead, then proceed with the rest of my script?
I can grasp pulling the process from the remote system via...
get-wmiobject -class Win32_Process -ComputerName $remotehost | Where-Object $_.ProcessName -eq "7za.exe"}
Not sure how to turn that into usable info for my issue.
Answer UPDATE: (thx to nudge by #dugas)
This will do it with some feedback for those that need it...
do {(Write-Host "Waiting..."),(Start-Sleep -Seconds 5)}
until ((Get-WMIobject -Class Win32_process -Filter "Name='7za.exe'" -ComputerName $target | where {$_.Name -eq "7za.exe"}).ProcessID -eq $null)
You can invoke the Wait-Process cmdlet on the remote computer with the Invoke-Command cmdlet. Example:
$process = Invoke-WmiMethod -Class Win32_Process -Name create -ArgumentList notepad -ComputerName RemoteComputer
Invoke-Command -ComputerName RemoteComputer -ScriptBlock { param($processId) Wait-Process -ProcessId $processId } -ArgumentList $process.ProcessId
Since you mentioned using Invoke-Command is not an option, another option is polling.
Example:
$process = Invoke-WmiMethod -Class Win32_Process -Name create -ArgumentList notepad -ComputerName hgodasvccr01
$processId = $process.ProcessId
$runningCheck = { Get-WmiObject -Class Win32_Process -Filter "ProcessId='$processId'" -ComputerName hgodasvccr01 -ErrorAction SilentlyContinue | ? { ($_.ProcessName -eq 'notepad.exe') } }
while ($null -ne (& $runningCheck))
{
Start-Sleep -m 250
}
Write-Host "Process: $processId is not longer running"
You should be able to do it with a do... while loop that just sleeps until the process is finished.
do {
"waiting"
start-sleep 10
} while (gwmi -class win32_process -ComputerName $remotehost | Where ProcessName -eq "7za.exe")