I'm making a PowerShell script that will allow the user to move certain local files to a certain server. To ease the process I want to check if the user has access to the server or not, and if not, I want to prompt for a username/password.
Using Test-Path I can check whether or not the user can access specific remote location. However, if Test-Path fails, there is no way of knowing if it's because the remote location does not exist, or because the user does not have sufficient rights.
I'm looking for a way to:
Find out if the user has access to a remote location (could use Test-Path for this)
(if above failed) Find out if this is because the remote location is unavailable or because the user does not have sufficient rights
(depending on above) Show error message or prompt for credentials
Of course I could Test-Path, ask for credentials if necessary, and then Test-Path again. But I'm trying to find a nicer solution.
You can use Test-Connection to see if the server exists. This is not a fool-proof method though because not all servers and other devices that may be in the network path respond to ICMP requests, which is what Test-Connection and ping use.
Related
I need to query some WMI values using PowerShell from Windows 10 devices. The script is executed in the context of a non-admin user by some software distribution tooling.
There is a local admin account, and for the current purpose (retrieving information before wiping the system) it wouldn't be a problem to put the password in the script. As automation is a hard requirement, there is no way to deal with UAC windows or the user to enter some credentials.
Is there any way to get
$sess = New-CimSession -Credential $admincred
to work without running into Access is denied, because it isn't run in an elevated context? Can I somehow self-elevate it by just having the admin credentials?
[Edit]
The comments asked to provide more concrete information:
I want to onboard many unmanaged (i.e. no software distribution tool, no domain join) Windows 10 devices to Windows Autopilot.
The devices are not at a specific site.
The device vendor can't provide the information.
The users don't have administrative privileges
The users don't know the local admin password (I do)
Exposing the local admin password is less of a problem than the missing tech knowledge of the users (the password is considered legacy)
The firewall is preventing incoming traffic (no RDP, WinRM)
Code (Source):
$devDetail = (Get-CimInstance -CimSession $session -Namespace root/cimv2/mdm/dmmap -Class MDM_DevDetail_Ext01 -Filter "InstanceID='Ext' AND ParentID='./DevDetail'")
It is too time consuming to get the information using manual remote sessions with a tool like Teamviewer. Getting the users to download a tool from the intranet and running it would be a way to go. So I created a standalone application that builds and runs a customized PowerShell script. What won't work is getting it to run in an elevated session. I always end up with Access denied.
Can I somehow self-elevate it by just having the admin credentials?
No you cannot. UAC is designed to prevent exactly what you are trying to do. Related Q&A:
elevate without prompt - verb runas start-process
UAC Getting in the Way of EXE Install Powershell
Powershell provide credentials for RunAs
There may be many workarounds, but they all will have in common that you have to go to your machines (locally or remotely) at least once, gain administrative privileges and prepare something, e. g.:
A scheduled task that runs under your local administrator account or under SYSTEM and triggers the execution of your script
Disabling UAC (temporarily) (not recommended either way)
Installing any remote management software, services or accounts (with extra run as background job privilege)
I want to create a powershell script. One of our supporting companies needs to connect to our server from time to time to make their work and I need to connect their RDP session to watch them if their doing is OK.
Server: MS Server 2012 R2 x64
The case is I want to create a script which;
1- Checks the server's current sessions
2- Finds the specific session ID come from the username (the which I will give them to connect) currently logged in as RDP
3- When I pull the correct session ID from the username (and that means he is currently online and connected), I want to shadow his/her session without prompting/requesting their approvals.
Yes, I can do these separately but looking a powershell script or something like that to these. In one attempt, I want to shadow rdp to correct session and if he/she is not online, I want the system return an information message to me that the username is not currently online.
Is it possible?
Thanks&Regards
Melih
If memory serves PoSh does not natively supports querying RDP sessions (unless using the RDS broker, but I could be wrong here) but you can easily do that via query session
I cannot test it right now but something like this should do the trick:
C:\>query session
SESSIONNAME USERNAME ID STATE TYPE DEVICE
console Administrator1 0 active wdcon
rdp-tcp#1 User1 1 active wdtshare
rdp-tcp 2 listen wdtshare
You can even call it with the username directly if that is known to you.
Shadowing the session would be easily accomplished with something like
mstsc /v:"$srv" /shadow:"$id" /control /noconsentprompt
I did not test this so maybe it needs some tweaking but a possible starting point could be
$userSessions = query session user01 /SERVER:server01 | Select-Object -skip 1 | ForEach-Object{$_.Split(' ',[System.StringSplitOptions]::RemoveEmptyEntries)}
$sessionId = $userSessions[2]
mstsc /v:"$srv" /shadow:"$sessionId" /control /noconsentprompt
Of course if running from the local server you can omit the /SERVER:XXX argument.
Hope this can help getting you started.
I need to know the logic behind AD cmdlets for deciding which server will handle the request.
The background is an temporary error message:
"A connection to the directory on which to process the request was unavailable. This is likely a transient condition."
I need to know which ADWS server is having the problem.
Note: i don't want to specify a server using the -Server property, i want to analyse the defect server
Try same with -verbose Switch. It should show you the connected DC.
I am trying to create a powershell startup script for my domain controlled computers that will place the computer into the the specified OU. I would like for the variables to be taken on the local computer and then passed to the remote server. Once there I would like to execute the last two lines on the server.
The script below does work if it is ran on the server however as stated above I would like to be able to execute this from a client machine. How can I make this happen?
$computername = $env:ComputerName
$new_ou = "OU=TestOU,DC=Test,DC=Controller,DC=com"
Import-Module ActiveDirectory
Get-ADComputer $computername | Move-ADObject -TargetPath $new_ou
Note: Before anyone asks...my goal is to have the OU be determined by the client IP address. I understand that there are scripts that will do the discribed above but they run strictly on the server and query the DNS. I would rather have this run as a startup script on the local computer so I an better control which computers are being moved. At this point I am not interested in tackling this issue. Only the issue of how to execute the above lines on a local machine.
I assume you want to run the last 2 lines on the server because you expect that most of your domain computers won't have the RSAT tools or AD cmdlets installed.
The way to run it on a server is to have PowerShell Remoting enabled on the server and then use Invoke-Command.
That authentication is typically done with kerberos, though you could change the method, and you can supply credentials manually (though I doubt you want to be embedding credentials in the script).
You need to consider that the user making the AD changes needs permission to do so. Usually that's a domain admin, although permission could be delegated.
If you're running this as a startup script, it's running as SYSTEM. That account authenticates on the domain as the computer account (COMPUTERNAME$). This means that the computer account needs permission to move itself, which may mean it needs the ability to write objects into all possible OUs (I don't recall offhand which permissions are needed).
So you would either need to grant this ability to all computers (any computer in Domain Computers would have the ability to move any other computer to any OU), or somehow give each computer only the ability to move itself into the correct OU (which might still be too much in the way of permissions).
Another option is to make a customized session configuration on the server with a RunAs user. You could limit the users allowed to connect to the session (to Domain Computers), and limit the allowed commands so that the connecting computers can only run a limited set of functions/cmdlets. Even better, you can write your own function to do the change and only let them run that one. With the RunAs user being a privileged user in AD, the changes will work without the connecting user having the ability to make the changes directly, and without giving the connecting user the ability to use the privileged user or elevate their own permission. Remember that the connecting user in this case is the computer account.
This last method is, I think, the best/most secure way to do what you want, if you insist that it must be initiated from the client machine.
Reconsider doing this as a server-side process. Get-ADComputer can return an IPv4 address for the object, so you could use that instead of DNS. Centralizing it would make it easier to manage and troubleshoot the process.
How would I check if my credentials are already cached for a specific server using tf.exe? I am trying to do slight automation for tfs get and workspace/workfold configuration. The assumption is that most machines already have the credentials cached, but I want to be able to double check beforehand, and throw an error in powershell if they are not.
Thank you,
Derongan
Try using vaultcmd.exe e.g.:
vaultcmd /listcreds:"Windows Credentials" /all
You could run that through a Where-Object command looking for a string that matches the TFS server name.