Running ADUC as different user - wrong directory - powershell

I'm fairly new to powershell.
In this code my coworkers are getting an error which I'm not getting.
I've tried some different things (like adding the complete path to powershell) but I'm not able to fix it.
Can anyone tell me what's going wrong?
Function Button4_Click()
{
$Filepathmmc = join-path -path $env:SystemRoot -ChildPath System32\Mmc.exe
$argumentlistdsa = join-path -path $env:SystemRoot -ChildPath System32\dsa.msc
$Credential = New-Object -TypeName System.Management.Automation.PsCredential -ArgumentList (Get-Content "$($env:userprofile)\username.txt"),(Get-Content "$($env:userprofile)\encrypt.txt" | ConvertTo-SecureString)
Start-Process powershell -Credential $Credential -ArgumentList "Start-Process -FilePath '$filepathmmc' -ArgumentList '$argumentlistdsa' -Verb RunAs"
}
I also tried using this as the Start-Process path:
$aducpath = (Join-Path $Env:SystemRoot -ChildPath "\syswow64\WindowsPowerShell\v1.0\powershell.exe")
Needs elevation

I see that you are still using join-path, have you tried using an absolute path for the sake of troubleshooting?
I also see that you're reading a password from a text file. I would advise you not to do that, and instead maybe have users log in themselves instead for elevation. If you replace $Credential in the invocation process with (Get-Credential) it will prompt your user for elevation. You can also use $Credential = Get-Credential to save it for the future.
I can't reproduce the error you're getting with just this code snippet. All of your Join-Paths are sane and seem to point to the expected place. When run as an unprivileged user, I get a UAC prompt rather than the invalid code. If there is actually a problem with where things are, might I suggest that you use something like this to search for what you need?
Function Button4_Click()
{
$Filepathmmc = (Get-ChildItem -Recurse -Path $env:SystemRoot -Filter "Mmc.exe").FullName | Select-Object -First 1
$argumentlistdsa = (Get-ChildItem -Recurse -Path $env:SystemRoot -Filter "dsa.mmc").FullName | Select-Object -First 1
Start-Process powershell -Credential (Get-Credential) -ArgumentList "Start-Process -FilePath '$filepathmmc' -ArgumentList '$argumentlistdsa' -Verb RunAs"
}
It's not perfect, but it will always return an instance of mmc. You can add -ErrorAction SilentlyContinue to the Get-ChildItem command to suppress the inevitable 'Accesss to the path X is denied' exceptions.

Related

PowerShell Start-Process Not Starting when script called remotely

I am trying to remotely install Octopus Deploy Tentacle to a VM. I have a powershell script that I've written that handles this business for me. It works exactly as expected when I am physically logged into the machine, but when I am remotely executing it on the machine it doesn't run the installer. Every other part of the script works fine though.
The portion of the script that downloads and installs:
try{
$url = "https://octopus.com/downloads/latest/OctopusTentacle64"
$downloadPath = "$env:TEMP\octopus\"
if (Test-Path $downloadPath) {
Remove-Item -Path $downloadPath -Recurse -Force
}
New-Item -Type Directory -Path $downloadPath | Out-Null
[System.Net.ServicePointManager]::SecurityProtocol = [System.Net.SecurityProtocolType]::Tls12
(New-Object System.Net.WebClient).DownloadFile($url, "$downloadPath\Octopus.Tentacle.msi")
Start-Process -FilePath "$downloadPath\Octopus.Tentacle.msi" -ArgumentList "/passive" -Wait -verbose
Write-Output "Octopus Tentacle Installed."
} catch { throw "error downloading tentacle. try again later."}
I am using this to attempt to run the file remotely(edit, copied wrong line):
Invoke-Command -ComputerName $vmName -FilePath "\\$vmName\Installers\Install-Calamari.ps1" -Credential $creds -ArgumentList $deployTag, $envID
What am I missing?

How to write local variable to a file in remote server using Powershell script?

On a remote server there is a .BAT file which uses a .properties file to run.
I am able to run the .BAT file calling the .properties file, but in that .properties file last line is:
exportQuery1=SELECT * FROM CI_INFOOBJECTS where SI_ID='123456'.
I am modifying that line/SI_ID value manually which actually increasing my effort.
I have tried a few options but am not able to provide the value/entire line from the local powershell commandline which will be written in the .properties file.
So I have to modify the .ps1 every time. I want to pass the entry with the local powershell command as a variable.
Deleting the old line:
Invoke-Command -computername $ServerName -Credential $Cred -ErrorAction stop -ScriptBlock {Set-Content -Path D:\Script\TestFile.txt -Value (get-content -Path D:\Script\TestFile.txt | Select-String -Pattern 'SI_ID' -NotMatch)}
Creating the New line at the end of the file:
Invoke-Command -computername $ServerName -Credential $Cred -ErrorAction stop -ScriptBlock {add-content D:\Script\TestFile.txt "exportQuery1=SELECT * FROM CI_INFOOBJECTS where SI_ID='abcdef'"}
Please help to pass the SI_ID/entire line from the command while executing the script.
Why not use a simple parameter and the using statement in a single invoke call?
param($SI_ID)
$SB = {
Set-Content -Path D:\Script\TestFile.txt -Value (get-content -Path D:\Script\TestFile.txt | Select-String -Pattern 'SI_ID' -NotMatch)
add-content D:\Script\TestFile.txt "exportQuery1=SELECT * FROM CI_INFOOBJECTS where SI_ID='$using:SI_ID'"
}
Invoke-Command -computername $ServerName -Credential $Cred -ErrorAction stop -ScriptBlock $SB
then just .\myscript -SI_ID "abcd"

How to Run script with admin rights to change execution policy

See below script:
I need to launch this script with admin rights embedded inside of the script to set execution policy to unrestricted and then at the end of the script set it back. From what I've found so far this is either not possible or very difficult to do. I'm hoping there is an easier way to do this. The users that will be running this script do not have admin rights on their PC's so they will not be able to elevate and manually run from inside of powershell.
Stop-process -Name OUTLOOK -ErrorAction SilentlyContinue -Force
Stop-process -Name communicator -ErrorAction SilentlyContinue -Force
Stop-process -Name lync -ErrorAction SilentlyContinue -Force
Stop-Process -Name UcMapi -ErrorAction SilentlyContinue -Force
Stop-Process -Name skypehost -ErrorAction SilentlyContinue -Force
Stop-Process -Name searchprotocolhost -ErrorAction SilentlyContinue -Force
$OstPath = "c:\users\$([environment]::username)"+ "\AppData" + "\local" + "\Microsoft" + "\Outlook"
$ost = get-ChildItem $OstPath | where { $_.Extension -eq ".ost"}
$ost | remove-Item -force
Start-Process Outlook
if (Test-Path 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe'
}
Else
{
write-host "Lync is not installed"
if (Test-Path 'C:\Program Files (x86)\Microsoft Office Communicator')
{
Start-Process 'C:\Program Files (x86)\Microsoft Office Communicator\communicator.exe'
}
Else
{
write-host "Communicator is not installed"
}
}
You can use:
$GBL_Username = "Here type your username"
$GBL_Password = ConvertTo-SecureString –String "Here type your password in plain text" –AsPlainText -Force
$GBL_Credential = New-Object –TypeName System.Management.Automation.PSCredential –ArgumentList $GBL_Username, $GBL_Password
Start-Process 'C:\Program Files (x86)\Microsoft Office\office15\lync.exe' -Credential $GBL_Credential
And use the variable $GBL_Credential with the second part (the execution of Office Comunicator)
A problem with this: the credential will show in plain text and, if someone try to edit the script with notepad, PowerShell ISE or other program, they can will see the passsword.
Have a good day.
From what I see in the script, there's no need to elevate. If this is only to overcome the ExecutionPolicy than your approach is wrong. ExecutionPolicy is there to prevent users run untrusted scripts. So far your script is one of those.
Correct way of doing it would be to sign your script with the certificate and set your ExecutionPolicy to Allsigned on all computers. Users will then only be able to run the signed scripts from now on.
If this is not possible, I see 2 options:
Users copy contents of the script and paste it into the powershell window
You set ExecutionPolicy to unrestricted. Keep in mind that users will still need to elevate if they try to do something serious, but for this script elevation is not necessary.
So all in all, ExecutionPolicy is there to prevent exactly what you are trying to do, so do not expect it will be easy to overcome. It's also not something that you turn off and on. You should think of what is acceptable for you and set it to appropriate level in your environment.

Run Registry File Remotely with PowerShell

I'm using the following script to run test.reg on multiple remote systems:
$computers = Get-Content computers.txt
Invoke-Command -ComputerName $computers -ScriptBlock {
regedit /i /s "\\SERVER\C$\RegistryFiles\test.reg"
}
The script doesn't error, but the registry entry doesn't import on any of the systems.
I know test.reg file is a valid registry file because I copied it over, ran it manually, and the registry key imports. I also made sure PowerShell Remoting is enabled on the remote computers.
Any ideas why the registry key isn't importing?
I found the best way not to mess with issues related to server authentication and cut down on complexity just to pass Reg file as parameter to function.
$regFile = #"
Windows Registry Editor Version 5.00
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\services\Tcpip\Parameters]
"MaxUserPort"=dword:00005000
"TcpTimedWaitDelay"=dword:0000001e
"#
Invoke-Command -ComputerName computerName -ScriptBlock {param($regFile) $regFile | out-file $env:temp\a.reg;
reg.exe import $env:temp\a.reg } -ArgumentList $regFile
I posted on some PowerShell forums and finally got this working.
I had to 1) move the $newfile variable inside the loop and 2) comment out the $ in the path stored in the $newfile variable.
For reference, the final script looks like this if anyone wants to use it:
$servers = Get-Content servers.txt
$HostedRegFile = "C:\Scripts\RegistryFiles\test.reg"
foreach ($server in $servers)
{
$newfile = "\\$server\c`$\Downloads\RegistryFiles\test.reg"
New-Item -ErrorAction SilentlyContinue -ItemType directory -Path \\$server\C$\Downloads\RegistryFiles
Copy-Item $HostedRegFile -Destination $newfile
Invoke-Command -ComputerName $server -ScriptBlock {
Start-Process -filepath "C:\windows\regedit.exe" -argumentlist "/s C:\Downloads\RegistryFiles\test.reg"
}
}

How to get all (IIS) websites status/state from remote machine using PowerShell?

I was trying to read the status of IIS website from remotely. I tried below code.
$Session = New-PSSession -ComputerName $serverName
$block = {
import-module 'webAdministration'
Get-ChildItem -path IIS:\Sites
}
Invoke-Command -Session $Session -ScriptBlock $block | Out-File -append $WebreportPath
But above command given me only Websites with https binding, when it comes to https it throws below error.
The data is invalid. (Exception from HRESULT: 0x8007000D)
+ CategoryInfo : NotSpecified: (:) [Get-ChildItem], COMException
+ FullyQualifiedErrorId : System.Runtime.InteropServices.COMException,Microsoft.PowerShell.Commands.GetChildItemCommand
I am trying to renmote a Windows Server 2008 R2 with IIS 7.
Please guide me. Thanks !
Hope this will help for someone. Below is my findings and the answer.
Powershell sends only objects remotely, and render them using available templates.
So need to give a template accordingly. I used "Format-Table".
Be-careful, if you use "Format-Table" outside it results same error. Remember to use it inside the scriptblock.
Error-prone:
Invoke-Command -ComputerName $serverName { Import-Module WebAdministration; Get-ChildItem -path IIS:\Sites} | Format-Table | Out-File -append $WebreportPath
Correct code:
Invoke-Command -ComputerName $serverName { Import-Module WebAdministration; Get-ChildItem -path IIS:\Sites | Format-Table} | Out-File -append $WebreportPath
My refers :
http://forums.iis.net/t/1155059.aspx?IIS+provider+and+PowerShell+remoting
Good Luck !
There seems to be some problem with retrieving the objects using a remote session, but that is no blocking issue (I have run into this as well).
To prevent the error from being written, you can use -ErrorAction like this:
$Session = New-PSSession -ComputerName $serverName
$block = {
Import-Module 'webAdministration'
Get-ChildItem -path IIS:\Sites
}
Invoke-Command -Session $Session -ErrorAction SilentlyContinue -ScriptBlock $block |
Out-File -append $WebreportPath
This way you will not see the remoting error, but you will still receive the data you need.
Note that this hides all errors, so you are possibly hiding an error that you may want to see. For that you will need a fix for the underlying ptoblem, so you can remove the -ErrorAction patch.