{"id":6963,"date":"2014-05-27T10:51:52","date_gmt":"2014-05-27T10:51:52","guid":{"rendered":"https:\/\/test.simple-talk.com\/uncategorized\/powershell-and-smo-be-careful-how-you-iterate\/"},"modified":"2016-07-28T10:55:08","modified_gmt":"2016-07-28T10:55:08","slug":"powershell-and-smo-be-careful-how-you-iterate","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/blogs\/powershell-and-smo-be-careful-how-you-iterate\/","title":{"rendered":"PowerShell and SMO &#8211; be careful how you iterate"},"content":{"rendered":"<p>I&#8217;ve yet to have a totally smooth experience with PowerShell and it was late on Friday when I crashed into this problem. I haven&#8217;t investigated if this is a generally well understood circumstance and if it is then I apologise for repeating everything.<\/p>\n<p>Scenario: I wanted to scan a number of server for many properties, including existing logins and to identify which accounts are bestowed with sysadmin privileges. A great task to pass to PowerShell, so with a heavy heart I started up PowerShellISE and started typing. The script doesn&#8217;t come easily to me but I follow the logic of SMO and the properties and methods available with the language so it seemed something I should be able to master.<\/p>\n<p>Version #1 of my script.<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration01.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-5350 alignnone\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration01.png\" width=\"661\" height=\"275\" alt=\"PS_Itteration01.png\" \/><\/a><\/p>\n<p>And the results it returns when executed against my home laptop server.<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration02.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5358\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration02.png\" width=\"377\" height=\"144\" alt=\"PS_Itteration02.png\" \/><\/a><\/p>\n<p>These results looked good and for a long time I was concerned with other parts of the script, for all intents and purposes quite happy that this was an accurate assessment of the server.<\/p>\n<p>Let&#8217;s just review my logic for each step of the code at the top.<\/p>\n<p>Lines 1 to 7 just set up our variables and write out the header message<\/p>\n<p>Line 8 our first loop, to go through each login on the server<\/p>\n<p>Line 10 an inner loop that will assess each role name that each login has been assigned<\/p>\n<p>Line 11 a test to see if each role has the name &#8216;sysadmin&#8217;<\/p>\n<p>Line 13 write out the login name with a bright format as it is a sysadmin login<\/p>\n<p>Line 17 write out the login name with no formatting<\/p>\n<p>It is quite possible that here someone with more PowerShell experience than me will be shouting at their screen pointing at the error I made but to me this made total sense.<\/p>\n<p>Until I altered the code, I altered lines 6 and 7 of code above to be:<\/p>\n<pre>$c = $Svr.Logins.Count<\/pre>\n<p>write-host &#8220;There are $c Logins on the server&#8221;<\/p>\n<p>This changed my output to look like this:<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration03.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5357\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration03.png\" width=\"231\" height=\"140\" alt=\"PS_Itteration03.png\" \/><\/a><\/p>\n<p>This started alarm bells ringing &#8211; there are clearly not 13 logins listed<\/p>\n<p>So, let&#8217;s see where things are going wrong, edit the script so it looks like this. I&#8217;ve highlighted the changes to make<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration04.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5356\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration04.png\" width=\"683\" height=\"304\" alt=\"PS_Itteration04.png\" \/><\/a><\/p>\n<p>Running this code shows me these results<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration05.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5355\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration05.png\" width=\"254\" height=\"145\" alt=\"PS_Itteration05.png\" \/><\/a><\/p>\n<p>Our $n variable should count up by one for each login returned and We are clearly missing some logins.<\/p>\n<p>I referenced this list back to Management Studio for my server and see the Logins as below, where there are clearly 13 logins.<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration06.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5354\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration06.png\" width=\"305\" height=\"309\" alt=\"PS_Itteration06.png\" \/><\/a><\/p>\n<p>We see a Login called Annette in SSMS but not in the script results so I opened that up and looked at its properties and it&#8217;s server roles in particular.<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration07.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5353\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration07.png\" width=\"303\" height=\"279\" alt=\"PS_Itteration07.png\" \/><\/a><\/p>\n<p>The account has only public access to the server. Inspection of the other logins that the PowerShell script misses out show they too are only members of the public role.<\/p>\n<p>Right now I can&#8217;t work out whether there is a good reason for this and if it should be expected behaviour or not. Please spend a few minutes to leave a comment if you have an opinion or theory for this.<\/p>\n<p>How to get the full list of logins. Clearly I needed to get a full list of the logins so set about reviewing my code to see if there was a better way to iterate through the roles for each login.<\/p>\n<p>This is the code that I came up with and I think it is doing everything that I need it to.<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration08.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5352\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration08.png\" width=\"654\" height=\"329\" alt=\"PS_Itteration08.png\" \/><\/a><\/p>\n<p>It gives me the expected results like this:<\/p>\n<p><a href=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration09.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alingnone size-full wp-image-5351\" src=\"https:\/\/www.red-gate.com\/simple-talk\/wp-content\/uploads\/2014\/05\/PS_Itteration09.png\" width=\"266\" height=\"171\" alt=\"PS_Itteration09.png\" \/><\/a><\/p>\n<p>So it seems that the ListMembers() method is the trouble maker in my first versions of the code. I would have expected that ListMembers should return Logins that are only members of the public role, certainly Technet makes no reference to it being left out in it&#8217;s <a href=\"http:\/\/technet.microsoft.com\/en-us\/library\/microsoft.sqlserver.management.smo.login.listmembers.aspx\">Login.ListMembers details<\/a>. Suffice to say, it&#8217;s a lesson learned and I will approach using it with caution in future circumstances.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>I&#8217;ve yet to have a totally smooth experience with PowerShell and it was late on Friday when I crashed into this problem. I haven&#8217;t investigated if this is a generally well understood circumstance and if it is then I apologise for repeating everything. Scenario: I wanted to scan a number of server for many properties,&#8230;&hellip;<\/p>\n","protected":false},"author":101210,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[2],"tags":[],"coauthors":[],"class_list":["post-6963","post","type-post","status-publish","format-standard","hentry","category-blogs"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/6963","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/101210"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=6963"}],"version-history":[{"count":7,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/6963\/revisions"}],"predecessor-version":[{"id":42384,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/6963\/revisions\/42384"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=6963"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=6963"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=6963"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=6963"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}