Je suis assez novice en matière de PowerShell, mais j'essaie de m'y retrouver. Voici le résumé de ce que je veux faire :
- 400 ordinateurs, dont pas plus de 5 sur un site physique, connectés par des vitesses assez faibles à travers un VPN.
- Tous ont une seule application avec une seule version (mais sur Windows XP et Windows 7) qui doit être supprimée en raison d'exigences de conformité.
-
J'ai essayé d'utiliser quelque chose comme ce qui suit, sans grand succès :
function Terminate-Process {
param( \[Parameter(Mandatory=$true,valuefrompipeline=$true)\] \[string\]$compname) begin {$processname = Read-Host "Process Name I Want To Kill"} process {
$result = Get-WmiObject -Class win32_Process -Filter "name='$processname'" -ComputerName (Get-Content computers.txt) | ForEach-Object { $_.Terminate() } if ($result.ReturnValue -eq 0 )
{ Write-Output " $($processname) terminated on $($compname) "} else { Write-Output "could not terminate $($processname) on $($compname) "}}
end{Write-Output "Script ...END"}
}
Start-Sleep -s 60
Get-Content Computers.txt | .\Get-InstalledSoftware.ps1 | Where {$_.AppName -match “SoftwareName” } | .\Uninstall-InstalledSoftware.ps1
\============================================
La dernière ligne appelle deux autres scripts powershell.
Get-InstalledSoftware.ps1 est :
\[cmdletbinding()\]
\[cmdletbinding()\]
param(
\[parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)\]
\[string\[\]\]$ComputerName = $env:computername
)
begin {
$UninstallRegKey="SOFTWARE\\\\Microsoft\\\\Windows\\\\CurrentVersion\\\\Uninstall"
}
process {
foreach($Computer in $ComputerName) {
Write-Verbose "Working on $Computer"
if(Test-Connection -ComputerName $Computer -Count 1 -ea 0) {
$HKLM = \[microsoft.win32.registrykey\]::OpenRemoteBaseKey('LocalMachine',$computer)
$UninstallRef = $HKLM.OpenSubKey($UninstallRegKey)
$Applications = $UninstallRef.GetSubKeyNames()
foreach ($App in $Applications) {
$AppRegistryKey = $UninstallRegKey + "\\\\" + $App
$AppDetails = $HKLM.OpenSubKey($AppRegistryKey)
$AppGUID = $App
$AppDisplayName = $($AppDetails.GetValue("DisplayName"))
$AppVersion = $($AppDetails.GetValue("DisplayVersion"))
$AppPublisher = $($AppDetails.GetValue("Publisher"))
$AppInstalledDate = $($AppDetails.GetValue("InstallDate"))
$AppUninstall = $($AppDetails.GetValue("UninstallString"))
if(!$AppDisplayName) { continue }
$OutputObj = New-Object -TypeName PSobject
$OutputObj | Add-Member -MemberType NoteProperty -Name ComputerName -Value $Computer.ToUpper()
$OutputObj | Add-Member -MemberType NoteProperty -Name AppName -Value $AppDisplayName
$OutputObj | Add-Member -MemberType NoteProperty -Name AppVersion -Value $AppVersion
$OutputObj | Add-Member -MemberType NoteProperty -Name AppVendor -Value $AppPublisher
$OutputObj | Add-Member -MemberType NoteProperty -Name InstalledDate -Value $AppInstalledDate
$OutputObj | Add-Member -MemberType NoteProperty -Name UninstallKey -Value $AppUninstall
$OutputObj | Add-Member -MemberType NoteProperty -Name AppGUID -Value $AppGUID
$OutputObj# | Select ComputerName, DriveName
}
}
}
}
end {}
et Uninstall-InstalledSoftware.ps1 :
\[cmdletbinding()\]
param (
\[parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true)\]
\[string\]$ComputerName = $env:computername,
\[parameter(ValueFromPipeline=$true,ValueFromPipelineByPropertyName=$true,Mandatory=$true)\]
\[string\]$AppGUID
)
try {
$returnval = (\[WMICLASS\]"\\\\$computerName\\ROOT\\CIMV2:win32\_process").Create("msiexec \`/x$AppGUID \`/qn")
} catch {
write-error "Failed to trigger the uninstallation. Review the error message"
$\_
exit
}
switch ($($returnval.returnvalue)){
0 { "Uninstallation command triggered successfully" }
2 { "You don't have sufficient permissions to trigger the command on $Computer" }
3 { "You don't have sufficient permissions to trigger the command on $Computer" }
8 { "An unknown error has occurred" }
9 { "Path Not Found" }
9 { "Invalid Parameter"}
}
Je reçois toutes sortes d'erreurs bizarres, et je ne suis même pas sûr que ce qui précède puisse fonctionner. J'ai trouvé la plupart de ces informations sur techibee.com, ici : http://techibee.com/powershell/powershell-uninstall-software-on-remote-computer/1400
Existe-t-il un moyen plus simple de procéder ? Je m'arrache un peu les cheveux ! Sinon, je pourrais me connecter par RDP à 400 ordinateurs, tuer le processus et désinstaller... mais je n'ai vraiment, vraiment, vraiment pas envie de faire ça.
1 votes
Quelques éléments qui me viennent immédiatement à l'esprit : 1. Si vous avez 400 machines sur une liaison lente, j'exécuterais l'intégralité du script dans un
Invoke-Command
scriptblock sur l'hôte distant, plutôt que de tout communiquer en retour. 2. Y a-t-il un danger à tenter de supprimer le logiciel, même s'il n'est pas installé ? Plutôt que d'obtenir une liste des logiciels installés et de la vérifier, ce qui est propre et net, pourriez-vous simplement tenter la désinstallation, et si elle échoue, supposer qu'il n'a jamais été installé en premier lieu ?