Run remote PowerShell Office uninstallation script - powershell

KB2956128 is causing headache for users in my network. I do not run WSUS in this environment so I was going to employ PS script to take care of uninstallation.
By all means the script below should work
$comp = 'PC03'
$scrblock =
{
$TitlePattern = 'KB2956128'
$Session = New-Object -ComObject Microsoft.Update.Session
$Collection = New-Object -ComObject Microsoft.Update.UpdateColl
$Installer = $Session.CreateUpdateInstaller()
$Searcher = $Session.CreateUpdateSearcher()
$Searcher.QueryHistory(0, $Searcher.GetTotalHistoryCount()) |
Where-Object { $_.Title -match $TitlePattern } |
ForEach-Object {
Write-Verbose "Found update history entry $($_.Title)"
$SearchResult = $Searcher.Search("UpdateID='$($_.UpdateIdentity.UpdateID)' and RevisionNumber=$($_.UpdateIdentity.RevisionNumber)")
Write-Verbose "Found $($SearchResult.Updates.Count) update entries"
if ($SearchResult.Updates.Count -gt 0) {
$Installer.Updates = $SearchResult.Updates
$Installer.Uninstall()
$Installer | Select-Object -Property ResultCode, RebootRequired, Exception
# result codes: http://technet.microsoft.com/en-us/library/cc720442(WS.10).aspx
}
}
}
Invoke-Command -ComputerName $comp -ScriptBlock $scrblock -Credential 'myDomain\administrator'
Instead I get this error
Exception calling "CreateUpdateInstaller" with "0" argument(s): "Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))"
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
+ PSComputerName : PC03
Exception calling "QueryHistory" with "2" argument(s): "Exception from HRESULT: 0x80240007"
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ComMethodTargetInvocation
+ PSComputerName : PC03
I don't quite understand why the access is denied. Any ideas?

Short answer is that the ComObject does not allow the CreateUpdateInstaller to be called remotely. You can only do this locally, not over sessions or any other remoting. You can however use psexec to remotely execute your script as system.

Related

PowerShell remoting to execute Windows update

I need to modify the below script to execute the Windows Update so it downloads and updates the remote server:
Invoke-RemoteExecution($computername){
$cred = get-credential
invoke-command -computername $computername -Credential $cred -scriptblock {
Function Search-Updates
{
$Criteria = "IsInstalled=0 and Type='Software'"
#Search for relevant updates.
$Searcher = New-Object -ComObject Microsoft.Update.Searcher
$SearchResult = $Searcher.Search($Criteria).Updates
return [System.MarshalByRefObject]$SearchResult
}
Function Download-Updates
{
Param ($SearchResult)
$Session = New-Object -ComObject Microsoft.Update.Session
$Downloader = $Session.CreateUpdateDownloader()
$Downloader.Updates = $SearchResult
$Downloader.Download()
}
[System.MarshalByRefObject]$SearchResult = Search-Updates
Download-Updates -SearchResult $SearchResult
}
}
Invoke-RemoteExecution -computername yourcomputername
The error I am facing is like the below:
Invoke-RemoteExecution -computername PRD-SVR01-VM
cmdlet Get-Credential at command pipeline position 1
Supply values for the following parameters:
Access is denied. (Exception from HRESULT: 0x80070005 (E_ACCESSDENIED))
+ CategoryInfo : OperationStopped: (:) [], UnauthorizedAccessException
+ FullyQualifiedErrorId : System.UnauthorizedAccessException
+ PSComputerName : PRD-SVR01-VM
The property 'Updates' cannot be found on this object. Verify that the property exists and can be set.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
+ PSComputerName : PRD-SVR01-VM
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
+ PSComputerName : PRD-SVR01-VM
I have tried to use the remoting but it is still failed as above.

Upload file to SharePoint

I would like to create a program in PowerShell to upload files to Sharepoint on schedule (using Task Scheduler)
I was looking for solution and I found this interesting article.
Based on this I wrote this script below:
Import-Module Microsoft.Online.Sharepoint.Powershell -DisableNameChecking;
(System.Reflection.Assembly)::LoadWithPartialName("System.IO.MemoryStream")
Clear-Host
$cred = Get-Credential "emailaddress#domain.com"
$credentials = New-Object Microsoft.SharePoint.Client.SharePointOnlineCredentials($cred.Username, $cred.Password)
$clientContext = New-Object Microsoft.SharePoint.Client.ClientContext("https://")
$clientCOntext.Credentials = $credentials
if (!$clientContext.ServerObjectIsNull.Value) {Write-host "Connected to site" -ForegroundColor Green}
Function UploadFileToLibrary(){
$docLib - $clientContext.Web.Lists.GetByTitle("IT Documents");
$clientContext.Load($docLib);
$clientContext.ExecuteQuery();
$rootFolder = $docLib.RootFolder
$Folder = "\\10.x.x.x\xpbuild$\IT\Level0\scresult\Upload";
$FilesInRoot = Get-ChildItem - Path $Folder | ? {$_.psIsContainer -eq $False}
Foreach ($File in ($FilesInRoot))
{
$startDTM = (Get-Date)
}Write-Host "Uploading File" $File.Name "to" $docLib.Title -ForegroundColor Blue
UploadFile $rootFolder $File $false
$endDTM = (Get-Date)
Write-Host "Total Elapsed Time : $(($endDTM-$startDTM).totalseconds) seconds"
}
Function UploadFile ($SPListFolder, $File, $CheckInRequired){
$FileStream = New-Object IO.FileStream($File.FullName,[System.IO.FileMode]::Open)
$FileCreationInfo = New-Object Microsoft.SharePoint.Client.FileCreationInformation
$FileCreationInfo.Overwrite = $True
$FileCreationInfo.ContentStream = $FileStream
$FileCreationInfo.Url = $File
$UploadedFile = $SPListFolder.Files.Add($FileCreationInfo)
If($CheckInRequired){
$clientContext.Load($UploadedFile)
$clientContext.ExecuteQuery()
If($uploadedFile.CheckOutType -ne "none"){
$UploadedFile.CheckIn("Checked in by Administrator", [Microsoft.SharePoint.Client.CheckinType]::MajorCheckIn)
}
}
$clientContext.Load($UploadedFile)
$clientContext.ExecuteQuery()
}
UploadFileToLibrary
When I tried to execute this I see that connection is active but I got an error:
Method invocation failed because [Microsoft.SharePoint.Client.List] does not contain a method named 'op_Subtraction'.
At C:\PowerShell\UploadSharepoint.ps1:11 char:1
+ $docLib - $clientContext.Web.Lists.GetByTitle("IT Documents");
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (op_Subtraction:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
Cannot find an overload for "Load" and the argument count: "1".
At C:\PowerShell\UploadSharepoint.ps1:12 char:1
+ $clientContext.Load($docLib);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodException
+ FullyQualifiedErrorId : MethodCountCouldNotFindBest
Exception calling "ExecuteQuery" with "0" argument(s): "List 'IT Documents' does not exist at site with URL 'https://'."
At C:\PowerShell\UploadSharepoint.ps1:13 char:1
+ $clientContext.ExecuteQuery();
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : ServerException
I cannot tell if any new problem occur once you fix that one, but given that the 2nd and 3rd error is caused by incorrect assignment of $docLib variable, changing - to =should resolve these three:
HERE |
$docLib = $clientContext.Web.Lists.GetByTitle("IT Documents");
# Below uses $docLib so it cannot be executed properly unless $docLib is assigned correct value
$clientContext.Load($docLib);
# And below fails as the above is not executed successfully
$clientContext.ExecuteQuery();

How to reset a Domain User Password with Remote Powershell

I want to reset my own Active Directory Password on a remote Machine (different domain).
If I use the following code snippet locally it works perfectly:
param(
[string]$oldPassword = $(Read-Host "Old password"),
[string]$newPassword = $(Read-Host "New password")
)
$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
$user = [ADSI] "LDAP://$($type.InvokeMember('UserName', 'GetProperty', $null, $ADSystemInfo, $null))"
$user.ChangePassword($oldPassword, $newPassword)
Running following snippet on the remote machine fails:
$ADSystemInfo = New-Object -ComObject ADSystemInfo
$type = $ADSystemInfo.GetType()
Invoke-Command -Session $Session -ScriptBlock {
param($rtype, $RemoteADSystemInfo, $OldPassword)
$user = [ADSI] "LDAP://$($rtype.InvokeMember('UserName', 'GetProperty', $null, $RemoteADSystemInfo, $null))"
$user.ChangePassword($OldPassword , "TestPa$$w0rd"")
} -ArgumentList $type,$ADSystemInfo,$Password
Error Message: Method invocation failed because
[Deserialized.System.RuntimeType] does not contain a method named
'InvokeMember'.
+ CategoryInfo : InvalidOperation: (InvokeMember:String) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound
+ PSComputerName : test.test.domain The following exception occurred while retrieving member "ChangePassword": "Unknown error (0x80005000)"
+ CategoryInfo : NotSpecified: (:) [], ExtendedTypeSystemException
+ FullyQualifiedErrorId : CatchFromBaseGetMember
+ PSComputerName : test.test.domain

PowerShell 3.0 behavior when getting external process exit code

I have been using this code from another post from this site:
$pinfo = New-Object System.Diagnostics.ProcessStartInfo
$pinfo.FileName = "notepad.exe"
$pinfo.RedirectStandardError = $true
$pinfo.RedirectStandardOutput = $true
$pinfo.UseShellExecute = $false
$pinfo.Arguments = ""
$p = New-Object System.Diagnostics.Process
$p.StartInfo = $pinfo
**$p.Start() | Out-Null**
#Do Other Stuff Here....
**$p.WaitForExit()**
$p.ExitCode
It has worked fine under PowerShell 2.0. The server was upgraded to PowerShell 3.0, and now the two bold like fail with:
Exception calling "Start" with "0" argument(s): "The system cannot find the
file specified"
At \\asdnsom3978\optim_windows\script_master\exportall.ps1:126 char:1
+ $p.Start() | Out-Null
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Exception calling "WaitForExit" with "0" argument(s): "No process is
associated with this object."
At \\asdnsom3978\optim_windows\script_master\exportall.ps1:128 char:1
+ $p.WaitForExit()
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : InvalidOperationException
Why did it broke and how do I correct it so it works for both version 2.0 and 3.0?
Hmm, I can't repro the error on my V3 system. But why are you going to all this trouble when you can just use the Start-Process command to do this e.g.:
$p = Start-Process Notepad -Wait -PassThru
$p.ExitCode
You might want to try providing a fully-qualified path to notepad.exe, like "C:\Windows\notepad.exe".

powershell invoke-command does not work if I use -computerName

I want to execute below code in the either local or remote machine whith current user.
$BackUpSqlAgentAndRemoveOldbackup = {
param([string]$AppServer,[string]$SqlInstance,[string]$BackupShare,[string]$alias)
[Environment]::UserName #I got same user name in all cases.
[System.Reflection.Assembly]::LoadWithPartialName('Microsoft.SqlServer.Smo') | Out-Null
$server = New-Object ('Microsoft.SqlServer.Management.Smo.Server') $SqlInstance
$backupName = 'SqlAgentJob_' + $SqlInstance + '_' + (Get-Date –format ‘yyyyMMdd_HHmm’) + '_' + $alias + '.sql'
$backupPath = join-path $BackupShare $backupName
$oldBackups = Get-ChildItem $backupShare | where { ( $_.name -like 'SqlAgentJob_*.sql' ) }
$server.JobServer.Jobs.Script() | Out-File -filepath $backupPath
foreach ( $item in $oldBackups ) { remove-item $item.fullName }
}
the #argList is
#('hafcapp-1', 'hafcsql-1', '\\Host5FileSrv\Backup\test','auto')
I notice that
this one, it works well (no -comupterName and -session)
Invoke-Command -ScriptBlock $BackUpSqlAgentAndRemoveOldbackup -argumentList $argList
this one, it throw execption (I also tried "-session", get same result)
Invoke-Command -computerName localhost -ScriptBlock $BackUpSqlAgentAndRemoveOldbackup -argumentList $argList
the exception is as below, it seems the it can not access the folder.
Cannot find path '\\Host5FileSrv\Backup\test' because it does not exist.
+ CategoryInfo : ObjectNotFound: (\\Host5FileSrv\Backup\test:String) [Get-ChildItem], ItemNotFoundException
+ FullyQualifiedErrorId : PathNotFound,Microsoft.PowerShell.Commands.GetChildItemCommand
You cannot call a method on a null-valued expression.
+ CategoryInfo : InvalidOperation: (Script:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
Cannot bind argument to parameter 'Path' because it is null.
+ CategoryInfo : InvalidData: (:) [Remove-Item], ParameterBindingValidationException
+ FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,Microsoft.PowerShell.Commands.RemoveItemCommand
does anyone know how can I do if I want to add computerName or session?
(notes:[Environment]::UserName return identical user)
You have run into the double hop problem. Your credentials can be transferred to the next machine (first hop), but no further (second hop). This means that you can't use the credentials of the machine where you are executing Invoke-Command on, the remote machine (localhost) to connect to a file share (\Host5FileSrv\Backup). Even if you use localhost as computername, it is still remoting. A solution could be CredSSP. See here and here for more information.
This looks like a "second hop" remoting problem, and you'll need to configure WinRM on the computers involved to use CredSSP
http://msdn.microsoft.com/en-us/library/windows/desktop/ee309365(v=vs.85).aspx