Execute drive cleanup command for remote server powershell - powershell

I have the below code for cleaning space in C drive. It is working fine locally but I have to execute it for remote servers
$ProcessInfo = New-Object -TypeName System.Diagnostics.ProcessStartInfo
$ProcessInfo.FileName = "$env:SystemRoot\system32\dism.exe"
$ProcessInfo.Arguments = "/Online /NoRestart /Cleanup-Image /StartComponentCleanup"
$ProcessInfo.UseShellExecute = $true
$ProcessInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Minimized
$Process.StartInfo = $ProcessInfo
$Process.Start() | Out-Null
Please let me know how to execute this for remote server using Invoke-command or some other way

Related

Powershell Admin rights dont work in Windows Forms

I want to add and remove user from the lokal Administrator group. Problem is that even I elevate rights in first place It still Access Denies me when I try to add them.
In a similar code It works this way... only thing I changed it that I created a GUI for it.
Here is the code:
$myWindowsID=[System.Security.Principal.WindowsIdentity]::GetCurrent()
$myWindowsPrincipal=new-object System.Security.Principal.WindowsPrincipal($myWindowsID)
$adminRole=[System.Security.Principal.WindowsBuiltInRole]::Administrator
if (!$myWindowsPrincipal.IsInRole($adminRole)){
start-process "powershell" -Verb "runas" -ArgumentList "-File",$MyInvocation.MyCommand.Definition
}
[VOID] [System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
[Void] [System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
$objForm = New-Object System.Windows.Forms.Form
$objForm.BackgroundImageLayout = 0
$objForm.BackgroundImage =[System.Drawing.Image]::FromFile('xx')
$objForm.StartPosition = "CenterScreen"
$objForm.Icon="xx"
$objForm.Size = New-Object System.Drawing.Size(400,200)
$objForm.Text = "Lokal Admin Adder v.01"
$objLabel = New-Object System.Windows.Forms.Label
$objLabel.Location = New-Object System.Drawing.Size(75,30)
$objLabel.Size = New-Object System.Drawing.Size(240,20)
$objLabel.Text = "Nutzernamen eingeben(m_mustermann)"
$objForm.Controls.Add($objLabel)
$objLabel2 = New-Object System.Windows.Forms.Label
$objLabel2.Location = New-Object System.Drawing.Size(280,140)
$objLabel2.Size = New-Object System.Drawing.Size(300,20)
$objLabel2.Text = "by Lucas Klarner"
$objForm.Controls.Add($objLabel2)
$objTextBox = New-Object System.Windows.Forms.TextBox
$objTextBox.Location = New-Object System.Drawing.Size(85,50)
$objTextBox.Size = New-Object System.Drawing.Size(200,20)
$objForm.Controls.Add($objTextBox)
$FinishButton = New-Object System.Windows.Forms.Button
$FinishButton.Location = New-Object System.Drawing.Size (20,80)
$FinishButton.Size = New-Object System.Drawing.Size (150,20)
$FinishButton.Text = "Nutzer hinzufügen"
$FinishButton.Name = "Nutzer hinzufügen"
$FinishButton.Add_Click({
$Usr = $objTextBox.Text; Add-LocalGroupMember -Group Administratoren -Member $Usr })
$objForm.Controls.Add($FinishButton)
$DeleteButton = New-Object System.Windows.Forms.Button
$DeleteButton.Location = New-Object System.Drawing.Size (210,80)
$DeleteButton.Size = New-Object System.Drawing.Size (150,20)
$DeleteButton.Text = "Nutzer entfernen"
$DeleteButton.Name = "Nutzer entfernen"
$DeleteButton.DialogResult = "OK"
$DeleteButton.Add_Click({
$Usr = $objTextBox.Text;Remove-LocalGroupMember -Group Administratoren -Member $Usr -Verbose })
$objForm.Controls.Add($DeleteButton)
[void] $objForm.ShowDialog()
Thanks a lot!!
FIXED:
Somehow my elevation code was not running correctly and I made a new one out of some internet posts:
if (-Not ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')) {
if ([int](Get-CimInstance -Class Win32_OperatingSystem | Select-Object -ExpandProperty BuildNumber) -ge 6000) {
$CommandLine = "-File `"" + $MyInvocation.MyCommand.Path + "`" " + $MyInvocation.UnboundArguments
Start-Process -FilePath PowerShell.exe -Verb Runas -ArgumentList $CommandLine
Exit
}
}
Here's how it works:
The first line checks to see if the script is already running in an elevated environment. This would occur if PowerShell is running as Administrator or UAC is disabled. If it is, the script will continue to run normally in that process.
The second line checks to see if the Windows operating system build number is 6000 (Windows Vista) or greater. Earlier builds did not support Run As elevation.
The third line retrieves the command line used to run the original script, including any arguments.
Finally, the fourth line starts a new elevated PowerShell process where the script runs again. Once the script terminates, the elevated PowerShell window closes.
https://blog.expta.com/2017/03/how-to-self-elevate-powershell-script.html

How to run Command as a different user with Powershell?

I'm trying to make a script that changes the HostnameAlias for a given dns record.
But only certain users have access to editing these records, for example ADMIN can edit it but CURRENTUSER cannot.
Currently I have this piece of code:
param(
[ValidateNotNull()]
[System.Management.Automation.PSCredential]
$Credential = $(Get-Credential)
)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
But i just keep getting Start-Process : This command cannot be run due to the error: The user name or password is incorrect even though I am absolutely sure they are indeed correct.
What am I doing wrong here.
Ps, I have looked at all the related questions, none seem to answer my question.
You can call System.Management.Automation.PSCredential object to specify any credentials you want and run with it in any process
$User = 'yourdomain\youruser'
$Password = 'yourpassword'
$Secure_Password = ConvertTo-SecureString $Password -AsPlainText -Force
$Credential = New-Object System.Management.Automation.PSCredential($User, $Secure_Password)
$Command = "Set-DnsServerResourceRecord -NewInputObject $($NewObject) -OldInputObject $($OldObject) -ZoneName $($ZoneName)"
Start-Process -FilePath PowerShell -NoNewWindow -Credential $Credential -ArgumentList $Command
You can use this:
#Get User credential
$Credential = Get-Credential Domain\UserNameYouWant
#Use System.Diagnostics to start the process as User
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
#With FileName we're basically telling powershell to run another powershell process
$ProcessInfo.FileName = "powershell.exe"
#CreateNoWindow helps avoiding a second window to appear whilst the process runs
$ProcessInfo.CreateNoWindow = $true
#Note the line below contains the Working Directory where the script will start from
$ProcessInfo.WorkingDirectory = $env:windir
$ProcessInfo.RedirectStandardError = $true
$ProcessInfo.RedirectStandardOutput = $true
$ProcessInfo.UseShellExecute = $false
#The line below is basically the command you want to run and it's passed as text, as an argument
$ProcessInfo.Arguments = "The command you want"
#The next 3 lines are the credential for User as you can see, we can't just pass $Credential
$ProcessInfo.Username = $Credential.GetNetworkCredential().username
$ProcessInfo.Domain = $Credential.GetNetworkCredential().Domain
$ProcessInfo.Password = $Credential.Password
#Finally start the process and wait for it to finish
$Process = New-Object System.Diagnostics.Process
$Process.StartInfo = $ProcessInfo
$Process.Start() | Out-Null
$Process.WaitForExit()
#Grab the output
$GetProcessResult = $Process.StandardOutput.ReadToEnd()
# Print the Job results
$GetProcessResult
Just a mistake on my part, forgot to specify domain before username when entering credentials.
Can solve it like this Get-Credential Domain\

Installing an exe with PowerShell DSC returns exit code only when run through LCM

I am trying to install the HPC Pack 2012 R2 U3 setup using PowerShell DSC. The following code works and installs the software:
$HpcPackName = "Microsoft HPC Pack 2012 R2 Server Components"
$HpcPackSourcePath = "C:\Temp\HPC2012R2_Update3_Full\setup.exe"
$sqlServer = "EMEAWINQA15"
$Arguments = "-unattend -headNode"
function InstallUsingProcess
{
[CmdletBinding()]
param()
Write-Verbose "HpcPackSourcePath: $HpcPackSourcePath"
Write-Verbose "Arguments: $Arguments"
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = $HpcPackSourcePath
$startInfo.Arguments = $Arguments
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$exitcode = 0
$process.Start() | Out-Null
$process.WaitForExit()
if($process)
{
$exitCode = $process.ExitCode
Write-Verbose "Exit code: $exitCode"
}
}
InstallUsingProcess -Verbose
However, when I run the same thing using a Script DSC configuration, it succeeds but returns very quickly with exit code 10:
Configuration TestHpcInstall
{
Import-DscResource –ModuleName PSDesiredStateConfiguration
Node $AllNodes.Where({$_.Roles -contains 'HpcHeadNode'}).NodeName
{
$HpcPackName = "Microsoft HPC Pack 2012 R2 Server Components"
$HpcPackSourcePath = "C:\Temp\HPC2012R2_Update3_Full\setup.exe"
$sqlServer = "EMEAWINQA15"
$Arguments = "-unattend -headNode"
Script TestInstall
{
GetScript = {
return #{ "Result" = "$true"}
}
TestScript = {
return $false
}
SetScript = {
Write-Verbose "HpcPackSourcePath: $using:HpcPackSourcePath"
Write-Verbose "Arguments: $using:Arguments"
$startInfo = New-Object System.Diagnostics.ProcessStartInfo
$startInfo.FileName = $using:HpcPackSourcePath
$startInfo.Arguments = $using:Arguments
$process = New-Object System.Diagnostics.Process
$process.StartInfo = $startInfo
$exitcode = 0
$process.Start() | Out-Null
$process.WaitForExit()
if($process)
{
$exitCode = $process.ExitCode
Write-Verbose "Exit code: $exitCode"
}
}
}
}
}
TestHpcInstall -ConfigurationData $configData -OutputPath "C:\Temp"
Start-DscConfiguration -ComputerName "EMEAWINQA15" -Path "C:\Temp\" -Verbose -Wait -Force
This is the same code used by the Package resource, which fails because error code 10 is returned instead of 0 (which is the case when the package installs successfully, as in the top-most code sample). The setup does not produce any output or log file.
Any ideas? I'm stumped.
I found the problem. I thought this had something to do with permissions because the setup gives a UAC elevation prompt when run normally. However, I had crossed it out before for two reasons:
LCM runs under NT AUTHORITY\SYSTEM account and is therefore an administrator, and
Because I supplied local administrator credentials to the Package resource already like so
(which didn't work):
Package InstallHpcHeadNode
{
Ensure = "Present"
Name = $HpcPackName
ProductId = ""
Path = $HpcPackSourcePath
Arguments = $Arguments
Credential = (Get-Credential)
}
But this was a mistake. From the docs, the Credential property says:
Provides access to the package on a remote source. This property is
not used to install the package.
which I'll admit I overlooked. I should have instead used the PsDscRunAsCredential property to force the installation using the supplied credentials. Still don't know why the installer doesn't run under NT AUTHORITY\SYSTEM though.

Remote desktop powershell indication

I'm trying to automate the remote desktop process (from windows client to windows server) for a service I'm working on.
To do so, I'm using the following Powershell script:
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
$Process = New-Object System.Diagnostics.Process
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\cmdkey.exe"
$ProcessInfo.Arguments = "/generic:TERMSRV/$ComputerCmdkey /user:$User /pass:$Password"
$ProcessInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Hidden
$Process.StartInfo = $ProcessInfo
if ($PSCmdlet.ShouldProcess($ComputerCmdkey,'Adding credentials to store')) {
[void]$Process.Start()
}
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\mstsc.exe"
$ProcessInfo.Arguments = "$MstscArguments /v $Computer"
$ProcessInfo.WindowStyle = [System.Diagnostics.ProcessWindowStyle]::Normal
$Process.StartInfo = $ProcessInfo
if ($PSCmdlet.ShouldProcess($Computer,'Connecting mstsc')) {
[void]$Process.Start()
}
This script works perfectly fine. What i'm missing is an indication on the client side (other than the UI window - some return value or event log) that can tell me whether the connection was successful or did it fail.
Can anyone here help with it?
Thanks

Trying to do mstsc remotely using powershell doesn't work

I have two server as X and Y. I have a powershell script that I am using for having a remote desktop of X on Y. The powershell script that I have to run on Y is --
$hostname = 'X'
$User = 'u-name'
$Password = 'password'
$ProcessInfo = New-Object System.Diagnostics.ProcessStartInfo
$Process = New-Object System.Diagnostics.Process
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\cmdkey.exe"
$ProcessInfo.Arguments = "/generic:TERMSRV/$hostname /user:$User /pass:$Password"
$Process.StartInfo = $ProcessInfo
$Process.Start()
$ProcessInfo.FileName = "$($env:SystemRoot)\system32\mstsc.exe"
$ProcessInfo.Arguments = "$MstscArguments /v $hostname"
$Process.StartInfo = $ProcessInfo
$Process.Start()
When I run this script locally on Y, it does run and opens the server X in Y.
But I want to trigger it from X only to open X in Y. So I Invoke this powershell script from X as --
$pass = ConvertTo-SecureString -AsPlainText test-password -Force
$cred = New-Object System.Management.Automation.PSCredential -ArgumentList test-uname,$pass
$hostn = hostname
$Use = 'u-name'
$Pass = 'password'
Write-Host "$hostname"
$ScriptBlockContent={
Param ($hostname,$User,$Password)
E:\Script\test.ps1 $hostname $User $Password}
Invoke-Command -ComputerName Y -Credential $cred -Scriptblock $ScriptBlockContent -ArgumentList $hostn,$Use,$Pass
When I am invoking this. It does open mstsc.exe on Y but only for some fraction of seconds and doesn't open the server X on Y. Can somebody please help.. !!
Thanks.
You are trying to launch an application with a GUI in a remote powershell session which has no desktop/display. Even if you use the credentials of a logged in user, the things you launch through Invoke-Command will not be visible to the logged-in user's session.
I think that this is possible with PsExec.exe, but I can't confirm.