I’m attempting to install the .net framework on a windows server 2008 r2 machine remotely via PowerShell. Reading about it seems that this cannot be achieved through an existing PowerShell session but credentials need to be explicitly passed in (any idea why this is?). However, I'm still getting permission errors.
For example, If I run:
$cred = Get-Credential -Credential 10.20.0.13\administrator
$Session=New-PsSession -ComputerName 10.20.0.13 -Credential $cred
Invoke-command -ScriptBlock {Start-Process -FilePath c:\installers\dotNetFx40_Full_x86_x64.exe -ArgumentList "/q /norestart /log c:\" -Wait} -Credential $cred -ComputerName 10.20.0.13
I can see on the remote machine that the installer runs (in task manager), the temporary folder is created on the root of c:\, the files extracted and then I get a 700kb log file. At the foot of that log file I get:
OS Version = 6.1.7601, Platform 2, Service Pack 1 OS Description =
Win2K8R2 - x64 Standard Edition Service Pack 1 CommandLine =
C:\b65da67b927bfb71c84adcecefc019\Setup.exe /q /norestart /log c:\
/x86 /x64 TimeZone = GMT Standard Time Initial LCID = 2057 Using
Simultaneous Download and Install mechanism Operation: Installing
Package Name = Microsoft .NET Framework 4 Setup Package Version =
4.0.30319 User Experience Data Collection Policy: Disabled Number of applicable items: 11 Exe
(C:\b65da67b927bfb71c84adcecefc019\SetupUtility.exe) succeeded. Exe
Log File: dd_SetupUtility.txt ServiceControl operation succeeded!
ServiceControl operation succeeded! Exe
(C:\b65da67b927bfb71c84adcecefc019\Windows6.1-KB958488-v6001-x64.msu)
failed with 0x5 - Access is denied. . Final Result: Installation
failed with error code: (0x00000005), "Access is denied. " (Elapsed
time: 0 00:01:12).
So access is denied. However, using the exact same credentials I can perform other tasks (add server roles in Powershell, add windows features via powershell etc) and I can RDP onto the box using the same username/password and run the installer there (which completes fine).
I’m missing something somewhere, but can’t seem to find out what it is. I can see its worked for someone else (http://social.technet.microsoft.com/Forums/windowsserver/ar-SA/3045eb24-7739-4695-ae94-5aa7052119fd/install-dotnet-framework-4-using-powershell?forum=winserverpowershell) so no idea why I’m getting this.
Any help much appreciated.
Thanks
You're creating a session but never using it?
I haven't tried this on a remote computer beforey, but try to run the process "as admin" by using -Verb RunAs, like this:
$cred = Get-Credential -Credential 10.20.0.13\administrator
$Session=New-PsSession -ComputerName 10.20.0.13 -Credential $cred
Invoke-command -ScriptBlock {Start-Process -FilePath c:\installers\dotNetFx40_Full_x86_x64.exe -ArgumentList "/q /norestart /log c:\" -Wait -Verb RunAs } -Session $Session
While installation of .NET framework 4.0, It installs some updates as well (.msu) files.
But when we are installaing .NET 4.0 remotely, It fails because of these updates. The reason behind that is, it's not allowable to install these updates remotely. Please find the KB article here. This article also mentioned the workaround for this.
you have servername in textfile or machine names in OU based. create .bat which has .exe to run C:\temp\xxx.exe /S /qn
$ou='OU=subou3,OU=subou2,OU=subou1,DC=domain,DC=com'
$filter = #("machinename1", "machinename2")
$compute= Get-ADComputer -Filter * -SearchBase $ou | where-object{$filter -contains $_.name}
$comp=$compute.name
foreach ($Computer in $Comp) {
Write-Host "Processing $Computer"
{
Write-Host " Installing application on $Comp"
psexec $Compter path\XXX.bat /S /qn
}
}
Related
I'd like a script to be used in this situation:
gain remote access without admin privileges
remotely start Quick Assist as .\Administrator and not have a UAC dialogue.
Step 1 is usually made with Quick Assist, sometimes made with Teams screen sharing.
I'm aware that I can locate quickassist.exe in File Explorer then use Shift and the context menu to Run as a different user, however I'd like a scripted approach.
Experiment A
This works, but there's a Yes/No UAC dialogue:
$isElevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ( -not $isElevated ) {
Start-Process powershell.exe -Credential Administrator -NoNewWindow -ArgumentList {
Start-Process quickassist.exe -Verb RunAs ;
} ;
}
Experiment B
I make multiple mistakes, don't know how to correct them. (I'm trying to learn PowerShell, gradually, but I'm easily confused whilst learning; slightly dyslexic.)
$isElevated = ([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)
if ( -not $isElevated ) {
Start-Process powershell.exe -Credential Administrator {
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "PromptOnSecureDesktop" -Value 0 -Force;
};
Write-Host "UAC (user account control) is weakened for a Quick Assist session …" -ForegroundColor Red;
Start-Process powershell.exe -Credential Administrator -NoNewWindow -ArgumentList {Start-Process quickassist.exe -Verb RunAs -Wait};
Write-Host "… Quick Assist session complete …" -ForegroundColor Red;
Start-Process powershell.exe -Credential Administrator {
Set-ItemProperty -Path "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System" -Name "PromptOnSecureDesktop" -Value 1 -Force;
};
Write-Host "… UAC is strengthened." -ForegroundColor Red;
}
the two intended changes to the registry do not occur
the third credential dialogue appears too soon – I want it to not appear until after the end of the Quick Assist session.
Also, conceptually, there's probably no need to run Quick Assist as Administrator whilst UAC is temporarily weakened.
References
https://stackoverflow.com/a/2258134/38108 (2010-02-13) I see use of -Credential with Invoke-Command but when I try to do something similar, for changes to the registry, I make a mess.
https://stackoverflow.com/a/47516161/38108 (2017-11-27) self-elevating PowerShell scripts.
https://superuser.com/a/1524960/84988 (2020-02-12) and https://serverfault.com/a/1003238/91969 (2020-02-15) are interesting – the same script in both answers – however I need something like -Credential Administrator in lieu of -ComputerName.
https://stackoverflow.com/a/60292423/38108 (2020-03-07) via https://stackoverflow.com/a/60263039/38108
PowerShell commands - PowerShell - SS64.com
https://github.com/okieselbach/Intune/blob/master/DisablePromptOnSecureDesktop.ps1 (2020-11-13) via Quick Assist the built-in Remote Control in Windows 10 – Modern IT – Cloud – Workplace
The short answer is don't. Get a real remote management tool or have someone hit the UAC yes prompt.
This is more of a windows thing than powershell, as windows explicitly denies elevating a process locally without going through UAC (and for good reason!). You used to be able to do things like this:
# Use Enter-PSSession to start a "remote" session
# This may still support elevation if you specify CredSSP and configure credential delegation):
New-PSSession MyPCName -Auth CredSSP -cred (get-credential)
# Create a scheduled task with RunAs/elevated permissions:
Register-ScheduledTask -Action $action -User .\Administrator -TaskName "Admin-Stuff" -RunLevel Highest
Which now give fat access denied messages when running locally. You also are not able to edit registry settings within HKLM: without elevation, so disabling uac temporarily is not an option.
You may be able to make use of this exploit that allows admin users to bypass uac, but I think you still have to Run-as-other-user your shell to use it.
I have an update script for running the Dell Command Update tool. In short dcu-cli.exe. The thing now is than when i run the same script code on the computer local then everything runs OK but when i run the exact same code in a script with invoke-command(and yes i have full admin rights) than the exitcode is 2 meaning An unknown application error has occurred instead of 0 (everything OK)
It is a very large script so i created a new one to debug this. This is the shorted code:
Invoke-Command -ComputerName "MyComputer" -ScriptBlock {
$ExitCode = 0
#Declare path and arguments
$DcuCliPath = 'C:\Program Files (x86)\Dell\CommandUpdate\dcu-cli.exe'
$DellCommand = "/applyUpdates -autoSuspendBitLocker=enable -outputLog=C:\Dell_Update.log"
#Verify Dell Command | Update exists
If (Test-Path -Path $DcuCliPath) {
$objWMI = Get-WmiObject Win32_ComputerSystem
Write-Host ("Dell Model [{0}]" -f $objWMI.Model.Trim())
$serviceName = "DellClientManagementService"
Write-Host ("Service [{0}] is currently [{1}]" -f $serviceName, (Get-Service $serviceName).Status)
If ((Get-Service $serviceName).Status -eq 'Stopped') {
Start-Service $serviceName
Write-Host "Service [$serviceName] started"
}
#Update the system with the latest drivers
Write-Host "Starting Dell Command | Update tool with arguments [$DellCommand] dcu-cli found at [$DcuCliPath]"
$ExitCode = (Start-Process -FilePath ($DcuCliPath) -ArgumentList ($DellCommand) -PassThru -Wait).ExitCode
Write-Host ("Dell Command | Update tool finished with ExitCode: [$ExitCode] current Win32 ExitCode: [$LastExitCode] Check log for more information: C:\Dell_Update.log")
}
}
When i remove the Invoke-Command -ComputerName "MyComputer" -ScriptBlock { and then copy + run the script local on the PC then the exitcode = 0
What i also noticed than when i run the command via 'Invoke-Command' then there is also no log file created as i passed along in the arguments... So my best guess is something is going wrong with local an remote paths?
So what am i missing? I'm guessing it is something simple but i spend several hours to get this running without any luck...
Try running it this way. You should be able to see any output or error messages. I typically add to the path first rather than using & or start-process.
invoke-command mycomputer {
$env:path += ';C:\Program Files (x86)\Dell\CommandUpdate';
dcu-cli /applyUpdates -autoSuspendBitLocker=enable -outputLog=C:\Dell_Update.log }
Using start-process inside invoke-command seems pretty challenging. I can't even see the output of findstr unless I save it to a file. And if I didn't wait the output would be truncated. By default start-process runs in the background and in another window. There's a -nonewwindow option too but it doesn't help with invoke-command.
invoke-command localhost { # elevated
start-process 'findstr' '/i word c:\users\joe\file1' -wait -RedirectStandardOutput c:\users\joe\out }
#js2010, thanks for your additional help. Unfortunately this didn't helped either.
So i did some more debugging and it turns out it was a bug in the dcu-cli version running on my test machine, DOH...!!
On the test machine version 3.1.1 was running and on another machine version 4.0 was running and that worked fine via remote Powershell. So i looked for the release notes, which i found here: https://www.dell.com/support/kbdoc/000177325/dell-command-update
And as you can see in version 3.1.3 there was this fix:
A problem was solved where dcu-cli.exe was not executed in an external interactive session of PowerShell.
I've setup a deployment group successfully via Azure Pipelines and have deployed my Api successfully as well. My homework says that I have to prove that the Api was deployed successfully so I thought that I should run this via IIS. However, a 502.5 error is being thrown and I find out that a server hosting bundle is needed. How do you automate this via Azure PIpelines? I found an Invoke-Webrequest script that does this but it only installs 1.0.0...
I'm not sure if there is a built in way to do this, but in our project we've done it by including the DotNetCore.2.0.7-WindowsHosting.exe installer in our build artifacts and simply executing the installer with a Powershell step at the beginning of the release process.
You'll want to use the /quiet and /norestart flags:
$Path = "path to your installer exe in artifacts"
$args = New-Object -TypeName System.Collections.Generic.List[System.String]
$args.Add("/quiet")
$args.Add("/norestart")
Start-Process -FilePath $Path -ArgumentList $args -NoNewWindow -Wait -PassThru
Good luck!
if you are looking to download this directly from MS instead you can use this script:
$ErrorActionPreference="Stop";
If(-NOT ([Security.Principal.WindowsPrincipal][Security.Principal.WindowsIdentity]::GetCurrent() ).IsInRole( [Security.Principal.WindowsBuiltInRole] “Administrator”)){
throw "Run command in Administrator PowerShell Prompt"
};If($PSVersionTable.PSVersion -lt (New-Object System.Version("3.0"))){ throw "The minimum version of Windows PowerShell that is required by the script (3.0) does not match the currently running version of Windows PowerShell." };
$tempDir = [System.IO.Path]::GetTempPath()
$downloadPath="$tempdir\netCoreHostingBundle.exe";
$DefaultProxy=[System.Net.WebRequest]::DefaultWebProxy;
$securityProtocol=#();
$securityProtocol+=[Net.ServicePointManager]::SecurityProtocol;
$securityProtocol+=[Net.SecurityProtocolType]::Tls12;
[Net.ServicePointManager]::SecurityProtocol=$securityProtocol;
$WebClient=New-Object Net.WebClient;
$Uri='https://download.visualstudio.microsoft.com/download/pr/9b9f4a6e-aef8-41e0-90db-bae1b0cf4e34/4ab93354cdff8991d91a9f40d022d450/dotnet-hosting-3.1.6-win.exe';
if($DefaultProxy -and (-not $DefaultProxy.IsBypassed($Uri))){$WebClient.Proxy= New-Object Net.WebProxy($DefaultProxy.GetProxy($Uri).OriginalString, $True);};
$WebClient.DownloadFile($Uri, $downloadPath);
$args = New-Object -TypeName System.Collections.Generic.List[System.String]
$args.Add("/quiet")
$args.Add("/norestart")
Start-Process -FilePath $downloadPath -ArgumentList $args -NoNewWindow -Wait -PassThru -WorkingDirectory $tempDir
I'm trying to create a Powershell script that will be deployed to any node that is showing bad update health to automate some of the simple tasks without having to interrupt users during their workday. The Powershell script works perfectly if ran from an elevated PS prompt. It also runs fine when the same script is deployed to a test machine via SCCM with one exception: it won't call SFC.EXE /SCANNOW.
I've tried using:
Start-Process -FilePath "${env:Windir}\System32\SFC.EXE" -ArgumentList '/scannow' -Wait -NoNewWindow
Start-Process -FilePath "sfc.exe" -ArgumentList '/scannow' -Wait -NoNewWindow
Start-Process -FilePath "${env:Windir}\System32\SFC.EXE" -ArgumentList '/scannow' -RedirectStandardOutput "C:\SFC-Out.log" -RedirectStandardError "C:\SFC-Err.log" -Wait -NoNewWindow
& "sfc.exe" "/scannow"
Invoke-Command -ScriptBlock { sfc.exe /scannow }
Again, all of these examples work exactly as intended when run from an elevated PS prompt, but fail when run from the deployed PowerShell script. When I used the -RedirectStandardOutput, I checked the file SFC-Out.log and it read:
"Windows Resource Protection could not start the repair service"
I think this is because SCCM runs programs/scripts in the SYSTEM context instead of a user context (or even an elevated user context, but SYSTEM is supposed to be higher than an elevated session).
Is there a way to accomplish this? Sorry for the bad formatting, this is my first post on this site.
A bit late but I encountered the same issue. Not sure if this is the case for you but the cause was configuring the deployment of the script with SCCM to run as a 32 bit process. The script was being deployed to 64 bit systems. When I unchecked "run as 32 bit process" in the deployment configuration SFC worked without an issue under the context of a System account.
I created a package (not an application) in SCCM and had to use the redirect using the elusive sysnative folder for x64 machines:
https://www.thewindowsclub.com/sysnative-folder-in-windows-64-bit
So it would be:
C:\Windows\Sysnative\SFC.EXE /SCANNOW
What you have will work, just missing "-Verb RunAs" to elevate permissions. So your cmdlet should read:-
Start-Process -FilePath "${env:Windir}\System32\SFC.EXE" -ArgumentList '/scannow' -Wait -Verb RunAs
I've been reading and searching online for this, the only answer so far is that It can't be run due to sccm using the system account. It's also the same behavior when trying to run winmgt.
Fast forward to SCCM Current Branch 2109 and I was able to solve this problem by using the new Scripts feature built into SCCM. Using & 'sfc.exe' '/scannow' works, and I can manually run this script against any device collection showing devices in error. Start-Process -FilePath "sfc.exe" -ArgumentList "/scannow" -NoNewWindow -Wait works too.
I am trying to connect to remote computers with Active Directory and see if a single program is installed. I have tried a couple tutorials I found on the Internet, but with no success:
http://windowsitpro.com/powershell/what-applications-are-installed-computers-your-network
http://community.spiceworks.com/scripts/show/2170-get-a-list-of-installed-software-from-a-remote-computer-fast-as-lightning
I cannot get them to work properly, and they are not exactly what I am looking for.
An example of what I want to do: say I have 3 computers on my network:
123-abc
123-bcd
123-cde
and I want to see if the executable C:\Program Files (x86)\Mozilla Firefox\Firefox.exe exists. Can someone please explain how I can go about this in PowerShell?
The simplest way, provided you have domain admin privileges and administrative shares are enabled and accessible on the target computers, would be this:
$computers = '123-abc', '123-bcd', '123-cde'
$path = 'C$\Program Files (x86)\Mozilla Firefox\Firefox.exe'
$computers | % {
'{0}: {1}' -f $_, (Test-Path -LiteralPath "\\$_\$path")
}
There are a handful of ways to check for installed software. Some better suited than others. But if you're certain on the file path on each machine, the Test-Path CmdLet could be an easy approach.
Invoke-Command -ComputerName 123-abc -ScriptBlock {Test-Path 'C:\Program Files (x86)\Mozilla Firefox\Firefox.exe'}
You could probably throw that into a loop with a custom object so you can work with it as well.
For example, your code could look like this.
$pass = "password";
$secpass = ConvertTo-SecureString $pass -AsPlainText -Force;
$creds = New-Object System.Management.Automation.PSCredential("domain\login", $secpass);
Invoke-Command -ComputerName 123-abc, 123-bcd, 123-cde -Credential $creds -ScriptBlock {
Test-Path "C:\Program Files (x86)\Mozilla Firefox\Firefox.exe"
};
There are multiple ways of running powershell commands on remote computers.
Many commands support string[] parameter -ComputerName to which you can pass multiple computer names
You can use the Enter-PSSession cmdlet to enter a Telnet-like session on the remote machine
And finally, you can use the Invoke-Command cmdlet to run a script block against multiple remote hosts.