visual studio
13 TopicsPowerShell Automation for Verifying MST
Just finished putting together a script to Apply an MST to an MSI then read out the property table. This is for an automation process to verify a submited MSI and MST meet our packaging standards. Need a little sanity check as working with COM objects is not a strong point for me. Really want to make sure I am closing the files correctly after applying the transform then querying the database. I wasn't able to delete the temp files running in Powershell ISE until I did the ReleaseComObject. I didn't have to do that when working with the straight MSI and just pull the properties from it so I hope this is not corrupting any files. # Apply MST to an MSI # Based on Code from: https://hinchley.net/articles/update-cab-file-and-msi-transform-via-command-line/ $SourceMSI = "C:\Temp\MSI\MSI-x64.msi" $SourceMST = "C:\Temp\MSI\MSI.mst" $TempMSI = "$SourceMSI.tmp" $TempMST = "$SourceMST.tmp" Copy-Item $SourceMSI $TempMSI -Force Copy-Item $SourceMST $TempMST -Force $WindowsInstaller = New-Object -ComObject WindowsInstaller.Installer #Open the database in Direct read/write without Transaction (2) $MSIDatabase1 = $WindowsInstaller.GetType().InvokeMember('OpenDatabase' , 'InvokeMethod' , $Null, $WindowsInstaller, @($TempMSI, 2)) #$MSIDatabase1.applytransform($TempMST, 0) $MSIDatabase1.GetType().InvokeMember('ApplyTransform' , 'InvokeMethod' , $Null , $MSIDatabase1 , @($TempMST, 0)) $Query = ("SELECT Property,Value FROM Property") #Opens a data view to the MSI based on the query created. $View = $MSIDatabase1.GetType().InvokeMember('OpenView', 'InvokeMethod', $null, $MSIDatabase1, ($Query)) $null = $View.GetType().InvokeMember('Execute', 'InvokeMethod', $null, $View, $null) $hash = @{} # Add File information (Note this adds the full File information Porperties so can call with <Var>.File |Select * $hash.Add('File',$TempMSI) WHILE ($Record = $View.GetType().InvokeMember('Fetch', 'InvokeMethod', $null, $View, $null)) { $name = $Record.GetType().InvokeMember('StringData', 'GetProperty', $null, $Record, 1) $value = $hashMSIValue = $Record.GetType().InvokeMember('StringData', 'GetProperty', $null, $Record, 2) $hash.Add($name,$value) } # Push Hash table into a PSCustom object $msiProperties = [pscustomobject]$hash # I'm not sure If I have everything required to close out here properly from applying the transform. $null = $MSIDatabase1.GetType().InvokeMember('Commit' , 'InvokeMethod' , $Null , $MSIDatabase1 , $Null) $null = $view.GetType().InvokeMember('Close', 'InvokeMethod', $null, $view, $null) # Really important part to be able to release the opened files and delete $null = [Runtime.Interopservices.Marshal]::ReleaseComObject($view) $null = [Runtime.Interopservices.Marshal]::ReleaseComObject($MSIDatabase1) $null = [Runtime.Interopservices.Marshal]::ReleaseComObject($WindowsInstaller) [GC]::Collect()2.4KViews1like0CommentsMicrosoftTeams cmdlets not working with AccessToken
I am trying to run cmdlets from powershell module MicrosoftTeams (version 2.0.0) in a C# web application. I am using Authorization code flow and code from the answer provided in this post to acquire token: https://stackoverflow.com/questions/43488511/acquire-aad-token-using-asp-net-web-forms. Note: I had changed resource in the code to graph.windows.net to acquire AAD token. Token is acquired by using AuthenticationContext.AcquireTokenByAuthorizationCodeAsync method. Once the token is acquired, I run the following lines to create a powershell instance in C# and to import MicrosoftTeams Module. PowerShell pshell InitialSessionState iss; iss = InitialSessionState.CreateDefault2(); iss.ImportPSModule(new[] { "MicrosoftTeams" }); pshell = PowerShell.Create(iss); Then to connect with MicrosoftTeams, I run the following code: var connectCmd = new Command("Connect-MicrosoftTeams"); connectCmd.Parameters.Add("AadAccessToken", AccessToken); connectCmd.Parameters.Add("AccountId", "xxxxxxx@xxxxxx.onmicrosoft.com"); pshell.Commands.AddCommand(connectCmd); var result1 = pshell.Invoke(); Code works fine till here. After this I clear the shell commands and invoke the Get-CsTeamsCallingPolicy cmdlet: pshell.Commands.Clear(); pshell.Streams.Error.Clear(); pshell.AddScript("Get-CsTeamsCallingPolicy"); var result2 = pshell.Invoke(); After Invoke, I get an exception and this dialog pops up: Pressing 'Continue' brings back the same dialogue a couple of times. Exception details from this screen are: System.Collections.Generic.KeyNotFoundException was unhandled by user code HResult=-2146232969 Message=The given key was not present in the dictionary. Source=mscorlib StackTrace: at System.Collections.Concurrent.ConcurrentDictionary`2.get_Item(TKey key) at Microsoft.TeamsCmdlets.Powershell.Connect.Models.AzureSessionProvider.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\Models\AzureSession.cs:line 80 at Microsoft.TeamsCmdlets.Powershell.Connect.TeamsPowerShellSession.GetAccessToken(String resource, IEnumerable`1 scopes) in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\TeamsPowerShellSession.cs:line 82 at Microsoft.TeamsCmdlets.PowerShell.Connect.GetCsInternalAccessToken.ProcessRecord() in D:\a\1\s\src\Microsoft.TeamsCmdlets.PowerShell.Connect\GetCsInternalAccessToken.cs:line 61 at System.Management.Automation.CommandProcessor.ProcessRecord() After pressing continue for the 3rd time, control goes back to C# code, and I receive the following runtime exception: Exception calling "GetSteppablePipeline" with "1" argument(s): "Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): "Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets."" Trying to run this logic from the powershell editor shows similar behavior: Running the following two lines: $AccessToken = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' Connect-MicrosoftTeams -AadAccessToken $AccessToken -AccountId 'xxxxxxx@xxxxxx.onmicrosoft.com' gives this result: Account Environment Tenant TenantId ------- ----------- ------ -------- xxxxxxx@xxxxxx.onmicrosoft.com AzureCloud xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx I then run Get-Team cmdlet: Get-Team -User xxxxxxx@xxxxxxx.onmicrosoft.com which results in this message: Get-Team : The given key was not present in the dictionary. At line:1 char:1 + Get-Team -User xxxxxxx@xxxxxxx.onmicrosoft.com + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [Get-Team], KeyNotFoundException + FullyQualifiedErrorId : System.Collections.Generic.KeyNotFoundException,Microsoft.TeamsCmdlets.PowerShell.Custom.GetTeam Running cmdlet Get-CsTeamsCallingPolicy yields this: Exception calling "GetSteppablePipeline" with "1" argument(s): "Exception calling "GetRemoteNewCsOnlineSession" with "1" argument(s): "Run either Connect-MicrosoftTeams or new-csonlinesession before running cmdlets."" At C:\Program Files\WindowsPowerShell\Modules\MicrosoftTeams\2.0.0\net472\SfBORemotePowershellModule.psm1:11369 char:13 + $steppablePipeline = $scriptCmd.GetSteppablePipeline($myI ... + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + CategoryInfo : NotSpecified: (:) [], ParentContainsErrorRecordException + FullyQualifiedErrorId : CmdletInvocationException If I run Connect-MicrosoftTeams directly from powershell without providing access token and accountid, I get the login screens and after login everything works fine i.e. I can run Get-Team and Get-CsTeamsCallingPolicy cmdlets successfully but I don't get this behavior when working with AadAccessToken. All the above code works fine if connecting to AzureAD module via Connect-AzureAD cmdlet like this both in web application and powershell editor: Connect-AzureAD -AadAccessToken $AccessToken -AccountId 'xxxxxxx@xxxxxxx.onmicrosoft.com' If someone has faced and successfully resolved this issue or have some tips on how to resolve this, please help. I have already tried a lot of things including searching for the specific exception messages and any possible solutions but found nothing that could help in this particular scenario, installed the latest version of MSTeams module, the previous version was old and did not have all the cmdlets that I am looking to work with. I installed the preview version of MSTeams module also to see if this issue is fixed in the upcoming release. Uninstalled the deprecated SkypeForBuisnessOnline Connector module, updated windows and so on. If you look at https://docs.microsoft.com/en-us/powershell/module/teams/connect-microsoftteams?view=teams-ps#example-4, this is what I am trying to achieve.2.1KViews1like5Comments