Invoke-command and msiexec - powershell

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
}
}

Related

wmi accelerator and authentication

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

Powershell remote-query for Server 2003's eventlog

Is there any way to remotely query the events on 2003 server thru Powershell.
Get-eventlog doesn't have a -credential switch and get-winevent doesn't work on Server 2003.
I even tried the impersonation module. It works with commands like get-service, get-process, get-counter but not with get-wmiobject or get-eventlog. Am I missing something.
You are probably looking for this:
Get-WmiObject Win32_NTLogEvent -ComputerName $compName -Credential $cred
gm results of Get-WmiObject for Win32_NTLogEvent (yes, it can take a while to produce):
You can use for filtering (i.e. add -filter "(TimeWritten>'$BeginDate')" to gwmi command), don't forget to assign $BeginDate variable prior to that. See these:
get-wmiobject to pull logs using Win32_NTLogEvent
Early Filtering of Win32_NTLogEvent class
Wrap your Get-EventLog command within an Invoke-Command script block.

Installing Windows Features on remote server 2012 using powershell 3.0

I am wondering which is best practice considering both examples will probably work. Using the built in help examples I have written a script to install windows features on remote servers. Here is my code:
$servers = ('server1', 'server2', 'server3', 'server4')
ForEach ($server in $servers) {
Install-WindowsFeature -Name Desktop-Experience -ComputerName $server -IncludeAllSubFeature -IncludeManagementTools -Restart
}
Would the above be preferred OR should I wrap the "Install-WindowsFeature ..." in an "Invoke-Command" block like the following?
Invoke-Command -ComputerName server1, server2, server3, server4 -command {
Install-WindowsFeature -Name Desktop-Experience -ComputerName $server -IncludeAllSubFeature -IncludeManagementTools -Restart
}
Thanks for your insight!
Personally I would use the latter (directly call Install-WindowsFeature -ComputerName $server rather than do a separate Invoke-Command) in this case for the following reasons:
You may be hard-coding the feature names now, but in the future you may want to put those in a variable. If you put them in a variable, you'll have to pass it as a parameter into the Invoke-Command's script block. This is entirely possible, but more work.
By using your own loop, you can write progress messages, logging, etc.
You gain nothing by using Invoke-Command in this case because you're running a single command on the remote computer (as opposed to running multiple commands with -ComputerName parameters vs. running multiple commands inside the script block).

Powershell (Version 2.0) remote execution of services with credentials

I want to start/stop apache and mysql services on remote machine by using powershell version 2.0 (Windows Server 2008). I found syntax for remote execution as follow:
(Get-WmiObject -Computer myCompName Win32_Service -Filter "Name='myServiceName'").InvokeMethod("Stop-Service",$null)
But I have to provide credentials (DOMAIN_NAME\USERNANE and PASSWORD) also for this exceution. I am new to powershell and need help for correct syntax (example will be easy to understand and implement).
Get-WMIObject accepts the -Credential parameter. You shouldn't be keeping your credentials in plain text in your script, so you'll want to prompt for them.
$creds = get-credential;
(Get-WmiObject -Computer myCompName Win32_Service -Filter "Name='myServiceName'" -credential $creds).InvokeMethod("Stop-Service",$null)
If you have PSRemoting enabled on the remote system, you can do this without WMI.
$creds = get-credential;
Invoke-Command -computername myCompName -credential $creds -scriptblock {(get-service -name myServiceName).Stop()};
Update based on comments
Since you're running this as a scheduled job, you should not be storing or prompting for credentials at all. Configured the scheduled job itself (via Scheduled Tasks) to run under the required user account, then either of the following should work:
# Your original code
(Get-WmiObject -Computer myCompName Win32_Service -Filter "Name='myServiceName'").InvokeMethod("Stop-Service",$null)
# If you have remoting enabled
Invoke-Command -computername myCompName -scriptblock {(get-service -name myServiceName).Stop()};

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.