I'm trying to create a powershell script that will uninstall all versions of a program in our studio.
I had a look at the registry and can see that we have 3 strings of the program installed in our studio computers
{D4BE10F2-3E2D-4120-863A-765623D53264}
{77067FD9-800C-48B4-803D-569642ADABC5}
{1DB1AEB7-EDBD-4BB1-87DB-26C72576DA42}
I created a test script:
msiexec.exe /x{D4BE10F2-3E2D-4120-863A-765623D53264} /q
and used it on a machine, this worked and that version of the program was uninstalled.
I want to create a script that cycle all 3 strings and Success on the correct one, as I don't know what machine has what version without doing a scan.
so I created a `powershell script:
foreach ($guid in '{D4BE10F2-3E2D-4120-863A-765623D53264}',
'{77067FD9-800C-48B4-803D-569642ADABC5}',
'{1DB1AEB7-EDBD-4BB1-87DB-26C72576DA42}') {
$exe = 'C:\Windows\System32\msiexec.exe'
$ps = Start-Process -PassThru -Wait $exe "/x /q"
if ($ps.ExitCode -eq 0) { "Success"; exit 0 }
}
Write-Warning "Uninstallation failed."
exit $ps.ExitCode
This is not working for me as it keeps returning with Uninstallation failed, I'm not sure whats going on.
Any advice?
This will work even if there are all three versions installed:
foreach ($guid in '{D4BE10F2-3E2D-4120-863A-765623D53264}',
'{77067FD9-800C-48B4-803D-569642ADABC5}',
'{1DB1AEB7-EDBD-4BB1-87DB-26C72576DA42}') {
$exe = 'C:\Windows\System32\msiexec.exe'
$ps = Start-Process $exe -ArgumentList "/x$guid /q" -PassThru -Wait
if ($ps.ExitCode -eq 0) {
Write-Host "$($guid): Success"
} else {
Write-Host "$($guid): Failed"
}
}
Related
I got a new system running on windows 11 and I'm having issues running the shell script to set up react native windows environment.
Set-ExecutionPolicy Unrestricted -Scope Process -Force;
iex (New-Object System.Net.WebClient).DownloadString('https://aka.ms/rnw-deps.ps1')
Please I need help resolving this error.
The script can be found at https://aka.ms/rnw-deps.ps1
Error is from lines 68 and 130
Here's a screenshot of the error I'm getting.
The script you link to is broken (as of this writing):
Line 98:
Write-Debug No Retail versions of Visual Studio found, trying pre-release...
This line causes a syntax error, due to missing quoting; the correct syntax is:
Write-Debug 'No Retail versions of Visual Studio found, trying pre-release...'
Line 130:
$p = Start-Process -PassThru -Wait -FilePath $vsInstaller -ArgumentList ("modify --channelId $channelId --productId $productId $addWorkloads --quiet --includeRecommended" -split ' ')
The fact that this line fails indicates that at least one of the referenced variables - $channelId, $productId, $addWorkloads is unexpectedly $null.
As an aside:
That an error results from this is a manifestation of a Windows PowerShell bug (which has since been fixed in PowerShell (Core) 7+) - passing an empty array or $null or an array that has at least one $null element to the -ArgumentList property of Start-Process unexpectedly causes an error.
There is a separate Start-Process bug - still present as of PowerShell Core 7.2.2 - the workaround for which makes it better to pass all arguments as a single string with embedded "..." quoting (as needed) to -ArgumentList (see this answer):
$p = Start-Process -PassThru -Wait -FilePath $vsInstaller -ArgumentList "modify --channelId $channelId --productId $productId $addWorkloads --quiet --includeRecommended"
I try to uninstall a msi file, but when I try this via array I get an error (cant find installation package)
When I do the same but not in array - it works
for ($i=0; $i -lt $msiArrayClean.length; $i++){
Write-Host $msiArrayClean[$i]
& msiexec.exe /x $msiArrayClean[$i]
}
here the output of Write Host
How i come to $msiArrayClean
$msiCache = get-wmiobject Win32_Product | Where-Object Name -like "*7-Zip*" | Format-Table LocalPackage -AutoSize -HideTableHeaders
$msiString = $msiCache | Out-String
$msiArrayWithEmptyLines = $msiString -split "`n"
$msiArray = $msiArrayWithEmptyLines.Split('', [System.StringSplitOptions]::RemoveEmptyEntries)
$msiArrayCleanString = $msiArray | Out-String
$msiArrayClean = $msiArrayCleanString -split "`n"
A few caveats up front:
Format-* cmdlets output objects whose sole purpose is to provide formatting instructions to PowerShell's output-formatting system - see this answer. In short: only ever use Format-* cmdlets to format data for display, never for subsequent programmatic processing.
The CIM cmdlets (e.g., Get-CimInstance) superseded the WMI cmdlets (e.g., Get-WmiObject) in PowerShell v3 (released in September 2012). Therefore, the WMI cmdlets should be avoided, not least because PowerShell (Core) (version 6 and above), where all future effort will go, doesn't even have them anymore. For more information, see this answer.
Use of the Win32_Product WMI class is discouraged, both for reasons of performance and due to potentially unwanted side effects - see this Microsoft article.
An alternative - available in Windows PowerShell only (not in PowerShell (Core) 7+) - is to use the following to get uninstall command lines and execute them via cmd /c:
Get-Package -ProviderName Programs -IncludeWindowsInstaller |
ForEach-Object { $_.meta.attributes['UninstallString'] }
If you need to stick with Win32_Product:
# Get the MSI package paths of all installed products, where defined.
$msiCache = (Get-CimInstance Win32_Product).LocalPackage -ne $null
foreach ($msiPackagePath in $msiCache) {
if (Test-Path -LiteralPath $msiPackagePath) {
# Note that msiexec.exe runs *asynchronously*.
# Use Start-Process -Wait to wait for each call to complete.
& msiexec.exe /x $msiPackagePath
} else {
Write-Warning "Package not found: $msiPackagePath"
}
}
I don't like reaching to WMI, since its perfomance is the issue. I prefer to do it via registry and it worked for me many times. Code explanation in comments.
$name = "7-zip"
#Get all items from registry
foreach ($obj in Get-ChildItem "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall") {
#Get DisplayName property of registry
$dname = $obj.GetValue("DisplayName")
#Search for given name
if ($dname -like "*$name*") {
#Get uninstall string (it gets you msiexec /I{APPID})
$uninstString = $obj.GetValue("UninstallString")
foreach ($line in $uninstString) {
#Getting GUID from "{" to "}""
$found = $line -match '(\{.+\}).*'
if ($found) {
#If found - get GUID
$appid = $matches[1]
Write-Output "About to uninstall app $appid"
#Start uninstallation
Start-Process "msiexec.exe" -arg "/X $appid /qb" -Wait
}
}
}
}
Edit: Added solution with msi path after Nehat's comment as this works for me (I tried to minimize the code :))
$msiCache = get-wmiobject Win32_Product | Where-Object Name -like "*7-Zip*" | Format-Table LocalPackage -AutoSize -HideTableHeaders
foreach ($msi in $msiCache | Out-String) {
if ([string]::IsNullOrEmpty($msi)) {
continue
}
Write-Host $msi
Start-Process "msiexec.exe" -arg "/x $msi" -Wait
}
I have a powershell script that launches an Excel macro to refresh pivot tables and data sources, it works fine when run manually or from cmd.
when run from Sql Agent job it succeeds without performing the Excel refresh.
I call the script with this command in the job step:
powershell -command "&'C:\rapport_declaratif\REFRESH_3.ps1'"
I tried calling it with powershell, with cmd, with xp_cmdshell but nothing seems to work.
I even called it differently, for exp when I call it with this command:
cmd.exe /c "C:\rapport_declaratif\REFRESH_3.ps1"
it runs forever.
I also googled and found that I have to create this folder:
C:\Windows\SysWOW64\config\systemprofile\DeskTop
I did and it didn't solve the problem.
Below is my powershell script:
# Open Excel file
$excel = new-object -comobject excel.application
$filePath = "C:\rapport_declaratif\Rapport_Declaratif.xlsm"
$workbook = $excel.Workbooks.Open($FilePath)
$excel.Visible = $true
$excel.DisplayAlerts = $false
$worksheet = $workbook.worksheets.item(1)
#Write-Host "Running macro in excel to refresh data."#
$excel.Run("Refresh_ALL")
Start-Sleep -s 30
#Write-Host "data refreshed."#
$workbook.save()
# Write-Host "saved."#
$workbook.close()
$excel.quit()
#Write-Host "Closed Excel"#
I managed to install SQL server on a clean machine with scripts.
But sometimes the scripts won't work because the machine needs a reboot.
My ask:
1.Is there any way to detect if reboot is required while installing SQLserver
2.If reboot is needed,reboot it automatically
In summary ,When a reboot is needed,the value is logged in Registry at below places..
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending
HKLM\SYSTEM\CurrentControlSet\Control\Session Manager
Before installing ,you can run below powershell script..
#Adapted from https://gist.github.com/altrive/5329377
#Based on <http://gallery.technet.microsoft.com/scriptcenter/Get-PendingReboot-Query-bdb79542>
function Test-PendingReboot
{
if (Get-ChildItem "HKLM:\Software\Microsoft\Windows\CurrentVersion\Component Based Servicing\RebootPending" -EA Ignore) { return $true }
if (Get-Item "HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\WindowsUpdate\Auto Update\RebootRequired" -EA Ignore) { return $true }
if (Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\Session Manager" -Name PendingFileRenameOperations -EA Ignore) { return $true }
try {
$util = [wmiclass]"\\.\root\ccm\clientsdk:CCM_ClientUtilities"
$status = $util.DetermineIfRebootPending()
if(($status -ne $null) -and $status.RebootPending){
return $true
}
}catch{}
return $false
}
if the above function returns true ,you can run below command..
Restart-Computer -ComputerName "Server01", "Server02", "localhost"
Server* stands for some names servers and localhost stands for local computer
References:
http://ilovepowershell.com/2015/09/10/how-to-check-if-a-server-needs-a-reboot/
Or lunch the install from command line (cmd) like so
C:\Users\username\Downloads\SQLEXPR_x64_ENU.exe /SKIPRULES=RebootRequiredCheck /ACTION=Install
fist is the address where the setup exe is located and second the parameters to skip reboot check
I am searching for a way to transfer an Excel file to a database (the client is called mbox. Is there a general way to transfer Excel to a database?). At least I want a script writing the INSERT-commands for me. I tried it with PowerShell but run into one huge problem: I can't write a proper for-each-loop for this task:
if($Args.count -eq 0){
"No Parameter-Error"
exit
}
if($Args.count -gt 1){
"Too many Parameter-Error"
exit
}
if (-not (Test-path $args[0] -include *.csv)){
"Invaild Root or no csv-file"
exit
}
$spalten=Import-Csv $args[0] -Delimiter ";"
$spalten.GetEnumerator() | % {
$key=$($_.key);
Echo "$key"
Echo $($_.value[$key])+"`n";
}
Please help, also know that I have no idea what one column will be named.