我希望能够远程进入系统并在那里压缩或解压缩文件,并在完成时获得过程信号.启动过程使用-wait参数从PowerShell同步运行7z.exe.当我尝试将它与invoke-command结合使用以远程运行相同的命令时,它不支持wait参数,我相信它会杀死进程,因为它快速返回并且从不生成zip文件.
[string]$sevenZip = "C:\Program Files\7-zip\7z.exe"
[Array]$arguments = "a", $zipFilename, $dirToZip;
"Starting $sevenZip with $arguments"
Start-Process $sevenZip "$arguments" -Wait
#blocks and waits for zip file to complete
Run Code Online (Sandbox Code Playgroud)
我最初尝试过PSCX write-zip和expand-archive,但后者与64位.NET 4.0配置不兼容.所以现在我试图通过命令行调用64位7z.exe.我没有收到任何错误.PowerShell将作业报告为运行状态,然后完成,并且不会生成任何zip文件.
Invoke-Command -ComputerName localhost -FilePath 'C:\Scripts\ZipIt.ps1' -ArgumentList 'd:\TestFolder','d:\promote\TestFile.7z' -AsJob
Run Code Online (Sandbox Code Playgroud)
感谢任何帮助或指针.
谢谢,格雷戈里
有没有一种方法可以使用Powershell Start-Process cmdlet启动新的Powershell会话并传递带有局部变量的脚本块(其中一次将是数组)?
例:
$Array = @(1,2,3,4)
$String = "This is string number"
$Scriptblock = {$Array | ForEach-Object {Write-Host $String $_}}
Start-Process Powershell -ArgumentList "$Scriptblock"
Run Code Online (Sandbox Code Playgroud)
谢谢。
出于某种原因,在远程计算机上通过invoke命令运行时,Start-Process msiexec将无法工作.我查了一下,虽然有些人建议使用psiexec我看到很多人使用普通的旧invoke-command在远程机器上启动msi安装程序.
这是我目前使用的代码:
$session = New-PSSession -computername $computerName -ea stop
$command = {
Param(
[Parameter()]
[string]$computerName,
[Parameter()]
[string]$domain,
[Parameter()]
[string]$user,
[Parameter()]
[string]$password,
[Parameter()]
[string]$installDir
)
$msiArgumentList = "/i C:\Installer.msi /l c:\log.txt /quiet /qr /norestart IAGREE=Yes DOMAIN=$domain ACCOUNT=$user PASSWORD=$password PASSWORDCONFIRM=$password INSTALLDIR=$installDir"
Start-Process msiexec -ArgumentList $msiArgumentList -Wait
}
Invoke-Command -session $session -ScriptBlock $command -ArgumentList $computerName, $domain, $user, $password, $installDir
Remove-PSsession -session $session
Run Code Online (Sandbox Code Playgroud)
我使用相同的方法使用intallutil远程安装服务,它工作正常.在目标计算机上启用脚本以及远程处理,以便所有帐户都能正常工作.两台计算机都具有相同的凭据,但我仍尝试向invoke-command和pssession添加凭据.我在本地测试了代码,安装工作正常.远程它没有,也没有错误.我可以在taskmanager的目标机器上看到msiexec已启动但没有任何反应.我甚至试过禁用防火墙,但仍然没有.我试过&运算符启动msiexec但仍然没有.
不确定我还能尝试什么.
我在远程计算机上创建了一个pssession并输入了这个属性.在该会话中,我使用start-process启动记事本.我可以确认记事本是使用get-process命令运行的,还是使用远程计算机中的taskmgr运行.但是,该过程的GUI端未显示.这是我一直在使用的序列:
$server = New-PSSession -ComputerName myserver -Credential mycreds
Enter-PSSession $server
[$server]: PS C:\>Start-Process notepad -Wait -WindowStyle Maximized
Run Code Online (Sandbox Code Playgroud)
该过程正在运行,但是当RDP到框时,记事本无法打开.如果我从服务器打开记事本,则会开始一个新的记事本过程.我也试过使用这样的动词参数:
[$server]: PS C:\>Start-Process notepad -Wait -WindowStyle Maximized -Verb Open
Run Code Online (Sandbox Code Playgroud)
同样的结果......过程开始,但没有记事本显示.我已经尝试了这个远程进入盒子(但是从我的本地主机发出)以及远程进入服务器之前.
我了解 PowerShell 作业,但我想使用启动进程并将可序列化的对象传递给新的 powershell 进程。有什么办法可以做到这一点吗?
看来使用启动进程你必须提供一个字符串参数列表,这对我来说不会减少它。我正在尝试从一个进程获取 PSCredential 到另一个进程(或 SecureString,我将采用其中之一)。也许这会规避安全性。
更新 - 添加我在看到其他人的帮助后使用的解决方案(使用来自@PetSerAl的解决方案)
我编写了两个测试脚本:父脚本和子脚本。父脚本调用子脚本。
父脚本:
$securePassword = ConvertTo-SecureString "testpassword" -AsPlainText -Force
$cred = New-Object PSCredential("testuser", $securePassword)
$credSerial = [Convert]::ToBase64String([Text.Encoding]::UTF8.GetBytes([Management.Automation.PSSerializer]::Serialize($cred)))
$psFile = "C:\repos\Test\PowerShell Scripts\KirkTestChild.ps1"
$p1 = "-someparam ""this is a test!!!"""
$p2 = "-cred ""$credSerial"""
$proc = Start-Process PowerShell.exe -PassThru:$true -Argument "-File ""$($psFile)""", $p1, $p2
Write-Host "ID" $proc.Id
Write-Host "Has Exited" $proc.HasExited
Start-Sleep -Seconds 15
Write-Host "Has Exited" $proc.HasExited
Run Code Online (Sandbox Code Playgroud)
子脚本:
Param(
$someParam,
$cred
)
Write-Host "someParam: $($someParam)"
Write-Host "cred (raw): $($cred)"
$realCred=[Management.Automation.PSSerializer]::Deserialize([Text.Encoding]::UTF8.GetString([Convert]::FromBase64String($cred))) …Run Code Online (Sandbox Code Playgroud) Powershell cmdletStart-Process的行为很奇怪:
当我启动另一个控制台进程并指定 时-NoNewWindow,ExitCode 属性(一个int!)为空。
这是一个测试:除了 之外,与其他东西相同cmd。本次测试是在Win10和PS5上进行的,Win7和PS5也是如此:
PS C:\Users\Martin> cmd.exe /Cver
Microsoft Windows [Version 10.0.15063]
PS C:\Users\Martin> $PSVersionTable
Name Value
---- -----
PSVersion 5.1.15063.296
PSEdition Desktop
PSCompatibleVersions {1.0, 2.0, 3.0, 4.0...}
BuildVersion 10.0.15063.296
CLRVersion 4.0.30319.42000
WSManStackVersion 3.0
PSRemotingProtocolVersion 2.3
SerializationVersion 1.1.0.1
PS C:\Users\Martin> $pNewWindow = Start-Process -FilePath "cmd.exe" -ArgumentList '/C"exit 42"' -PassThru
PS C:\Users\Martin> $pNewWindow.WaitForExit()
PS C:\Users\Martin> $pNoNewWindow.HasExited
True
PS C:\Users\Martin> $pNewWindow.ExitCode
42
PS C:\Users\Martin> $pNoNewWindow = Start-Process -FilePath "cmd.exe" -ArgumentList '/C"exit …Run Code Online (Sandbox Code Playgroud) 我想cmd.exe在不同的用户下运行一个常规脚本。
我已经使用过Start-Process,当脚本执行时,它只是用不同的用户在屏幕上打开提示,但不处理$command.
cmd.exe所以我的问题是“使用PowerShell运行后如何传递命令?
这是我到目前为止所拥有的:
$username = "abc"
$pwd = ConvertTo -SecureString "xyz" -AsPlainText -Force
$cred = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $username $pw
$command = "filepath/.groovy"
try {
Start-Process 'cmd' -Credential $cred -ArgumentList $command
Write-Host $LASTEXITCODE
if($LASTEXITCODE -ne 0) {
throw "Error occured"
} else {
return 0
}
} catch {
Write-Error "Error Desc:$_Error.InnerException.Message";
}
Run Code Online (Sandbox Code Playgroud) 我在 Windows 10 上有这个简单的脚本,它在执行时工作正常,但从任务计划程序运行时无法启动记事本。Stop-Process 完美运行,Start-Process 不运行。当我按需运行它时,它会关闭记事本,然后在不打开记事本的情况下继续运行,该任务也不会关闭。
Stop-Process -processname notepad
Start-Process "C:\Windows\system32\notepad.exe"
Run Code Online (Sandbox Code Playgroud)
这是它被配置为运行的方式。
我尝试过的事情,但仍然不起作用。
-ExecutionPolicy Bypass和-ExecutionPolicy RemoteSignedLogon as batch工作权限当我调用以下代码时:
Start-Process Firefox
Run Code Online (Sandbox Code Playgroud)
然后,PowerShell打开浏览器。我可以使用其他几个程序来做到这一点,并且可以正常工作。我的问题是:如果键入Firefox,PowerShell如何知道要打开哪个程序?我的意思是,我没有使用具体的路径或其他内容...
我虽然与环境变量有关……但是我在那里找不到任何名为Firefox的变量……他怎么知道?
我正在使用预定的 PowerShell 脚本在循环中多次使用各种参数启动相同的进程。过程计算量很大,运行时间很长,我有数千次迭代。我注意到,因为它是一个预定脚本,所以它以低于正常的优先级运行。即使我碰到它,任何产生的进程仍然低于正常。因此,由于我在循环中运行此过程数千次,因此我需要-Wait像这样使用:
foreach($list in $lists){
Start-Process -FilePath $path_to_EXE -ArgumentList $list -NoNewWindow -Wait
}
Run Code Online (Sandbox Code Playgroud)
现在,我想提高优先级,我发现的一种方法是这样做:
($MyProcess = Start-Process -FilePath $path_to_EXE -ArgumentList $list -NoNewWindow -Wait -PassThru).PriorityClass = [System.Diagnostics.ProcessPriorityClass]::AboveNormal
Run Code Online (Sandbox Code Playgroud)
但是,它不起作用,因为它需要等到进程完成,然后执行括号外的任何内容:(...).PriorityClass = ...
我不能让它继续循环并产生数千个进程,我需要一次运行一个,但是我如何告诉它提高优先级,然后等待?