I am trying to use the following code to make a beep on a remote computer through Powershell:
Invoke-WmiMethod -Path Win32_Process -Name Create -ArgumentList "[console]::beep(500,300)" -ComputerName "mycompname"
In addition I have used [System.Media.SystemSounds]::Beep.Play() in place of the console command.
It doesn't give any error codes and outputs this:
__GENUS : 2
__CLASS : __PARAMETERS
__SUPERCLASS :
__DYNASTY : __PARAMETERS
__RELPATH :
__PROPERTY_COUNT : 2
__DERIVATION : {}
__SERVER :
__NAMESPACE :
__PATH :
ProcessId :
ReturnValue : 9
PSComputerName :
I am running this command with elevated Powershell and I am an admin on the network. Using Invoke-Command DOES NOT work on my computer, so I am opting for Invoke-WmiMethod instead. The following code DOES actually work, so I don't understand why the beep one won't:
Invoke-WmiMethod -path Win32_Process -Name Create -ArgumentList "msg * 'hello'" -ComputerName "mycompname"
Final notes: I would like to be able to use Invoke-WmiMethod to do remote shutdown and taskkill, but those functions also do not work, only sending a message works. Any help would be greatly appreciated.
May be can you try this (modify username and password)
$Username = 'labuser'
$Password = 'labuser'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
Invoke-command –computername "mycompname" -credential $Cred –scriptblock {[console]::beep(500,300)}
TessellatingHeckler was right. I just needed to change the code so that the receiving computer knows that I am using powershell:
Invoke-WmiMethod -Path Win32_Process -Name Create -ArgumentList "powershell.exe [console]::beep(500,300)" -ComputerName "mycompname"
This also works for everything else:
Invoke-WmiMethod -Path Win32_Process -Name Create -ArgumentList "powershell.exe shutdown -s" -ComputerName "mycompname"
Thanks!
Related
So i'm trying to run CleanMgr via powershell on a remote computer. Since CleanMgr has a GUI Powershell cannot run it directly, as described here
If you do this then CleanMgr will hang forever waiting for user input. So this means we have to approach this differently.
I tried several approaches, see below. But non of them works like i would. It still hangs OR runs attached from powershell giving no feedback when done.
Simply put i want to run (remotely) CleanMgr on our Office PC's from my PC (Domain Admin).
Invoke-Command -ComputerName $ComputerOBJ -ScriptBlock {
# Create registry values
Write-Host "Setup keys..."
$volumeCaches = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
foreach ($key in $volumeCaches) {
Set-ItemProperty -Path "$($key.PSPath)" -Name StateFlags0333 -Value 2
}
# Execute Disk Cleanup Tool (cleanmgr.exe)
#Write-Host 'Starting CleanMgr.exe...'
Attempt 1:
Start-Process -FilePath "CleanMgr.exe" -ArgumentList '/sagerun:333' -NoNewWindow
Attempt 2:
Start-Process -FilePath "CleanMgr.exe" -ArgumentList '/sagerun:333' -WindowStyle Hidden
Attempt 3:
Invoke-WmiMethod -Class Win32_Process -Name "Create" -ArgumentList 'CleanMgr.exe /sagerun:333'
Attempt 4:
C:\temp\PsExec.exe \\$ComputerOBJ CleanMgr.exe /sagerun:333
Attempt 5:
$A = New-ScheduledTaskAction -Execute "cleanmgr.exe" -Argument '/sagerun:333'
$T = New-ScheduledTaskTrigger -Once -At (get-date).AddSeconds(1); $t.EndBoundary = (get-date).AddSeconds(60).ToString('s')
$S = New-ScheduledTaskSettingsSet -StartWhenAvailable -DeleteExpiredTaskAfter 00:00:30
Register-ScheduledTask -Force -user SYSTEM -TaskName "Run CleanMgr" -Action $A -Trigger $T -Settings $S
#Wait until Clean is done.
Write-Host 'Waiting for CleanMgr and DismHost processes to complete...'
Get-Process -Name cleanmgr, dismhost -ErrorAction SilentlyContinue | Wait-Process
# Remove the previously created registry values
Write-Host "Cleanmgr completed, now deleting keys"
$volumeCaches = Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Explorer\VolumeCaches"
foreach ($key in $volumeCaches) {
Remove-ItemProperty -Path "$($key.PSPath)" -Name StateFlags0333 -Force
}
}
Im trying to create a script where a domain user would be able to run IIS service on windows as a local admin using stored credentials.
$adminerpath = 'c:\programdata\adminer'
Function StoreCreds(){
$credential = Get-Credential
$credential | Export-CliXml -Path $adminerpath\data.dat
}
if (Test-Path $adminerpath){
$credential = Import-CliXml -Path $adminerpath\data.dat
Start-Process C:\windows\System32\inetsrv\InetMgr.exe -Credential ($credentials)
}
else {
New-Item -Path $adminerpath -ItemType "directory"
attrib +h c:\programdata\adminer | Out-Null
StoreCreds
}
very simple, should see if the credential is stored and then run process with -credential.
it works with anything else (like note.exe or pwoershell.exe), but when i try running this with InetMgr.exe im getting:
start-process : This command cannot be run due to the error: The requested operation requires elevation.
any help would be much appriciated
Just some notes:
The issue that is being faced does not happen on every machine, only 1 in 20
I know it is not a powershell issue, but need to know from a health perspective what could cause this
The machine allows a connection with an Admin account over the PS Port, but after that the machine does not see the rights of the account
If I pass the Credentials using a Get-Credential rather than a PS Credential Object, it works however this is not an acceptable solution as the script it being wrapped in an MSO Runbook
Code being used for Credentials:
$Username = "domainname\userid"
$Password = "P#s4w0rd1!" | ConvertTo-SecureString -AsPlainText -Force
$mycreds = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $Username, $Password
Code for the PSSession:
$Session1 = New-PSSession -ComputerName WorkstationNAme #Connects to the computer
Invoke-Command -Session $Session1 -ScriptBlock {
$FreeDrive = (68..90 | %{$L=[char]$_; if ((gdr).Name -notContains $L) {$L}})[0] #Grabs the first available Drive Letter
$execDriveLocation = New-PSDrive -Name $FreeDrive -PSProvider FileSystem -Root $Using:Variable1 -Credential $using:mycreds -Persist #Creates temporary mapped drive
}
Error Returned on the affected machines:
The specified network password is not correct
+ CategoryInfo : InvalidOperation: (D:PSDriveInfo) [New-PSDrive], Win32Exception
+ FullyQualifiedErrorId : CouldNotMapNetworkDrive,Microsoft.PowerShell.Commands.NewPSDriveCommand
+ PSComputerName : computername
Any thoughts or suggestions?
I'm trying to return exit code from a powershell script that is executed on a remote machine. But, when I check ExitCode it has some random number.
What I'm doing wrong? In addition, is it possible to return the whole text?
my script
$proc = Start-Process -Filepath "$PSExec" -ArgumentList "\\$server -h -u $user -p $pass -d PowerShell $command" -PassThru -Wait
$proc.ExitCode
remote script
New-Item "c:\temp\1.txt" -type file -force
exit 123
UPDATE
$secureString = ConvertTo-SecureString $password -Force -AsPlainText #$password includes password in clear text
$cred = New-Object System.Management.Automation.PSCredential($usrName, $secureString)
$sess = New-PSSession -ComputerName $serverName -Credential $cred
$command = "`"C:\temp\1.ps1`""
$result = Invoke-Command -Session $sess -ScriptBlock {
Start-Process -Filepath "$PSExec" -ArgumentList "\\$server -h -u $usrName -p $password -d PowerShell $command" -PassThru -Wait
}
Can you use Invoke-Command as an alternative?
Example:
$session = New-PSSesson -ComputerName $serverName -Credential (Get-Credential)
$result = Invoke-Command -Session $session -ScriptBlock {
Start-Process ...
}
As an alternative to Get-Credential you can created a credential object and pass it via the -Credential paramter to Invoke-Command. Example:
$secureString = ConvertTo-SecureString $password -Force -AsPlainText #$password includes password in clear text
$cred = [System.Management.Automation.PSCredential]::new($usrName, $secureString)
$sess = New-PSSession -ComputerName $ComputerName -Credential $cred
Invoke-Command -Session $sess -ScriptBlock { ... }
$result should also include the ExitCode property, since Powershell Remoting serializes the remote object. I always suggest Powershell Remoting compared to the cmdlet specific ComputerName implementations. It uses a more standardized way (WsMan -> HTTP(S)). See this link for further details.
Hope that helps.
For your first approach, your issue is that when running psexec with the -d (don't wait) flag it returns the pid of the command that launched it, rather than waiting and returning the exitcode.
Altogether your process also could be optimized. First if you wanted to use psexec.exe, I don't see a reason for Start-Process since you are waiting and passing through. Just & $psexec ... would suffice.
However Moerwald's suggestion for using Invoke-Command is a great one. In your updated code, you are still running Start-Process and Psexec which are unnecessary. When you are invoking the command, you are already remotely running code, so just run the code:
$secureString = ConvertTo-SecureString $password -Force -AsPlainText
$cred = New-Object System.Management.Automation.PSCredential($usrName, $secureString)
$result = Invoke-Command -ComputerName $serverName -Credential $cred -ScriptBlock {
New-Item "c:\temp\1.txt" -type file -force
exit 123
}
Also, since it doesn't look like you are reusing the session, I dropped the saving the session to a variable. And it would also be better to replace all of the credential setup with a Get-Credential rather than passing plaintext passwords around (avoid the password ending up in a saved transcript). That would look like this:
$result = Invoke-Command -ComputerName $serverName -Credential (Get-Credential) -ScriptBlock {
New-Item "c:\temp\1.txt" -type file -force
exit 123
}
I need to connect to some remote servers from a client (same domain as the servers) once connected, I need to run a batch file:
I've done so with this code:
$Username = 'USER'
$Password = 'PASSWORD'
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
try {
Invoke-Command -ComputerName "SERVER1" -Credential $Cred -ScriptBlock -ErrorAction Stop {
Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat"
}
} catch {
Write-Host "error"
}
This script does not give any errors, but it doesn't seem to be executing the batch script.
any input on this would be greatly appreciated.
Try replacing
invoke-command -computername "SERVER1" -credential $Cred -ScriptBlock -ErrorAction stop { Start-Process "C:\Users\nithi.sundar\Desktop\Test.bat" }
with
Invoke-Command -ComputerName "Server1" -credential $cred -ErrorAction Stop -ScriptBlock {Invoke-Expression -Command:"cmd.exe /c 'C:\Users\nithi.sund
ar\Desktop\Test.bat'"}
It's not possible that the code you posted ran without errors, because you messed up the order of the argument to Invoke-Command. This:
Invoke-Command ... -ScriptBlock -ErrorAction Stop { ... }
should actually look like this:
Invoke-Command ... -ErrorAction Stop -ScriptBlock { ... }
Also, DO NOT use Invoke-Expression for this. It's practically always the wrong tool for whatever you need to accomplish. You also don't need Start-Process since PowerShell can run batch scripts directly:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
C:\Users\nithi.sundar\Desktop\Test.bat
} -Credential $Cred -ErrorAction Stop
If the command is a string rather than a bare word you need to use the call operator, though:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
& "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
You could also invoke the batch file with cmd.exe:
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
cmd /c "C:\Users\nithi.sundar\Desktop\Test.bat"
} -Credential $Cred -ErrorAction Stop
If for some reason you must use Start-Process you should add the parameters -NoNewWindow and -Wait.
Invoke-Command -ComputerName "SERVER1" -ScriptBlock {
Start-Process 'C:\Users\nithi.sundar\Desktop\Test.bat' -NoNewWindow -Wait
} -Credential $Cred -ErrorAction Stop
By default Start-Process runs the invoked process asynchronously (i.e. the call returns immediately) and in a separate window. That is most likely the reason why your code didn't work as intended.