wmi accelerator and authentication - powershell

It seems I can not find clearly written somewhere that when using WMI accelerator in a PowerShell script, you can not pass on authentication.
A little background ...
I am writing PowerShell scripts for SCCM 2012 and found, for instance, the following quite using :
PS R:\> ([wmi]((gwmi -namespace root\sms\site_AAA -class SMS_Application -filter
"LocalizedDisplayName LIKE '%Winzip_Tartempion%'")
.__PATH)).SDMPackageXML
When executed locally (on the SCCM primary server, it works fine and swiftly.
However, the following ends up in error when executed from my desktop computer running W7 :
PS R:\> ([wmi]((gwmi -namespace root\sms\site_AAA -credential $cred
-ComputerName CEMTECH
-class SMS_Application -filter "LocalizedDisplayName LIKE
'%Winzip_Tartempion%'")
.__PATH)).SDMPackageXML
For the time being, using a PSSession is out of the question.
With the current infrastructure I have to deal with, using SCCM commandlet is out of the question.
My only question here is : can you confirm that we can not pass any authentication with a WMI accelerator ? At that point, I am searching for that answer mainly for my curiosity. I found a way to manage with my current constraints. It is just that I find the accelerators so "elegant".
Now why do I need it ? I need to access "lazy properties" without using SCCM cmdlets, from a desktop computer to which the user is logged on with an account which will not be the same as the name authorized to connect/access the SCCM primary server.
What I still did not find is how to use "*.__PATH" with the Get-WMIObject cmdlet.

The WMI-accelerator [wmi] doesn't support alternate credentials.
Why do you need it? You could just run:
$obj = Get-WmiObject -namespace root\sms\site_P41 -credential $cred -ComputerName qs07352 -class SMS_Application -filter "LocalizedDisplayName LIKE '%Winzip_Tartempion%'"
$obj.Get()
$obj.SDMPackageXML

Related

Invoke-command and msiexec

I'm trying to remove an application on a remote machine using the Invoke-Command cmdlet but it's not working.
Here is my script:
Invoke-Command -ComputerName "Computername" -Verbose -ScriptBlock {
msiexec.exe /x '{4ADBF5BE-7CAF-4193-A1F9-AM6820E68569}' /qn /passive
}
Are there any reliable, working alternatives in this context?
This doesn't use Invoke-Command or MSIExec, but it's a functional uninstall method for removing applications on remote machines using WMI for anything registered with WMI (should be anything installed via msiexec).
(Get-WmiObject -Class Win32_product -ComputerName ComputerName -Filter {IdentifyingNumber LIKE '{4ADBF5BE-7CAF-4193-A1F9-AM6820E68569}'}).uninstall()
Additionally that can be put into a ForEach loop if you have several computers to do it on. If you have the Name, IdentifyingNumber, and Version listed in WMI you can make it much faster with the following context (using AT&T Connect Participant Application v9.0.82):
$App="IdentifyingNumber=`"`{1F3A6960-8470-4C84-820C-EBFFAF4DA580`}`",Name=`"AT&T Connect Participant Application v9.0.82`",version=`"9.0.82`""
([WMI]\\ComputerName\root\cimv2:Win32_Product.$App).Uninstall()
Yes, the $App string is horribly escaped, but that's due to the way WMI requires the string to be formatted with curly braces and double quotes and what not. This is not exactly useful for a single uninstall since it requires you to get all that info up front and format the key string. If you were going to remove a piece of software off 30 machines though, it would be much better. You can get all that info by just leaving off the .Uninstall() method from my first command, so...
Get-WmiObject -Class Win32_product -ComputerName RemoteComputer -Filter {IdentifyingNumber LIKE '{1F3A6960-8470-4C84-820C-EBFFAF4DA580}'}
Will spit back something like:
IdentifyingNumber : {1F3A6960-8470-4C84-820C-EBFFAF4DA580}
Name : AT&T Connect Participant Application v9.0.82
Vendor : AT&T Inc.
Version : 9.0.82
Caption : AT&T Connect Participant Application v9.0.82
Can also be used with the name, or even partial names by changing the filter to something like `{Name LIKE '%AT&T Connect%'} or you can query WMI to list all the applications registered with it by leaving the -Filter off completely, though you probably want to pipe that to Format-Table to make it readable. I used:
gwmi -class win32_product -computername RemoteComputer|ft IdentifyingNumber,Name,Version
A good read with more info about this can be found at this link
Here is the solution I came up with
$myses = New-PSSession -ComputerName "Computer"
Invoke-Command -Session $myses -ScriptBlock {
#finds all instances of Java installed
$find_sep = gwmi win32_product -filter "Name LIKE '%Java%'" | select -ExpandProperty IdentifyingNumber
foreach($i in $find_sep){
msiexec.exe /x $i /qn /passive /l*v! c:\uninst.log
}
}

New-PsDrive Remote copy from DFS share errors: A specified logon session does not exist

So to recap the situation: I am at one computer trying to run powershell using enter-pssession computername, then from the remote session, run the logic below:
$DFSPath = "\\DFSpath.com"
$RDL1 = [char](1+[char](gdr ?)[-1].name)
New-PSDrive -Name $RDL1 -PSProvider FileSystem -Root $DFSPath -Persist -credential domain\UN
The get-variable shows the variables properly. But when I try to create with New-PSDrive, it gives:
New-PSDrive : A specified logon session does not exist. It may already have
been terminated
I did look at this: PowerShell 2.0: Accessing Windows Shares during a Remote Session but wasn't able to get it to work. Also I wouldn't know how to devise it in my script above (which will be run on multiple computers). Is there anything newer? I am using v3 powershell. Thanks so much!
From the looks of things it appears that you are experiencing the dreaded "Double-Hop". If you only what to remote to a few computers it's pretty easy to setup the "fix" for the "Double-Hop". On the computers that you want to remote to you need to run the following commands:
Enable-PSRemoting
Enable-WSManCredSSP Server
Then on the computer you want to remote from you need to run the command:
Enable-WSManCredSSP Client –DelegateComputer [<FQDN of the server>][*]
In place of the fully qualified domain name you can put a * instead. That will allow you to send your credentials to any computer (that could be dangerous).
Now how would you work this into a script? There is a command called Invoke-Command. If you look at the parameters of Get-Help Invoke-Command -Parameter *, you'll see that it take a Credential and a Authentication. Here's how you would run a command on multiple computers.
$MyCred = Get-Credential
Invoke-Command -ComputerName Computer1,Computer2 -Credential $MyCred -Authentication Credssp -ScriptBlock {Get-ChildItem $args[0]} -ArgumentList '\\Server\Share' -ErrorAction SilentlyContinue
Now if you'll be remoting onto many machines and you know how to use Group Policy. I'd recommend setting up PSRemoting and enabling WSManCred with the Group Policy.

How to deactivate Windows Remote-Desktop with Powershell?

All our testboxes run on VMs (windows server 2003/08) and testers access them via remote desktop only.
Some maintenance steps require to kick all users from the system and deactivate access via remote desktop.
I started to write the maintenance scripts in powershell and am looking for a way to temporarily deactivate remote desktop. Is that possible, any straight-forward solutions to this?
What I have tried so far:
A colleague recommended turning-off the netlogon-service, but I can
still logon with remote-desktop.
Another colleague recommended disabling blocking the port for
remote-desktop with the firewall, but somehow that does not feel
right to me (?) because I don't want to change one part of a system
to affect another part. Am I too picky ... ? ;)
Any hints highly appreciated.
Cheers,
Tobi
You need to set
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Terminal Server\fDenyTSConnections
value to 1 by default to disable remote desktop but needs to reboot.
Another way that seem not needing reboot (NOT TESTED):
$ts=get-WMIObject Win32_TerminalServiceSetting -computername remotemachinename
$ts.SetAllowTSConnections(0)
Now I have found a solution that works perfect for me. Windows Server 2008 comes with a feature called "Terminal Services Server Drain Mode"
... the TS Server Drain Mode prevents new users from logging onto the server, while allowing currently logged on users to reconnect to their existing sessions. By waiting for existing users to save their work and log off, the administrator can take a terminal server down for maintenance without causing user data loss.
Before I activate the drain mode I ensure that no one is logged in and then I active the drain mode with the following code:
Invoke-Command -ComputerName myServerHostName -ScriptBlock
{
Set-ItemProperty -Path "HKLM:\SYSTEM\Currentcontrolset\control\Terminal Server" -Name TSServerDrainMode -Value 1
}
Although I am changing a registry key, I am not required to reboot the server for the changes to be effective. This works without a reboot.
When I am done performing maintenance work I deactive drain mode with "-Value 0" and users are able to log in again.
Works like a charm!
My original answer was:
My perferred solution that I have found through extensive web search is as follows (also untested):
$Terminal = Get-WmiObject Win32_Terminal –Computer “ComputerName”
$Terminal.Enable($True)
Other possible and interesting code snippets, or variations on the topic, that I have found:
$myWmiObject = Get-WmiObject -namespace “rootCIMV2TerminalServices” -class Win32_Terminal -Computer “ComputerName” -Authentication PacketPrivacy
or
Set-WmiInstance -namespace “rootCIMV2TerminalServices” -class Win32_Terminal -ComputerName “ComputerName” -Authentication PacketPrivacy -Argument #{fEnableTerminal=0}
or
Get-WmiObject -ComputerName “ComputerName” -namespace root/cimv2/terminalservices -class Win32_Terminal -Authentication PacketPrivacy
I use this gWmi code frequently :
#Remote change logon /disable
$TS_Connector = gwmi Win32_TerminalServiceSetting -N "root/cimv2/terminalservices" -computername $ServerName -Authentication PacketPrivacy
$TS_Connector.Logons=1
$TS_Connector.Put()
and for enable logons
#Remote change logon /enable
$TS_Connector = gwmi Win32_TerminalServiceSetting -N "root/cimv2/terminalservices" -computername $ServerName -Authentication PacketPrivacy
$TS_Connector.Logons=0
$TS_Connector.Put()
instead of Invoke-command() because nead RCP openned, and RPC connexion are disabled by default on windows
Looking for something else this morning (coincidentally) I saw this: "Checking and enabling Remote Desktop with PowerShell".
Summary: involves registry manipulation.

Enabling Enable-PSRemoting on Powershell 1.0

This is in relation to http://www.computerperformance.co.uk/powershell/powershell_remote.htm . Currently, most of the machines in my Test environment are on Powershell 1.0. Under such a scenario, is there a way by which I can still manage to make remote calls via Powershell from one machine to another.
My ultimate motive is to start/stop/restart a windows service remotely using Powershell.
You're not going to be able to use PowerShell Remoting in 1.0, but you can use WMI or .Net ServiceController for this task.
$S = Get-WmiObject -Computer $Server -Class win32_service -filter "name='$ServiceName'"
$S.StopService()
$S.StartService()
In fact, if you have 2.0 on the client you're on, you can skip a couple of steps versus the way it's written on either of those posts by using Invoke-WMIMethod:
Invoke-WMIMethod -Name StopService -Computer $Server -Class win32_service -filter "name='$ServiceName'"
Invoke-WMIMethod -Name StartService -Computer $Server -Class win32_service -filter "name='$ServiceName'"
Note: for general remoting, you could set up an SSH server on each box and remote in that way (and set up PowerShell as the default shell), /n software has a pre-built solution around that.

Changing account name and password on Windows Services remotely

I need to write a program / script to change the account name and password on certain services running on a remote server. I intend to do it with Powershell. Is that the best solution or is there something else that would be more suitable?
A quick google search brought up this script:
$account="domain\userName"
$password="password"
$svc=gwmi win32_service -filter "name='alerter'"
$svc.change($null,$null,$null,$null,$null,$null,$account,$password,$null,$null,$null)
Am I mistaken in thinking the above script works on the local machine? If that is true, how do I do the same for a service on a remote machine?
The command is running on your local machine. Use the -ComputerName parameter to run it on remote systems.
$svc=gwmi win32_service -filter "name='alerter'" -ComputerName Server1,Server2