{"id":957,"date":"2020-03-23T11:07:52","date_gmt":"2020-03-23T10:07:52","guid":{"rendered":"http:\/\/www.vatland.no\/?p=957"},"modified":"2020-03-23T11:07:52","modified_gmt":"2020-03-23T10:07:52","slug":"hash-tables-in-powershell","status":"publish","type":"post","link":"https:\/\/www.vatland.no\/index.php\/hash-tables-in-powershell\/","title":{"rendered":"Hash tables in powershell"},"content":{"rendered":"<p>We all have the need to store data in some kind of arrays. I use hashtables a lot. Preferred use is as a lookup table, I can use &#8216;contains&#8217; instead of looping through each item or reference an object by name instead of index number. Lookup table for licenses is where I use it the most at the time being. A table of license ID versus license name. One place for this is Microsoft licenses in partnercenter, and show licenses assigned to users. Using powershell to connect to Microsoft partnercenter to get all available skus by ID , name and displayname. When I have collected this &#8211; how do you ask?.<br \/>\nHere you go:<\/p>\n<div class=\"codecolorer-container powershell default\" style=\"overflow:auto;white-space:nowrap;width:435px;height:300px;\"><div class=\"powershell codecolorer\">&nbsp;Import<span class=\"sy0\">-<\/span>module partnercenter<br \/>\n&nbsp;Connect<span class=\"sy0\">-<\/span>CompanyPartnerCenter<br \/>\n&nbsp;<br \/>\n&nbsp; &nbsp; <span class=\"re0\">$lic<\/span> <span class=\"sy0\">=<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"re0\">$prodid<\/span> <span class=\"sy0\">=<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span> <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"re0\">$customerstenants<\/span> <span class=\"sy0\">=<\/span> Get<span class=\"sy0\">-<\/span>PartnerCustomer<br \/>\n&nbsp; &nbsp; <span class=\"kw3\">ForEach<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$customer<\/span> <span class=\"kw3\">in<\/span> <span class=\"re0\">$customerstenants<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$message<\/span> <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;Customer :$($customer.name)&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw1\">write-verbose<\/span> <span class=\"kw5\">-Message<\/span> <span class=\"st0\">&quot;$message&quot;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$custskus<\/span> <span class=\"sy0\">=<\/span> Get<span class=\"sy0\">-<\/span>PartnerCustomerSubscribedSku <span class=\"sy0\">-<\/span>CustomerId <span class=\"re0\">$customer<\/span>.customerid <br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">foreach<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$custsku<\/span> <span class=\"kw3\">in<\/span> <span class=\"re0\">$custskus<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">if<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$lic<\/span>.ContainsKey<span class=\"br0\">&#40;<\/span><span class=\"re0\">$custsku<\/span>.SkuPartNumber<span class=\"br0\">&#41;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"kw3\">else<\/span> <span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$lic<\/span>.Add<span class=\"br0\">&#40;<\/span><span class=\"re0\">$custsku<\/span>.skupartnumber<span class=\"sy0\">,<\/span> <span class=\"re0\">$custsku<\/span>.productname<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$prodid<\/span>.Add<span class=\"br0\">&#40;<\/span><span class=\"re0\">$custsku<\/span>.SkuId<span class=\"sy0\">,<\/span> <span class=\"re0\">$custsku<\/span>.ProductName<span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"br0\">&#125;<\/span> &nbsp;<br \/>\n&nbsp;<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Connect-companypartnercenter is a custom function. <a href=\"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-1\/\">Here is how to connect to Office partnercenter.<\/a><br \/>\nThe script above will (hopefully , no try-catch) end up in 2 hash tables. One &#8220;skuid&#8221; and productname:<\/p>\n<div class=\"codecolorer-container text default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"text codecolorer\">&quot;SkuID&quot;,&quot;DisplayName&quot;<br \/>\n&quot;WACONEDRIVEENTERPRISE&quot;,&quot;OneDrive for Business (Plan 2)&quot;<br \/>\n&quot;O365_BUSINESS_ESSENTIALS&quot;,&quot;Office 365 Business Essentials&quot;<br \/>\n&quot;MCOSTANDARD&quot;,&quot;Skype for Business Online (Plan 2)&quot;<br \/>\n&quot;Win10_E3_Local&quot;,&quot;Windows 10 Enterprise E3 (local only)&quot;<br \/>\n&quot;WACONEDRIVESTANDARD&quot;,&quot;OneDrive for Business (Plan 1)&quot;<\/div><\/div>\n<p>As long as I&#8217;m using this in the same script it is ok. Exporting it to files is not that straight forward, even tried &#8216;convertto-json&#8217; &#8211;not working (convertfrom-json returns an array)<br \/>\nSo I do this to crate a csv file. Creating correct columns.<\/p>\n<div class=\"codecolorer-container powershell default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"powershell codecolorer\">&nbsp; &nbsp; &nbsp; &nbsp;<span class=\"re0\">$csvobject<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$lic<\/span>.GetEnumerator<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">|<\/span> <span class=\"kw1\">Select-Object<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span>expression <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> <a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.name <span class=\"br0\">&#125;<\/span>; label <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;SkuID&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span>expression <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> <a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.value <span class=\"br0\">&#125;<\/span>; label <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;DisplayName&quot;<\/span> <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">|<\/span> convertto<span class=\"sy0\">-<\/span>csv <span class=\"kw5\">-Delimiter<\/span> <span class=\"st0\">','<\/span> <span class=\"kw5\">-NoTypeInformation<\/span> <span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$csvobject<\/span> <span class=\"sy0\">|<\/span> <span class=\"kw1\">Out<span class=\"kw4\">-File<\/span><\/span> <span class=\"kw5\">-Encoding<\/span> unicode <span class=\"re0\">$ExportSkuIDFile<\/span><br \/>\n<br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$csvobject<\/span> <span class=\"sy0\">=<\/span> <span class=\"br0\">&#40;<\/span><span class=\"re0\">$prodid<\/span>.GetEnumerator<span class=\"br0\">&#40;<\/span><span class=\"br0\">&#41;<\/span> <span class=\"sy0\">|<\/span> <span class=\"kw1\">Select-Object<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span>expression <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> <a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.name <span class=\"br0\">&#125;<\/span>; label <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;ProductID&quot;<\/span> <span class=\"br0\">&#125;<\/span><span class=\"sy0\">,<\/span> <span class=\"sy0\">@<\/span><span class=\"br0\">&#123;<\/span>expression <span class=\"sy0\">=<\/span> <span class=\"br0\">&#123;<\/span> <a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.value <span class=\"br0\">&#125;<\/span>; label <span class=\"sy0\">=<\/span> <span class=\"st0\">&quot;DisplayName&quot;<\/span> <span class=\"br0\">&#125;<\/span> <span class=\"sy0\">|<\/span> convertto<span class=\"sy0\">-<\/span>csv <span class=\"kw5\">-Delimiter<\/span> <span class=\"st0\">','<\/span> <span class=\"kw5\">-NoTypeInformation<\/span> <span class=\"br0\">&#41;<\/span><br \/>\n&nbsp; &nbsp; &nbsp; &nbsp; <span class=\"re0\">$csvobject<\/span> <span class=\"sy0\">|<\/span> <span class=\"kw1\">Out<span class=\"kw4\">-File<\/span><\/span> <span class=\"kw5\">-Encoding<\/span> unicode $ExportProductIDFile<\/div><\/div>\n<p>Now that we have the file it would be great to be able to use them \ud83d\ude42<br \/>\nAnd this is how it is imported in to a hashtable.<\/p>\n<div class=\"codecolorer-container powershell default\" style=\"overflow:auto;white-space:nowrap;width:435px;\"><div class=\"powershell codecolorer\"><span class=\"re0\">$filecontent<\/span><span class=\"sy0\">=<\/span><span class=\"kw1\">import-csv<\/span> <span class=\"kw5\">-Path<\/span> <span class=\"re0\">$importfile<\/span> <span class=\"kw5\">-Encoding<\/span> Unicode <span class=\"sy0\">-<\/span>Header <span class=\"st0\">&quot;column1&quot;<\/span><span class=\"sy0\">,<\/span><span class=\"st0\">&quot;column2&quot;<\/span><br \/>\n<span class=\"re0\">$hashtable<\/span><span class=\"sy0\">=@<\/span><span class=\"br0\">&#123;<\/span><span class=\"br0\">&#125;<\/span><br \/>\n<span class=\"re0\">$filecontent<\/span><span class=\"sy0\">|<\/span><span class=\"kw1\">ForEach-Object<\/span><span class=\"br0\">&#123;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"kw1\">write-verbose<\/span> <span class=\"kw5\">-message<\/span> <span class=\"st0\">&quot;$_.column1 , $_.column2&quot;<\/span><br \/>\n&nbsp; &nbsp; <span class=\"re0\">$hashtable<\/span>.add<span class=\"br0\">&#40;<\/span><a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.column1<span class=\"sy0\">,<\/span><a href=\"about:blank\"><span class=\"kw6\">$_<\/span><\/a>.column2<span class=\"br0\">&#41;<\/span><br \/>\n<span class=\"br0\">&#125;<\/span><\/div><\/div>\n<p>Read the file line by line and build our hash-table. Now we can use : $hashtable[&#8220;MCOSTANDARD&#8221;] , this will return the full name &#8216;Skype for Business Online (Plan 2)&#8217;<br \/>\nI have this as functions in my default module, the module I import in all my powershell sessions. (Surely you know about powershell profiles?)<br \/>\nHope this helped.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>We all have the need to store data in some kind of arrays. I use hashtables a lot. Preferred use is as a lookup table, I can use &#8216;contains&#8217; instead of looping through each item or reference an object by name instead of index number. Lookup table for licenses is where I use it the &hellip; <a href=\"https:\/\/www.vatland.no\/index.php\/hash-tables-in-powershell\/\" class=\"more-link\">Continue reading <span class=\"screen-reader-text\">Hash tables in powershell<\/span> <span class=\"meta-nav\">&rarr;<\/span><\/a><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"jetpack_post_was_ever_published":false,"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"Hash tables in powershell","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2}},"categories":[74,48],"tags":[65,96,95,59],"class_list":["post-957","post","type-post","status-publish","format-standard","hentry","category-csp","category-powershell","tag-csp","tag-csv-files","tag-hashtables","tag-powershell"],"aioseo_notices":[],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"jetpack_likes_enabled":false,"jetpack-related-posts":[{"id":899,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-2\/","url_meta":{"origin":957,"position":0},"title":"CSP access to tenants using powershell. Part 2","author":"Atle","date":"September 20, 2019","format":false,"excerpt":"In part 1 we created the Azure Enterprise App for Partnercenter and used this information to connect using powershell and connect-partnercenter. Now we will use this to connect to one of our customers tenants. First we will use AZ module and connect-azaccount. We will use the AZ module and the\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":875,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-1\/","url_meta":{"origin":957,"position":1},"title":"CSP access to tenants using powershell. Part 1","author":"Atle","date":"September 18, 2019","format":false,"excerpt":"A short explanation of how to access customer tenant using a CSP tenant SPN credential connectiong to AzureAD and AZ. Have been struggling for a while to manage all our customers tenants using powershell scripts. It can be complicated to organize all the credentials, tenant domain, tenant id's password expiry.\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":914,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-4\/","url_meta":{"origin":957,"position":2},"title":"CSP access to tenants using powershell. Part 4","author":"Atle","date":"September 24, 2019","format":false,"excerpt":"This is a small script that connects to partnercenter list all customers tenants and let you select one. When one is selected it connects to azuread and az for that customer. All my credentials are stored in SecretServer . I use a web service request to get those credentials. I\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":975,"url":"https:\/\/www.vatland.no\/index.php\/log-tenants-from-office-365-to-local-db\/","url_meta":{"origin":957,"position":3},"title":"Log tenants from office 365 to local Db","author":"Atle","date":"January 3, 2021","format":false,"excerpt":"Hi, I like to keep control of how many licenses our cutomers use versus how many\u00a0 have been purchased. Here is 1st part\u00a0 my PS script to copy the info from csp to the DB. I will start creating a database and table to keep a list of all the\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":1010,"url":"https:\/\/www.vatland.no\/index.php\/add-tenant-licenses-from-csp-to-database\/","url_meta":{"origin":957,"position":4},"title":"Add tenant licenses from csp to database.","author":"Atle","date":"January 17, 2021","format":false,"excerpt":"This is a followup from previus post. In this post I will populate the database with what licenses a tenant has aquired. This will add records of what aquired skus and 'usage'. For me this is how many license are bought versus how many are assigned. This does not account\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/uncategorized\/azure-uncategorized\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]},{"id":902,"url":"https:\/\/www.vatland.no\/index.php\/csp-access-to-tenants-using-powershell-part-3\/","url_meta":{"origin":957,"position":5},"title":"CSP access to tenants using powershell. Part 3","author":"Atle","date":"September 23, 2019","format":false,"excerpt":"In this part 3 of CSP and powershell I will show how you can connect to azureAD of a customer tenant using your CSP app credentials and refreshtoken. This is almost the same procedure as we use to connect to az. We will start with the same variables as in\u2026","rel":"","context":"In &quot;Azure&quot;","block_context":{"text":"Azure","link":"https:\/\/www.vatland.no\/index.php\/category\/azure\/"},"img":{"alt_text":"","src":"","width":0,"height":0},"classes":[]}],"_links":{"self":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/957","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/comments?post=957"}],"version-history":[{"count":8,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/957\/revisions"}],"predecessor-version":[{"id":965,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/posts\/957\/revisions\/965"}],"wp:attachment":[{"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/media?parent=957"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/categories?post=957"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.vatland.no\/index.php\/wp-json\/wp\/v2\/tags?post=957"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}