Wildcards in VisibleExternalCommands not working in PSSessionConfiguration - powershell

I am trying to use wildcards like "c:\scripts\*.ps1" in VisibleExternalCommands for New-PSSessionConfigurationFile and the resulting .pssc file looks fine, but cannot get it to work as expected and the documentation is weak here. I can only make VisibleExternalCommands work by giving full path.
Steps to reproduce, tested on Win10 with PowerShell 5.1:
Setup directory and scripts:
Enable-PSRemoting -Force
mkdir c:\scripts
echo "Write-Output hello" | Out-File c:\scripts\hello.ps1 -Force
echo "Write-Output world" | Out-File c:\scripts\world.ps1 -Force
Using Wildcard (NOT working):
New-PSSessionConfigurationFile -VisibleExternalCommands "c:\scripts\*.ps1" -Path c:\scripts\TestWildcard.pssc -SessionType RestrictedRemoteServer -LanguageMode FullLanguage
Register-PSSessionConfiguration -Name TestWildcard -Path c:\scripts\TestWildcard.pssc -Force
Invoke-Command . -ConfigurationName TestWildcard {c:\scripts\hello.ps1; c:\scripts\world.ps1}
# Fails to recognize both .ps1 scripts as external commands
Using Full Path (works fine):
New-PSSessionConfigurationFile -VisibleExternalCommands "c:\scripts\hello.ps1" -Path c:\scripts\TestFullPath.pssc -SessionType RestrictedRemoteServer -LanguageMode FullLanguage
Register-PSSessionConfiguration -Name TestFullPath -Path c:\scripts\TestFullPath.pssc -Force
Invoke-Command . -ConfigurationName TestFullPath {c:\scripts\hello.ps1; c:\scripts\world.ps1}
# Prints hello and fails to recognize c:\scripts\world.ps1
The documentation (https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/new-pssessionconfigurationfile?view=powershell-5.1) says that wildcard characters are supported, but shows no example of it.
Am I missing something or is this a bug?

The VisibleExternalCommands option does not accept wildcards. This documentation bug was fixed in https://github.com/MicrosoftDocs/PowerShell-Docs/issues/4756.

Related

How to get PS script to access folders that need admin access

I'm a desktop support tech for my company, and we often have a good bit of repetitive troubleshooting we perform such as clearing temp files and cache from C\windows\temp, local appdata temp folder, as well as google and IE cache/cookies. I was writing a powershell script to do this all in one go, and it does what it is supposed to. The only problem is that when I am on a user's computer, I have to actually access the windows temp and local appdata folders first and then run the script for it to work. I believe this is because those two folders require admin access to get into. Since I'm an admin I can put my creds in to access the folders just fine, but I'm having trouble finding some code to insert in order to allow the powershell script to gain access to those folders. Note: I do have a command at the beginning of the script that launches powershell as admin, but that seems to not be enough. My code is below, any insight on this would be terrific. (Looks like my comment hashtags in the code turned the comments bold, apologies)
# Runs the below script with PowerShell in Admin mode
Start-Process "$psHome\powershell.exe" -verb runas -ArgumentList "-file fullpathofthescript"
# Clears google chrome cache
Remove-Item -Path "C:\Users\*\AppData\Local\Google\Chrome\User Data\Default\Cache\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears IE cookies
Remove-Item -Path "C:\Users\*\AppData\Roaming\Microsoft\Windows\Cookies\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears the "windows\temp" folder
Remove-Item -Path "C:\Windows\Temp\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue
# Clears the user's local temp folder
Remove-Item -Path "C:\Users\*\AppData\Local\Temp\*" -verb runas -Recurse -Force -ErrorAction SilentlyContinue"
You can use the -Credential parameter to prompt for the local admin credentials which should allow you to delete in the C:\Windows\* location, assuming ACLs have not be messed with.
Remove-Item -Path "C:\Windows\Temp\*" -Credential (Get-Credential) -Recurse -Force -ErrorAction SilentlyContinue
Putting in the ErrorAction is stopping you from seeing the below error as well.
Remove-Item : A positional parameter cannot be found that accepts argument 'runas'.

Running ADUC as different user - wrong directory

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.

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.

Using the -command PowerShell feature does not executing in CMD

I am trying to create a PowerShell command that reads a registy variable and then executes a command. It does this from the command line using CMD and it runs under SYSTEM.
I have the following code:
powershell.exe -ExecutionPolicy ByPass -WindowStyle Minimized -Command
"$ErrorActionPreference = 'silentlycontinue' |`
New-Variable -name UserNameForSapFolderRemoval -Value (get-itemproperty 'HKCU:\Volatile Environment' |`
Select-Object -ExpandProperty UserName) |`
Remove-Item $("C:\Users\"+$UserNameForSapFolderRemoval +"\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Sapgui 7.30") -Force -Recurse |`
Remove-Variable -Name UserNameForSapFolderRemoval"
But it returns with:
The string is missing the terminator
I added the " character but without succes.
Any idea how I can get this powershell command to run succesful?
Parsing username from registry is way too complicated, as there already is $env:username. Try something like this,
powershell -command { rm -force -recurse "c:\users\$env:username\appdata\whatever" }

Call VBScript With Return Value on Remote Machine With Powershell

I need to call a remote VB script from Powershell, and the VB script needs to run on the remote machine.
I have been using \$computer\root\cimv2:Win32_Process").Create(C:\test.vbs)
This works, however I can't get a return value from the script, just a return value from the win32 process.
I would convert the whole thing to powershell, but can't as I'm connecting to a legacy domain I can't install additional tools on so have to call the remote vbscript
This is an old question but I would like to share my solution. It's the same as the one posted by Ansgar but it's been tested and working fine:
$VNC = '\\share\software\AppName\_Install_Silent.vbs'
$Computer = 'RemoteHost'
$TMP = "\\$Computer\c$\TEMP"
if (!(Test-Path $TMP)) {
New-Item -Path $TMP -ItemType Directory
}
Copy-Item -LiteralPath (Split-Path $VNC -Parent) -Destination $TMP -Container -Recurse -Force -Verbose
$LocalPath = Join-Path 'C:\TEMP' (Join-Path (Split-Path $VNC -Parent | Split-Path -Leaf) (Split-Path $VNC -Leaf))
Invoke-Command -ScriptBlock {cscript.exe $Using:LocalPath} -Computer $Computer
# Restart might be needed of remote host
The difference is that you have to copy the files first to the remote machine to avoid the double hop issue and then you can install it with the $Using variable.
Hope this helps someone.
I'd probably try either remote invocation:
Invoke-Command -ScriptBlock { cscript.exe "C:\test.vbs" } -Computer $computer
or PsExec:
PsExec \\$computer cscript.exe "C:\test.vbs"
Can't test either of them right now, though.