How to check network folder exist with credentials using powershell 5 - windows

Lest say there is a network folder \\my_server\my_root\my_dir.
To access this folder these credentials required username: my_doman\my_user password: my_password.
Now in my program first it try to map network folder to a local drive. If there is a exception, it consider as folder not exist. I think this is not a good way.
Is there a way to check this folder exist without try to map to a local drive? I'm looking for something like
[System.IO.Path]::Exist("\\my_server\my_root\my_dir","my_doman\my_user","my_password")
I'm using Powershell 5
This is how I map the drive now
try{
$net = new-object -ComObject WScript.Network
$net.MapNetworkDrive($free_drive, $network_dir, $false, "domain\user", "password")
}catch{
Write-host: "folder does not exist"
}

Using New-PSDrive:
New-PSDrive -Name Q -PSProvider FileSystem -Root \\my_server\my_root\my_dir -Credential my_domain\my_user -Persist
Old School method using cmdline utility:
net use \\my_server\my_root\my_dir /user:my_domain\my_user my_password
start \\my_server\my_root\my_dir
For mapping you can use this:
$net = New-Object -comobject Wscript.Network
$net.MapNetworkDrive("Q:","\\my_server\my_root\my_dir",0,"my_domain\my_user","my_password")
For testing the path, you can use:
Test-Path \\my_server\my_root\my_dir
Note:You will get a boolean value in return from the test path.
Hope it helps.

Assuming that on the machine executing the script you're able to log in as the user under which you want to connect to the remote share, you could use Invoke-Command to invoke Test-Path as another user:
$pathExists = Invoke-Command -ComputerName . -Credential $credentials -ScriptBlock {
Test-Path -Path "\\my_server\my_root\my_dir"
}
if ($pathExists)
{
# my_dir\ exists
}
else
{
# my_dir\ is inaccessible/non-existent
}
I'm not in a position to test this at present but I suspect you may need to include -Authentication Credssp as a parameter to Invoke-Command (assuming the necessary environment for that is in place) due to the double-hop problem.
Of course, if you're checking for the existence of that directory under another user in order to make decisions for future filesystem operations to be executed as that same user, you would then need to Invoke-Command another batch of operations or include them after Test-Path. At that point you might be better off connecting to the share under alternate credentials in the usual way. It's just the difference between executing as another user and connecting as another user, each with their own pros and cons.

I was having the same problem checking the folder and/or file existence on a remote server before copying the file from deployment server. Nothing worked for me and ended up in a huge frustration.
I then tried this...
$pathExists = Invoke-Command -ComputerName <remoteServerName> -Credential $credentials
-ScriptBlock {
Test-Path -Path <AbsolutePath> "UNC path does not work here and you must use Absolute
path. eg. instead of \\Server use D:\Dir1 or D:\Dir1\File1.bat"
}
if (-not ($pathExists))
{
write-host "Directory or File does not exist"
}
else
{
write-host "Directory or File exist"
}
This worked just fine for me after using the absolute path in the Test-Path. For some reason the UNC path does not work! Hope, this helps someone!

Related

Install Offline Windows Updates(.msu) to remote servers

I'm trying to get a script together to remotely install some windows updates on some remote servers that are connected in an offline domain.
I have tried regular PS Remoting and after some research, I think what I am trying to do isnt supported by microsoft. When checking my event logs I have a bunch of these errors.
Edit
I wanted to add that I have tried running the .\Install2012R2.ps1 script from my local computer, modified to have the Invoke-Command in that and have it run the update portion of the original Install2012R2.ps1 and I would get the same errors.
I was hoping that by placing the script on each server that it would like that more.
End Edit
Windows update could not be installed because of error 2147942405 "Access is denied."
(Command line: ""C:\Windows\System32\wusa.exe" "C:\Updates\windows8.1-kb4556853-x64.msu" /quiet /norestart")
I have tried running Invoke-Command as credentialed to an administrator account on the servers but I have been having no luck and was looking for some advice if someone has maybe tried/done this before.
$Servers = #("V101-Test1","V101-Test2")
$Username = 'admin'
$Password = 'Password'#not actual password
$pass = ConvertTo-SecureString -AsPlainText $Password -Force
$Cred = New-Object System.Management.Automation.PSCredential -ArgumentList $Username,$pass
Get-PSSession | Remove-PSSession
New-PSSession -ComputerName $Servers
foreach($Server in $Servers){
Get-ChildItem -Path C:\Source\Temp -Recurse | Copy-Item -Destination "\\$Server\c$\Updates\" -Force
}
Invoke-Command $Servers -Credential $Cred -ScriptBlock{
& "C:\Updates\Install2012R2.ps1"
}
EDIT 2
Here is the actual install code of the Install2012R2.ps1 script
$updatedir= "./"
$files = Get-ChildItem $updatedir -Recurse
$msus = $files | ? {$_.extension -eq ".msu"}
$exes = $files | ? {$_.extension -eq ".exe"}
foreach ($file in $msus){
$KBCtr++
$fullname = $file.fullname
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
$KBN = $fullname.split('-')[1]
# Need to wrap in quotes as folder path may contain space
$fullname = "`"" + $fullname + "`""
# Specify the command line parameters for wusa.exe
$parameters = $fullname + " /quiet /norestart"
# Start services and pass in the parameters
$install = [System.Diagnostics.Process]::Start( "wusa",$parameters )
$install.WaitForExit()
}
I'm not sure why wusa.exe is failing here with Access Denied, but here is a PowerShell-native approach you can try. If nothing else, it should give you a clearer indication via the captured error information as to what the underlying issue is:
Add-WindowsPackage -Path C:\Updates\OurHeroicUpdate.msu -Online -PreventPending -NoRestart
-Path is the path to the msu file
-Online tells Add-WindowsPackage to modify the currently "mounted image" (the running version) of Windows (as opposed to an offline disk image you could also apply it to)
-PreventPending prevents installing the msu if there is already a pending change, like needing to reboot for updates.
Add-WindowsPackage is part of the DISM module available under Windows PowerShell, and is the functional equivalent of dism /packagepath:"cabfile", although it can take an msu where dism.exe only allows a cab.

Find if a program is installed on remote computer

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.

Log in to a DC with local user

Short but complicated question : is there any way to log on to a Domaincontroler with Servername\Username?
Ive got a Script wich specificly uses a Local Account (since 99% of our Servers are not in a Domain + you can create Local user accounts on almost Every Windows machine, but not on a DC sadly).
So basicly what im asking is : is there a way to trick a DC to accept Servername\Username as a domain login? is there a way by rights? Changing the Script is not an option sadly since the infrastructure behind it is too big to change, and i dont want to add a server specific exception.
Update : It worked on 2 2003 DCs but still no luck with the 2008 DC. is/was there a Change in microsofts server Policy?
the Script part im Using :
$SecurePassWord = ConvertTo-SecureString -AsPlainText $($Row['Passwort']) -Force
$Cred = New-Object -TypeName "System.Management.Automation.PSCredential" -ArgumentList "$($Row['ServerName'])\$($Row['Benutzername'])", $SecurePassWord
$pssessionoption = new-pssessionoption -operationtimeout 7200000 -IdleTimeout 7200000
Try {
$Session = New-PSSession -ComputerName $($Row['ServerName']) -credential $Cred -sessionOption $pssessionoption -EA Stop
Remove-PSSession -Session $Session
}
Catch [system.exception]
{
write-host "not working"
}
Anybody has an Explanation?
No, you cannot create a local users on a DC and therefore cannot use local credentials. Ever. This question should really be Server Fault.

Run code block locally as a different user in powershell script

This is something incredibly simple, but I just can't get anything to work. I want to run a block code in a powershell script under a specific user. The keyword is locally and I'm using powershell 2.0.
Invoke-Command seems to require a remote host? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Invoke-Command -ComputerName "." -scriptblock {
write-output "HI!"
} -Credential $cred
Start-Job with -ScriptBlock isn't supported with powershell 2.0? I run the following and the error message that I see seems to suggest as much:
$strScriptUser = "DOMAIN\USER"
$strPass = "PASSWERD"
$PSS = ConvertTo-SecureString $strPass -AsPlainText -Force
$cred = new-object system.management.automation.PSCredential $strScriptUser,$PSS
Start-Job -ScriptBlock {
write-output "HI!"
} -Credential $cred
Am I doing something wrong, or is there an alternative way?
Added: Here is what I'm trying to do in the first place. I'm making a scheduled task that runs when a user logs into/unlocks a terminal that writes logon information to a file. The scheduled task runs as the local user in order to get at the username, profile, etc. information. The logon information is then written to a log file using a different user account, which is the only account that can modify the file. To deter access to the logon credentials in the script I convert the script to an EXE using PS2EXE.
Here is another way.
# Get the other user's credentials
$credential = Get-Credential
# Execute a scriptblock as another user
$commands = #'
$env:username
# ... more commands ...
'#
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-Command', $commands
# Execute a file as another user
$script = '.\path\name.ps1'
Start-Process -FilePath Powershell -LoadUserProfile -Credential $credential -ArgumentList '-File', $script
With the -LoadUserProfile switch, this has the added benefit of creating the user's profile if it does not already exist.
Another approach is impersonation, it is good option if you are not willing to enable remoting.
Check this and this out.
You should just put your code between
Push-ImpersonationContext $credential
and
Pop-ImpersonationContext
It would help to see the error messages you're not showing us, but I think the answer to your question is to use PowerShell Remoting as you tried with Invoke-Command. The computer name . is fine as is localhost but you do have to have remoting enabled on your machine to do it.
To enable remoting, run Enable-PSRemoting within powershell, or run winrm quickconfig in a regular command prompt.
If you already have remoting enabled, then you might be trying to do the remoting with a non-administrative user. If that's the case, take a look at the output of Get-PSSessionConfiguration. You'll get a list of endpoints and the permissions that are applied.
The endpoint you're connecting to by default is called Microsoft.Powershell and you could change the permissions with Set-PSSessionConfiguration (be sure to use the -ShowSecurityDescriptorUI parameter unless you want to mess with SDDL).
But instead of doing that, there should already be a group given access called BUILTIN\Remote Management Users which you can add your limited user to.
If none of this helps, give more details and error messages.
Edit
After seeing the explanation of what you're ultimately trying to accomplish, I have another suggestion for you.
Your existing scheduled task writes the information to a known location.
A different scheduled task running under the privileged user account picks up that information and puts it into the file that the limited user cannot access.
Bonus: start the second task from the first task.
This could be a quick compromise to do what you want without remoting and without exposing the credentials of the privileged user.
Issues with the current approach:
The major problem I have with your original idea is that you're going to need to embed the credentials into the script, so the limited user will have access to the credentials of the account that can modify the file anyway.
Ideally:
You would have a web service that you could invoke with your limited-user powershell script in which you can only give it the login information and not get anything back. So you'd hit a URL and do a POST or whatever with the data that you want to log, but that user can't ever retrieve any info. It might be a bit beyond what you're willing to do for this.

Handle command for remote pc

I want to run handle for a specific folder for a remote pc at my network so to know which processes are locking the folders.
tried:
handle /accepteula \\remotePcName\c:\myFolder
handle /accepteula \\remotePcName\User(name of the account)\c:\myFolder
and some other combinations with no luck getting
No matching handles found.
Is it possible to do this? Run handle for a remote pc?
Could you please try like this:
c:\powershell\Tools\psexec.exe \\remotePcName C:\handle.exe c:\myFolder
How about using invoke-command to execute 'handles' remotely?
$serverName = 'serverName'
$pathtoCheck = 'C:\temp' # folder you want to check on the remote server.
$pathtoHandle = 'c:\temp\handle.exe' #location of handle.exe on the remote server.
Invoke-command -ComputerName $serverName -Scriptblock {
param(
[string]$handles,
[string]$pathToCheck
)
"$handles /accepteula $pathToCheck" | Invoke-Expression
} -ArgumentList $pathtoHandle,$pathtoCheck

Resources