使用备用凭据的Copy-Item

44

我正在使用powershell v2的CTP。我编写了一个需要访问dmz中的各种网络共享并复制一些文件的脚本。然而,我的问题是明显powershell的cmdlets如copy-item、test-path等不支持备用凭据...

有没有建议如何最好地完成我的任务..?


这里有一个类似的问题。https://dev59.com/qnVD5IYBdhLWcg3wWKLc - notandy
13个回答

49
最近我遇到了这个问题,在最新版本的Powershell中有一个新的BitsTransfer模块,它允许使用BITS进行文件传输,并支持使用-Credential参数。
以下示例展示了如何使用BitsTransfer模块将文件从网络共享复制到本地计算机,使用指定的PSCredential对象。
Import-Module bitstransfer
$cred = Get-Credential
$sourcePath = \\server\example\file.txt
$destPath = C:\Local\Destination\
Start-BitsTransfer -Source $sourcePath -Destination $destPath -Credential $cred

另一种处理方式是使用标准的"net use"命令。然而,该命令不支持"securestring"密码,因此在获取凭据对象后,您需要获取解密版本的密码以传递给"net use"命令。

$cred = Get-Credential
$networkCred = $cred.GetNetworkCredential()
net use \\server\example\ $networkCred.Password /USER:$networkCred.UserName
Copy-Item \\server\example\file.txt C:\Local\Destination\

只是插一句话,我尝试了BITS部分,它像魔法般地运行良好。 - Marcus
我需要执行 Complete-BitsTransfer 命令来等待其完成,还是它默认是同步的? - jpmc26
5
请注意,这种方法无法处理像 \\server\C$ 这样的位置。请参考 http://serverfault.com/q/512558/172060。 - jpmc26
3
我认为BITS传输并不像你所说的那样工作。我正在使用PowerShell 2,仍然需要在使用BITS之前使用“net use”创建映射,否则它(很明显)会显示UNC路径不存在。因此,在我的脚本中,我执行以下操作:使用“net use”添加路径......bits...然后使用“net use /delete”。 - Santhos

36

由于PowerShell在许多cmdlet中不支持使用“-Credential”参数(非常令人烦恼),而通过WMI映射网络驱动器被证明在PS中非常不可靠,因此我发现通过net use命令预缓存用户凭据可以很好地解决问题:

# cache credentials for our network path
net use \\server\C$ $password /USER:$username

使用路径中的 \\server\C$ 的所有操作似乎都可以使用 *-item cmdlet 完成。

完成后,您还可以删除共享:

net use \\server\C$ /delete

1
这似乎是\\server\C$样式路径的唯一选择。 - jpmc26
尽管它似乎可以工作,但每次我从网络路径调用Copy-Item时,它都会提示我输入用户名和密码,这非常令人烦恼。 - Jim Aho
@JimAho 对我来说它没有提示用户名和密码。 - digz6666

27

PowerShell 3.0 现在支持 FileSystem 提供程序上的凭据。要使用替代凭据,只需在 New-PSDrive cmdlet 上使用 Credential 参数即可。

PS > New-PSDrive -Name J -PSProvider FileSystem -Root \\server001\sharename -Credential mydomain\travisj -Persist

执行此命令后,您现在可以访问新创建的驱动器并执行其他操作,包括像普通驱动器一样复制或移动文件。以下是完整解决方案:

$Source = "C:\Downloads\myfile.txt"
$Dest   = "\\10.149.12.162\c$\skumar"
$Username = "administrator"
$Password = ConvertTo-SecureString "Complex_Passw0rd" -AsPlainText -Force
$mycreds = New-Object System.Management.Automation.PSCredential($Username, $Password)

New-PSDrive -Name J -PSProvider FileSystem -Root $Dest -Credential $mycreds -Persist
Copy-Item -Path $Source -Destination "J:\myfile.txt"

1
对我来说很完美!谢谢分享! - Fals

8

这是一个老问题,但是我为了未来的查找进行更新。

现在PowerShell v3支持使用-Credential参数进行文件系统操作。

希望这能帮助其他正在寻找同样解决方案的人。


11
似乎“-credential”参数仅适用于文件系统提供程序的New-PsDrive命令。在v3上,使用copy-item命令仍无法工作。 - CB.
没错,这是因为copy-item针对PSDrives起作用。您必须使用不同的凭据重新挂载驱动器,或者创建一个新的PSDrive到相同的远程资源,但由于底层操作系统的限制(即,在同一会话中为相同的远程资源使用不同的网络凭据),这可能有时会失败。 - x0n

6
我会尝试映射远程系统的驱动器(使用'net use'或WshNetwork.MapNetworkDrive,这两种方法都支持凭据),然后使用copy-item命令。

这是最佳答案,因为文件系统提供程序(因此包括copy-item)不支持凭据。 - halr9000

2
这是我的脚本,它在一台机器上以LocalSystem身份运行,但需要域用户的凭据才能访问网络文件位置。它允许您将用户的密码存储在一个“相对安全”的加密文件中;只有编写该文件的用户才能读取它。
通过将包含明文密码的文件复制到计算机上来设置和更改密码。下次运行脚本时,它会读取密码,加密它,然后删除明文密码。
$plaintext_password_file = 'C:\plaintext.txt' # Stores the password in plain text - only used once, then deleted
$encryted_password_file = 'C:\copy_pass.txt'  # Stores the password in "safe" encrypted form - used for subsequent runs of the script
                                              #   - can only be decrypted by the windows user that wrote it
$file_copy_user = 'OURDOMAIN\A_User'

# Check to see if there is a new plaintext password
if (Test-Path $plaintext_password_file)
{
    # Read in plaintext password, convert to a secure-string, convert to an encrypted-string, and write out, for use later
    get-content $plaintext_password_file | convertto-securestring -asplaintext -force | convertfrom-securestring | out-file $encryted_password_file
    # Now we have encrypted password, remove plain text for safety
    Remove-Item $plaintext_password_file
}


# Read in the encrypted password, convert to a secure-string
$pass = get-content $encryted_password_file | convertto-securestring

# create a credential object for the other user, using username and password stored in secure-string
$credentials = new-object -typename System.Management.Automation.PSCredential -argumentlist $file_copy_user,$pass

# Connect to network file location as the other user and map to drive J:
New-PSDrive -Name J -PSProvider FileSystem -Root "\\network\file_directory" -Credential $credentials

# Copy the file to J:
Copy-Item -Force -Verbose -Path "C:\a_file.txt" -Destination "J:\"

作为额外的改进:用户名也可以加密,而不是硬编码。

2
新版本的PowerShell可以处理此问题,MS文档提供了一个很好的示例 在此处使用不同凭据复制文件
$Session = New-PSSession -ComputerName "Server02" -Credential "Contoso\User01"
Copy-Item "D:\Folder002\" -Destination "C:\Folder002_Copy\" -ToSession $Session

2

0

再次将其从死亡中带回来。我通过将.ps1文件包装在批处理文件中并执行Win7,Shift + r.点击RunAs的方式解决了类似凭据问题。如果您愿意,也可以使用PsExec:

psexec.exe /accepteula /h /u user /p pwd cmd /c "echo. | powershell.exe -File script.ps1"

0

这里有一篇文章,其中有人让它工作了。看起来需要更改注册表。


1
那个人在同一个域内进行了双重跳转。由于我正在访问完全不同的域上的文件,所以我需要能够指定一个帐户... - xspydr

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接