How to capture exception thrown by gem install in powershell - ruby

I'm trying to capture the exception thrown while installing gems, I see the error on the command window however I'm not able to capture the error in catch block, I would like to capture and log in logs file, below is the code.
try{
$tiny= .\gem install --local c:\mypath\tiny_tds-2.1.5-x64-mingw321.gem
if($tiny -eq $null){
throw
}
Write-Host "Installation completed :" $tiny
}
catch{
$string_err = $_ | Out-String
Write-Host "*****************************"
Write-Host $string_err
Write-Host "*****************************"
}
Error that I get on powershell command window

Related

Script ran successfully but still software is not uninstalled

Even though the below script runs successfully to remove software, I
am still able to see the software in the control panel program list,
what I am doing wrong?
See the command below :
PS D:\Project> .\ScriptWithBelowCode.ps1 -ComputerName
"X-XXX50947" -AppGUID XXXXXX-A60B-4899-A369-XXXXXXX
Uninstallation command triggered successfully
[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 `/norestart `/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"}
}
Command to execute .\ScriptFileWithAboveContent.ps1 -ComputerName "X-15XX150947" -AppGUID 30F836D2-A60B-4899-A369-XXXXX884EAF
Command to get GUID
Get-WmiObject -Class Win32_Product ` -Filter "Name like '%Microsoft%'" | Select-Object -ExpandProperty IdentifyingNumber
Second try
$app = Get-WmiObject -Class Win32_Product | Where-Object {$_.IdentifyingNumber -match "XXXXXX-A60B-4899-XXXX-B0FXXX84EAF" }
$app.Uninstall()
I am getting error showing below
PS D:\Project> .\ScriptFileWithAboveContent.ps1
Exception calling "Uninstall" : "Operation is not valid due to the current state of the object."
At D:\MicrosoftAIM\ScriptFileWithAboveContent.ps1:2 char:5
+ $app.Uninstall()
+ ~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : WMIMethodException
Third try
The below script ran successfully, But still, the software is still in the program list.
echo "Getting product code"
$ProductCode = Get-WmiObject win32_product -Filter "Name like '%somesoftware%'" | Select-Object -Expand IdentifyingNumber
echo "removing Product"
# Out-Null argument is just for keeping the power shell command window waiting for msiexec command to finish else it moves to execute the next echo command
& msiexec /x $ProductCode | Out-Null
echo "uninstallation finished"
PS D:\MicrosoftAIM> .\ScriptWithAboveContent.ps1
Getting product code
removing Product
uninstallation finished
PS D:\MicrosoftAIM> Get-WmiObject -Class Win32_Product ` -Filter "Name like '%Microsoft%azure%info%'"

How to add arguments to Diagnostic Start with PowerShell

I am limited to only using native windows tools, and I need to automate opening a browser, going to a website, and then closing the browser. I'm going to use task scheduler to run the script.
I created this PowerShell script which successfully opens a browser, and closes it.
How would I go about having this open a specific webpage? Start Arguments or something else?
$browser = [Diagnostics.Process]::Start("chrome.exe")
$id = $browser.Id
Start-Sleep -Seconds 5
try {
Stop-Process -Id $id -ErrorAction stop
} catch {
Write-Host "Failed to kill"
}
You can start the process with the appropriate Chromium command line argument(s):
$browser = [Diagnostics.Process]::Start("chrome.exe", "https://stackoverflow.com/ --new-window")
$id = $browser.Id
Start-Sleep -Seconds 5
try {
Stop-Process -Id $id -ErrorAction stop
}
catch {
Write-Host "Failed to kill"
}
Process.Start Method
Run Chromium with flags
List of Chromium Command Line Switches

Powershell -- Command throws exception, retry previous command (loops) until successful

Have a command that (on 2008 boxes) throws an exception due to the buffer limit.
Essentially, the script stops WAUA, blows out SoftwareDistribution, then reaches out to rebuild SD and check for updates against WSUS then checks back in so the alerts in WSUS stop.
I want a specific line to retry if an exception is thrown until it finishes without an exception, then we can tell it to report back in to WSUS to clear it out.
Stop-Service WUAUSERV
Remove-Item -Path C:\WINDOWS\SoftwareDistribution -recurse
Start-Service WUAUSERV
GPUpdate /force
WUAUCLT /detectnow
sleep 5
## This is the command I'd like to loop, if possible, when an exception is thrown ##
$updateSession = new-object -com "Microsoft.Update.Session"; $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates
WUAUCLT /reportnow
Any kind of help would be appreciated. Everything I've been able to find has been how to create my own exception but not how to handle it when an exception is thrown and retry until it finishes without an error.
Edit:
Then based on the below Answer, is this how I would want it to be written so it will continue to check until it runs successfully and then it'll report back in?
Stop-Service WUAUSERV
Remove-Item -Path C:\WINDOWS\SoftwareDistribution -recurse
Start-Service WUAUSERV
GPUpdate /force
WUAUCLT /detectnow
sleep 5
while(-not $?) {$updateSession = new-object -com "Microsoft.Update.Session"; $updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates}
WUAUCLT /reportnow
You can use the special character $? This will return false if the last command returned with error, so your while loop would just look like:
while(-not $?)
See what is $? in powershell.
Alternatively, $error[0] gives the last thrown error message so you could build a while loop around that, similar to:
while($error[0] -ne "error message")
Set a value to false and only flip it if you get total success. Loop until you succeed or your timeout exceeds your defined value -- if you don't include a timeout, you have created an infinite loop condition where if the host never succeeds, it'll run until reboot.
$sts = $false
$count = 0
do {
try {
$updateSession = new-object -com "Microsoft.Update.Session"
$updates=$updateSession.CreateupdateSearcher().Search($criteria).Updates
$sts = $true
} catch {
## an exception was thrown before we got to $true
}
$Count++
Start-Sleep -Seconds 1
} Until ($sts -eq $true -or $Count -eq 100)

How to Tell When Azure Remove-AzureStorageShare Is Done In PowerShell

I am trying to perform a scheduled operation where I create a file share in Azure and copy some files in it. Before I begin doing so, I would like to cleanup the previous job if it did not cleanup on the prior run. To do so, I found the handy-dandy Remove-AzureStorageShare method. My problem is that after I call this method, it takes Azure sometimes up to 2 minutes to complete the task. I have a wait in PowerShell, but I'm unable to check Azure for the share without throwing an exception and then continue. So basically, I want the following operations to happen:
1] Check for Share in Azure, delete if it exists
2] Once Azure is done deleting, re-create it
3] Copy my files into the new Share
Here is what I have and it doesn't work:
Write-Host "STEP 6 : Removing existing Azure Share...";
# THIS NEXT LINE THROWS AN ERROR IF THE SHARE DOESN'T EXIST
If ((Get-AzureStorageShare -Name $azureShareName -Context $context) {
Remove-AzureStorageShare
-Context $context
-Name $azureShareName
-Force
-ErrorAction SilentlyContinue | Out-Null
}
$removed = $false;
While(!$removed) {
Try {
# THIS LINE SHOULD THROW AN EXCEPTION SINCE IT'S BEING DELETED
If ((Get-AzureStorageShare -Name $azureShareName -Context $context) -eq $null) {
$removed = $true;
}
}
Catch
{
# SINCE THE EXCEPTION IS THROWN, WE WILL SLEEP FOR A FEW...
Write-Host "STEP 6a : Waiting...still removing.";
Start-Sleep -s 10;
}
}
When I attempt to create the share again, I get the following error:
New-AzureStorageShare : The remote server returned an error: (409) Conflict. HTTP Status Code: 409 - HTTP Error Message: The specified share is being deleted. Try operation later.
Thank you for your question.
I think we can use this PowerShell to check for share in Azure:
Write-Host "STEP 6 : Removing existing Azure Share...";
# THIS NEXT LINE THROWS AN ERROR IF THE SHARE DOESN'T EXIST
If ((Get-AzureStorageShare -Name $azureShareName -Context $ctx)) {
Remove-AzureStorageShare `
-Context $ctx `
-Name $azureShareName `
-Force `
-ErrorAction SilentlyContinue | Out-Null
}
$removed = $false;
While(!$removed) {
Try {
# THIS LINE SHOULD THROW AN EXCEPTION SINCE IT'S BEING DELETED
If ((Get-AzureStorageShare -Name $azureShareName -Context $ctx) -eq $null) {
$removed = $true;
}
else {
Write-Host "STEP 6a : Waiting...still removing.";
Start-Sleep -s 5;
}
}
Catch
{
# SINCE THE EXCEPTION IS THROWN, WE WILL SLEEP FOR A FEW...
Write-Host "STEP 6b : Waiting...still removing.";
Start-Sleep -s 5;
}
}
If the Share existing the PowerShell will show: waiting…still removing, else the PowerShell will show error 404:
If you still have questions, welcome to post back here. Thanks.

Azure Custom Script Extension continually restarting

Having a bit of trouble with the Azure Custom script extension on a windows VM. I have created a script that installs a particular business application. In order to accomplish this, the script calls several other scripts and a reboot is required in between two scripts.
The script is designed such that it can "pick up where it left off" by checking whether certain files exist or if registry keys exist. The reboot portion of this goes fine, however, I'm noticing that the script handler sets several registry keys to keep track of its state in
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Azure\ScriptHandler
I see a registry value called "MreSeqNumStarted", which I presume is how the script handler keeps track of what script it's executing. There is only one script fired by the extension currently, and this value is set to 0.
What I'm seeing, is that, when the machine is rebooted after the script has completed, the script fires again. This occurs with every reboot of the virtual machine. I believe the script extension is not marking the script as "completed", and I'm somewhat at a loss as to why. The basic (sanitized) flow of the script is below:
trap {$_.Exception.Message; Get-PSCallstack;continue}
if(Test-Path C:\ScriptLog.txt)
{
Add-Content "C:\ScriptLog.txt" "`nScript Previously Run, Prior log exists."
} else {
Write-Host "Begin Script" | Out-File "C:\ScriptLog.txt"
}
#$storagePath = [uri]::EscapeDataString($storagePath)
#Create Directory Structure and download scripts/files
if(Test-Path C:\PreparePlatform\) {
Add-Content "C:\ScriptLog.txt" "`nFiles Already Downloaded... Continuing"
} else {
New-Item -ItemType Directory -Force -Path C:\SoftwareName\PreparePlatform\
(New-Object Net.WebClient).DownloadFile('SAS-URL-GOES-HERE','C:\SoftwareName\PreparePlatform\PreparePlatform.zip');(new-object -com shell.application).namespace('C:\SoftwareName\PreparePlatform').CopyHere((new-object -com shell.application).namespace('C:\SoftwareName\PreparePlatform\PreparePlatform.zip').Items(),16)
(New-Object Net.WebClient).DownloadFile('SAS-URL-GOES-HERE','C:\SoftwareName\SOMEZIP.zip');(new-object -com shell.application).namespace('C:\SoftwareName').CopyHere((new-object -com shell.application).namespace('C:\SoftwareName\SOMEZIP.zip').Items(),16)
Add-Content "C:\ScriptLog.txt" "`nExtracted Install Media"
}
if(Test-Path C:\SoftwareName\preparedone.txt) {
Add-Content "C:\ScriptLog.txt" "`nPreparePlatform already completed... Continuing"
} else {
Invoke-Expression "Set-Location c:\SoftwareName\PreparePlatform\; C:\SoftwareName\PreparePlatform\Prepare-WindowsPlatform.ps1"
CreateSQLUser -identifierValue $value -saPassword $sqlSaPassword -tenantPass $TenantSqlPassword
CreateSQLLogin -identifierValue $value -saPassword $SqlSaPassword -tenantPass $TenantSqlPassword
Write-Host "PreparePlatform Complete" | Out-File "C:\SoftwareName\preparedone.txt"
}
if(Test-Path C:\SoftwareName\UpdatePlatform.txt) {
Add-Content "C:\ScriptLog.txt" "`nUpdatePlatform already completed... Continuing"
} else {
Add-Content "C:\ScriptLog.txt" "`nBegin Update-Platform"
Invoke-Expression "Set-Location C:\SoftwareName\PreparePlatform\; C:\SoftwareName\PreparePlatform\Update-WindowsPlatform.ps1"
Write-Host "UpdatePlatform Complete" | Out-File "C:\SoftwareName\UpdatePlatform.txt"
}
if(Test-Path C:\SoftwareName\Rebooted.txt) {
Add-Content "C:\ScriptLog.txt" "`nReboot already completed... Continuing"
} else {
Write-Host "Rebooting" | Out-File "C:\SoftwareName\Rebooted.txt"
Restart-Computer -Force
Restart-Computer -Force
Start-Sleep 3600 #Make sure nothing else executes
}
# TODO: Make more robust for potentially more nodes... need to delay 1 hour for each node
If($env:computername -eq 'pvm-SoftwareName-1') { Write-Output "Second Node, waiting 1 hour"; Add-Content "C:\ScriptLog.txt" "`nNot First Node, waiting 1 hour" ;Start-Sleep -Seconds 3600 }
Add-Content "C:\ScriptLog.txt" "`nPrepare SoftwareName Installers"
Set-Location C:\SoftwareName\Script\; C:\SoftwareName\Script\Prepare-SoftwareNameInstallers.ps1 -neededParameters $values
Add-Content "C:\ScriptLog.txt" "`nPrepare SoftwareName Installers complete"
try
{
if(-not (Get-Service -Name 'SoftwareName server')) {
C:\SoftwareName\Script\Install-SoftwareNameBP.ps1 -neededParameters $values
} else {
Add-Content "C:\ScriptLog.txt" "`n ALREADY INSTALLED!"
}
}
catch
{
$_.Exception.Message;Get-PSCallStack
if (-not (Get-Service -Name 'SoftwareName Server').Status -eq 'Running')
{throw "Service unavailable"}
}
Write-Output "Install Finished."
try
{
if(-not ((Invoke-WebRequest -Uri https://IISSiteURL/).StatusCode -eq '200'))
C:\SoftwareName\Script\Install-SoftwareNameSF.ps1 -neededParameters $values
}
catch
{
$_.Exception.Message;Get-PSCallStack
if(-not (Test-Path -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{AGUID}") )
{throw "Smartforms Install failed"}
}
try
{
#Begin
C:\SoftwareName\Script\Install-SoftwareNameSP.ps1 -neededParameters $values
}
catch
{
$_.Exception.Message;Get-PSCallStack
if(-not (Test-Path -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{AGUID}") )
{throw "Sharepoint Install failed"}
}
try
{
#[bool]$skipDeploy
#if($env:computername -eq 'pvm-SoftwareName-0') { $skipDeploy = $false } else { $skipDeploy = $true }
#Begin
C:\SoftwareName\Script\Install-SoftwareNameMG.ps1 -neededParameters $values
catch
{
$_.Exception.Message;Get-PSCallStack
if(-not (Test-Path -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{AGUID}") )
{throw "Management Install failed"}
}
try
{
C:\SoftwareName\Script\Install-Finalize.ps1 -neededParameters $values
}
catch
{
$_.Exception.Message;Get-PSCallStack
if(-not (Test-Path -Path "HKLM:\SOFTWARE\Wow6432Node\Microsoft\Windows\CurrentVersion\Uninstall\{AGUID}") )
{throw "Install Finalize Failed"}
}
#Kill the script
Add-Content "C:\ScriptLog.txt" "`nScript Completed"
Exit
Below is the expected output of C:\ScriptLog.txt
Begin Scheduled Job Regstration
Extracted Install Media
Begin PreparePlatform
Completed PreparePlatform
Begin Update-Platform
Script Previously Run, Prior log exists.
Files Already Downloaded... Continuing
PreparePlatform already completed... Continuing
UpdatePlatform already completed... Continuing
Reboot already completed... Continuing
Prepare SOFTWARENAME Installers
Prepare SOFTWARENAME Installers complete
C:\SOFTWARENAME\Script\Install-K2BP.ps1 -parameterValues $values
C:\SOFTWARENAME\Script\Install-K2SF.ps1 -parameterValues $values
C:\SOFTWARENAME\Script\Install-K2SP.ps1 -parameterValues $values
C:\SOFTWARENAME\Script\Install-K2MG.ps1 -parameterValues $values
C:\SOFTWARENAME\Script\Install-Finalize.ps1 -parameterValues $values
Script Completed
After a reboot, the same log file:
Begin Scheduled Job Regstration
Extracted Install Media
Begin PreparePlatform
Completed PreparePlatform
Begin Update-Platform
Script Previously Run, Prior log exists.
Files Already Downloaded... Continuing
PreparePlatform already completed... Continuing
UpdatePlatform already completed... Continuing
Reboot already completed... Continuing
Prepare SOFTWARENAME Installers
Prepare SOFTWARENAME Installers complete
C:\SOFTWARENAME\Script\Install-SOFTWARENAMEBP.ps1 -neededParameters $values
C:\SOFTWARENAME\Script\Install-SOFTWARENAMESF.ps1 -neededParameters $values
C:\SOFTWARENAME\Script\Install-SOFTWARENAMESP.ps1 -neededParameters $values
C:\SOFTWARENAME\Script\Install-SOFTWARENAMEMG.ps1 -neededParameters $values
C:\SOFTWARENAME\Script\Install-Finalize.ps1 -neededParameters $values
Script Completed
Script Previously Run, Prior log exists.
Files Already Downloaded... Continuing
PreparePlatform already completed... Continuing
UpdatePlatform already completed... Continuing
Reboot already completed... Continuing
Prepare SOFTWARENAME Installers
Prepare SOFTWARENAME Installers complete
C:\SOFTWARENAME\Script\Install-SOFTWARENAMEBP.ps1 -neededParameters $values...
Edit1: I've commented out all calls to external scripts. The script at this point only writes output to a file effectivley and traps any exceptions in doing so. The script continues to re-fire with every VM reboot.

Resources