����JFIFXX�����    $.' ",#(7),01444'9=82<.342  2!!22222222222222222222222222222222222222222222222222����"��4�� ���,�PG"Z_�4�˷����kjز�Z�,F+��_z�,�© �����zh6�٨�ic�fu���#ډb���_�N�?��wQ���5-�~�I���8����TK<5o�Iv-�����k�_U_�����~b�M��d����Ӝ�U�Hh��?]��E�w��Q���k�{��_}qFW7HTՑ��Y��F�?_�'ϔ��_�Ջt��=||I ��6�έ"�����D���/[�k�9���Y�8ds|\���Ҿp6�Ҵ���]��.����6�z<�v��@]�i%��$j��~�g��J>��no����pM[me�i$[����s�o�ᘨ�˸ nɜG-�ĨU�ycP�3.DB�li�;��hj���x7Z^�N�h������N3u{�:j�x�힞��#M&��jL P@_���� P��&��o8������9�����@Sz6�t7#O�ߋ �s}Yf�T���lmr����Z)'N��k�۞p����w\�Tȯ?�8`�O��i{wﭹW�[�r�� ��Q4F�׊���3m&L�=��h3����z~��#�\�l :�F,j@�� ʱ�wQT����8�"kJO���6�֚l����}���R�>ډK���]��y����&����p�}b��;N�1�m�r$�|��7�>e�@B�TM*-iH��g�D�)� E�m�|�ؘbҗ�a��Ҿ����t4���o���G��*oCN�rP���Q��@z,|?W[0�����:�n,jWiE��W��$~/�hp\��?��{(�0���+�Y8rΟ�+����>S-S����VN;�}�s?.����� w�9��˟<���Mq4�Wv'��{)0�1mB��V����W[�����8�/<� �%���wT^�5���b��)iM� pg�N�&ݝ��VO~�q���u���9� ����!��J27����$O-���! �:�%H��� ـ����y�ΠM=t{!S�� oK8������t<����è:a������[�����ա�H���~��w��Qz`�po�^ ����Q��n� �,uu�C�$ ^���,������8�#��:�6��e�|~���!�3�3.�\0��q��o�4`.|� ����y�Q�`~;�d�ׯ,��O�Zw�������`73�v�܋�<���Ȏ�� ـ4k��5�K�a�u�=9Yd��$>x�A�&�� j0� ���vF��� Y�|�y��� ~�6�@c��1vOp�Ig����4��l�OD���L����� R���c���j�_�uX6��3?nk��Wy�f;^*B� ��@�~a�`��Eu������+���6�L��.ü>��}y���}_�O�6�͐�:�YrG�X��kG�����l^w���~㒶sy��Iu�!� W ��X��N�7BV��O��!X�2����wvG�R�f�T#�����t�/?���%8�^�W�aT��G�cL�M���I��(J����1~�8�?aT ���]����AS�E��(��*E}� 2��#I/�׍qz��^t�̔���b�Yz4x���t�){ OH��+(E��A&�N�������XT��o��"�XC��'���)}�J�z�p� ��~5�}�^����+�6����w��c��Q�|Lp�d�H��}�(�.|����k��c4^�"�����Z?ȕ ��a<�L�!039C� �Eu�C�F�Ew�ç ;�n?�*o���B�8�bʝ���'#Rqf���M}7����]����s2tcS{�\icTx;�\��7K���P���ʇ Z O-��~��c>"��?�������P��E��O�8��@�8��G��Q�g�a�Վ���󁶠�䧘��_%#r�>�1�z�a��eb��qcPѵ��n���#L��� =��׀t� L�7�`��V���A{�C:�g���e@�w1 Xp3�c3�ġ����p��M"'-�@n4���fG��B3�DJ�8[Jo�ߐ���gK)ƛ��$���� ���8�3�����+���� �����6�ʻ���� ���S�kI�*KZlT _`���?��K����QK�d����B`�s}�>���`��*�>��,*@J�d�oF*����弝��O}�k��s��]��y�ߘ��c1G�V���<=�7��7����6�q�PT��tXԀ�!9*4�4Tހ3XΛex�46���Y��D ����� �BdemDa����\�_l,��G�/���֌7���Y�](�xTt^%�GE�����4�}bT���ڹ�����;Y)���B�Q��u��>J/J �⮶.�XԄ��j�ݳ�+E��d ��r�5�_D�1 ��o�� �B�x�΢�#���<��W�����8���R6�@g�M�.��� dr�D��>(otU��@x=��~v���2� ӣ�d�oBd��3�eO�6�㣷�����ݜ6��6Y��Qz`��S��{���\P�~z m5{J/L��1������<�e�ͅPu�b�]�ϔ���'������f�b� Zpw��c`"��i���BD@:)ִ�:�]��hv�E�w���T�l��P���"Ju�}��وV J��G6��. J/�Qgl߭�e�����@�z�Zev2u�)]կ�����7x���s�M�-<ɯ�c��r�v�����@��$�ޮ}lk���a���'����>x��O\�ZFu>�����ck#��&:��`�$�ai�>2Δ����l���oF[h��lE�ܺ�Πk:)���`�� $[6�����9�����kOw�\|���8}������ބ:��񶐕��I�A1/�=�2[�,�!��.}gN#�u����b��� ~��݊��}34q����d�E��Lc��$��"�[q�U�硬g^��%B �z���r�pJ�ru%v\h1Y�ne`ǥ:g���pQM~�^�Xi� ��`S�:V29.�P���V�?B�k�� AEvw%�_�9C�Q����wKekPؠ�\�;Io d�{ ߞo�c1eP����\� `����E=���@K<�Y���eڼ�J���w����{av�F�'�M�@/J��+9p���|]�����Iw &`��8���&M�hg��[�{��Xj��%��Ӓ�$��(����ʹN���<>�I���RY���K2�NPlL�ɀ)��&e����B+ь����( � �JTx���_?EZ� }@ 6�U���뙢ط�z��dWI�n` D����噥�[��uV��"�G&Ú����2g�}&m��?ċ�"����Om#��������� ��{�ON��"S�X��Ne��ysQ���@Fn��Vg���dX�~nj�]J�<�K]:��FW��b�������62�=��5f����JKw��bf�X�55��~J �%^����:�-�QIE��P��v�nZum� z � ~ə ���� ���ة����;�f��\v���g�8�1��f24;�V���ǔ�)����9���1\��c��v�/'Ƞ�w�������$�4�R-��t���� e�6�/�ġ �̕Ecy�J���u�B���<�W�ַ~�w[B1L۲�-JS΂�{���΃������A��20�c#��@ 0!1@AP"#2Q`$3V�%45a6�FRUq��� ����^7ׅ,$n�������+��F�`��2X'��0vM��p�L=������5��8������u�p~���.�`r�����\���O��,ư�0oS ��_�M�����l���4�kv\JSd���x���SW�<��Ae�IX����������$I���w�:S���y���›R��9�Q[���,�5�;�@]�%���u�@ *ro�lbI �� ��+���%m:�͇ZV�����u�̉����θau<�fc�.����{�4Ա� �Q����*�Sm��8\ujqs]{kN���)qO�y�_*dJ�b�7���yQqI&9�ԌK!�M}�R�;������S�T���1���i[U�ɵz�]��U)V�S6���3$K{�ߊ<�(� E]Զ[ǼENg�����'�\?#)Dkf��J���o��v���'�%ƞ�&K�u�!��b�35LX�Ϸ��63$K�a�;�9>,R��W��3�3� d�JeTYE.Mϧ��-�o�j3+y��y^�c�������VO�9NV\nd�1 ��!͕_)a�v;����թ�M�lWR1��)El��P;��yوÏ�u 3�k�5Pr6<�⒲l�!˞*��u־�n�!�l:����UNW ��%��Chx8vL'��X�@��*��)���̮��ˍ��� ���D-M�+J�U�kvK����+�x8��cY������?�Ԡ��~3mo��|�u@[XeY�C�\Kp�x8�oC�C�&����N�~3-H���� ��MX�s�u<`���~"WL��$8ξ��3���a�)|:@�m�\���^�`�@ҷ)�5p+��6���p�%i)P M���ngc�����#0Aruz���RL+xSS?���ʮ}()#�t��mˇ!��0}}y����<�e� �-ή�Ԩ��X������ MF���ԙ~l L.3���}�V뽺�v�����멬��Nl�)�2����^�Iq��a��M��qG��T�����c3#������3U�Ǎ���}��לS�|qa��ڃ�+���-��2�f����/��bz��ڐ�� �ݼ[2�ç����k�X�2�* �Z�d���J�G����M*9W���s{��w���T��x��y,�in�O�v��]���n����P�$�JB@=4�OTI�n��e�22a\����q�d���%�$��(���:���: /*�K[PR�fr\nڙdN���F�n�$�4�[�� U�zƶ����� �mʋ���,�ao�u 3�z� �x��Kn����\[��VFmbE;�_U��&V�Gg�]L�۪&#n%�$ɯ�dG���D�TI=�%+AB�Ru#��b4�1�»x�cs�YzڙJG��f��Il��d�eF'T� iA��T���uC�$����Y��H?����[!G`}���ͪ� �纤Hv\������j�Ex�K���!���OiƸ�Yj�+u-<���'q����uN�*�r\��+�]���<�wOZ.fp�ێ��,-*)V?j-kÊ#�`�r��dV����(�ݽBk�����G�ƛk�QmUڗe��Z���f}|����8�8��a���i��3'J�����~G_�^���d�8w������ R�`(�~�.��u���l�s+g�bv���W���lGc}��u���afE~1�Ue������Z�0�8�=e�� f@/�jqEKQQ�J��oN��J���W5~M>$6�Lt�;$ʳ{���^��6�{����v6���ķܰg�V�cnn �~z�x�«�,2�u�?cE+Ș�H؎�%�Za�)���X>uW�Tz�Nyo����s���FQƤ��$��*�&�LLXL)�1�" L��eO��ɟ�9=���:t��Z���c��Ž���Y?�ӭV�wv�~,Y��r�ۗ�|�y��GaF�����C�����.�+� ���v1���fήJ�����]�S��T��B��n5sW}y�$��~z�'�c ��8 ��� ,! �p��VN�S��N�N�q��y8z˱�A��4��*��'������2n<�s���^ǧ˭P�Jޮɏ�U�G�L�J�*#��<�V��t7�8����TĜ>��i}K%,���)[��z�21z ?�N�i�n1?T�I�R#��m-�����������������1����lA�`��fT5+��ܐ�c�q՝��ʐ��,���3�f2U�եmab��#ŠdQ�y>\��)�SLY����w#��.���ʑ�f��� ,"+�w�~�N�'�c�O�3F�������N<���)j��&��,-� �љ���֊�_�zS���TǦ����w�>��?�������n��U仆�V���e�����0���$�C�d���rP �m�׈e�Xm�Vu� �L��.�bֹ��� �[Դaզ���*��\y�8�Է:�Ez\�0�Kq�C b��̘��cө���Q��=0Y��s�N��S.���3.���O�o:���#���v7�[#߫ ��5�܎�L���Er4���9n��COWlG�^��0k�%<���ZB���aB_���������'=��{i�v�l�$�uC���mƎҝ{�c㱼�y]���W�i ��ߧc��m�H� m�"�"�����;Y�ߝ�Z�Ǔ�����:S#��|}�y�,/k�Ld� TA�(�AI$+I3��;Y*���Z��}|��ӧO��d�v��..#:n��f>�>���ȶI�TX��� 8��y����"d�R�|�)0���=���n4��6ⲑ�+��r<�O�܂~zh�z����7ܓ�HH�Ga롏���nCo�>������a ���~]���R���̲c?�6(�q�;5%� |�uj�~z8R=X��I�V=�|{v�Gj\gc��q����z�؋%M�ߍ����1y��#��@f^���^�>N�����#x#۹��6�Y~�?�dfPO��{��P�4��V��u1E1J �*|���%���JN��`eWu�zk M6���q t[�� ��g�G���v��WIG��u_ft����5�j�"�Y�:T��ɐ���*�;� e5���4����q$C��2d�}���� _S�L#m�Yp��O�.�C�;��c����Hi#֩%+) �Ӎ��ƲV���SYź��g |���tj��3�8���r|���V��1#;.SQ�A[���S������#���`n�+���$��$I �P\[�@�s��(�ED�z���P��])8�G#��0B��[ى��X�II�q<��9�~[Z멜�Z�⊔IWU&A>�P~�#��dp<�?����7���c��'~���5 ��+$���lx@�M�dm��n<=e�dyX��?{�|Aef ,|n3�<~z�ƃ�uۧ�����P��Y,�ӥQ�*g�#먙R�\���;T��i,��[9Qi歉����c>]9�� ��"�c��P�� �Md?٥��If�ت�u��k��/����F��9�c*9��Ǎ:�ØF���z�n*�@|I�ށ9����N3{'��[�'ͬ�Ҳ4��#}��!�V� Fu��,�,mTIk���v C�7v���B�6k�T9��1�*l� '~��ƞF��lU��'�M ����][ΩũJ_�{�i�I�n��$���L�� j��O�dx�����kza۪��#�E��Cl����x˘�o�����V���ɞ�ljr��)�/,�߬h�L��#��^��L�ф�,íMƁe�̩�NB�L�����iL����q�}��(��q��6IçJ$�W�E$��:������=#����(�K�B����zђ <��K(�N�۫K�w��^O{!����)�H���>x�������lx�?>Պ�+�>�W���,Ly!_�D���Ō�l���Q�!�[ �S����J��1��Ɛ�Y}��b,+�Lo�x�ɓ)����=�y�oh�@�꥟/��I��ѭ=��P�y9��� �ۍYӘ�e+�p�Jnϱ?V\SO%�(�t� ���=?MR�[Ș�����d�/ ��n�l��B�7j� ��!�;ӥ�/�[-���A�>�dN�sLj ��,ɪv��=1c�.SQ�O3�U���ƀ�ܽ�E����������̻��9G�ϷD�7(�}��Ävӌ\�y�_0[w ���<΍>����a_��[0+�L��F.�޺��f�>oN�T����q;���y\��bՃ��y�jH�<|q-eɏ�_?_9+P���Hp$�����[ux�K w�Mw��N�ی'$Y2�=��q���KB��P��~������Yul:�[<����F1�2�O���5=d����]Y�sw:���Ϯ���E��j,_Q��X��z`H1,#II ��d�wr��P˂@�ZJV����y$�\y�{}��^~���[:N����ߌ�U�������O��d�����ؾe��${p>G��3c���Ė�lʌ�� ת��[��`ϱ�-W����dg�I��ig2��� ��}s ��ؤ(%#sS@���~���3�X�nRG�~\jc3�v��ӍL��M[JB�T��s3}��j�Nʖ��W����;7��ç?=X�F=-�=����q�ߚ���#���='�c��7���ڑW�I(O+=:uxq�������������e2�zi+�kuG�R��������0�&e�n���iT^J����~\jy���p'dtG��s����O��3����9* �b#Ɋ�� p������[Bws�T�>d4�ۧs���nv�n���U���_�~,�v����ƜJ1��s�� �QIz��)�(lv8M���U=�;����56��G���s#�K���MP�=��LvyGd��}�VwWBF�'�à �?MH�U�g2�� ����!�p�7Q��j��ڴ����=��j�u��� Jn�A s���uM������e��Ɔ�Ҕ�!)'��8Ϣ�ٔ��ޝ(��Vp���צ֖d=�IC�J�Ǡ{q������kԭ�߸���i��@K����u�|�p=..�*+����x�����z[Aqġ#s2a�Ɗ���RR�)*HRsi�~�a &f��M��P����-K�L@��Z��Xy�'x�{}��Zm+���:�)�) IJ�-i�u���� ���ܒH��'�L(7�y�GӜq���� j��� 6ߌg1�g�o���,kر���tY�?W,���p���e���f�OQS��!K�۟cҒA�|ս�j�>��=⬒��˧L[�� �߿2JaB~R��u�:��Q�] �0H~���]�7��Ƽ�I���(}��cq '�ήET���q�?f�ab���ӥvr� �)o��-Q��_'����ᴎo��K������;��V���o��%���~OK ����*��b�f:���-ťIR��`B�5!RB@���ï�� �u �̯e\�_U�_������� g�ES��3�������QT��a����x����U<~�c?�*�#]�MW,[8O�a�x��]�1bC|踤�P��lw5V%�)�{t�<��d��5���0i�XSU��m:��Z�┵�i�"��1�^B�-��P�hJ��&)O��*�D��c�W��vM��)����}���P��ܗ-q����\mmζZ-l@�}��a��E�6��F�@��&Sg@���ݚ�M����� ȹ 4����#p�\H����dYDo�H���"��\��..R�B�H�z_�/5˘����6��KhJR��P�mƶi�m���3�,#c�co��q�a)*Pt����R�m�k�7x�D�E�\Y�閣_X�<���~�)���c[[�BP����6�Yq���S��0����%_����;��Àv�~�| VS؇ ��'O0��F0��\���U�-�d@�����7�SJ*z��3n��y��P����O���������m�~�P�3|Y��ʉr#�C�<�G~�.,! ���bqx���h~0=��!ǫ�jy����l�O,�[B��~��|9��ٱ����Xly�#�i�B��g%�S��������tˋ���e���ې��\[d�t)��.+u�|1 ������#�~Oj����hS�%��i.�~X���I�H�m��0n���c�1uE�q��cF�RF�o���7� �O�ꮧ� ���ۛ{��ʛi5�rw?׌#Qn�TW��~?y$��m\�\o����%W� ?=>S�N@�� �Ʈ���R����N�)�r"C�:��:����� �����#��qb��Y�. �6[��2K����2u�Ǧ�HYR��Q�MV��� �G�$��Q+.>�����nNH��q�^��� ����q��mM��V��D�+�-�#*�U�̒ ���p욳��u:�������IB���m���PV@O���r[b= �� ��1U�E��_Nm�yKbN�O���U�}�the�`�|6֮P>�\2�P�V���I�D�i�P�O;�9�r�mAHG�W�S]��J*�_�G��+kP�2����Ka�Z���H�'K�x�W�MZ%�O�YD�Rc+o��?�q��Ghm��d�S�oh�\�D�|:W������UA�Qc yT�q������~^�H��/��#p�CZ���T�I�1�ӏT����4��"�ČZ�����}��`w�#�*,ʹ�� ��0�i��課�Om�*�da��^gJ݅{���l�e9uF#T�ֲ��̲�ٞC"�q���ߍ ոޑ�o#�XZTp����@ o�8��(jd��xw�]�,f���`~�|,s��^����f�1���t��|��m�򸄭/ctr��5s��7�9Q�4�H1꠲BB@l9@���C�����+�wp�xu�£Yc�9��?`@#�o�mH�s2��)�=��2�.�l����jg�9$�Y�S�%*L������R�Y������7Z���,*=�䷘$�������arm�o�ϰ���UW.|�r�uf����IGw�t����Zwo��~5 ��YյhO+=8fF�)�W�7�L9lM�̘·Y���֘YLf�큹�pRF���99.A �"wz��=E\Z���'a� 2��Ǚ�#;�'}�G���*��l��^"q��+2FQ� hj��kŦ��${���ޮ-�T�٭cf�|�3#~�RJ����t��$b�(R��(����r���dx� >U b�&9,>���%E\� Ά�e�$��'�q't��*�א���ެ�b��-|d���SB�O�O��$�R+�H�)�܎�K��1m`;�J�2�Y~9��O�g8=vqD`K[�F)k�[���1m޼c��n���]s�k�z$@��)!I �x՝"v��9=�ZA=`Ɠi �:�E��)`7��vI��}d�YI�_ �o�:ob���o ���3Q��&D&�2=�� �Ά��;>�h����y.*ⅥS������Ӭ�+q&����j|UƧ����}���J0��WW< ۋS�)jQR�j���Ư��rN)�Gű�4Ѷ(�S)Ǣ�8��i��W52���No˓� ۍ%�5brOn�L�;�n��\G����=�^U�dI���8$�&���h��'���+�(������cȁ߫k�l��S^���cƗjԌE�ꭔ��gF���Ȓ��@���}O���*;e�v�WV���YJ\�]X'5��ղ�k�F��b 6R�o՜m��i N�i����>J����?��lPm�U��}>_Z&�KK��q�r��I�D�Չ~�q�3fL�:S�e>���E���-G���{L�6p�e,8��������QI��h��a�Xa��U�A'���ʂ���s�+טIjP�-��y�8ۈZ?J$��W�P� ��R�s�]��|�l(�ԓ��sƊi��o(��S0��Y� 8�T97.�����WiL��c�~�dxc�E|�2!�X�K�Ƙਫ਼�$((�6�~|d9u+�qd�^3�89��Y�6L�.I�����?���iI�q���9�)O/뚅����O���X��X�V��ZF[�یgQ�L��K1���RҖr@v�#��X�l��F���Нy�S�8�7�kF!A��sM���^rkp�jP�DyS$N���q��nxҍ!U�f�!eh�i�2�m���`�Y�I�9r�6� �TF���C}/�y�^���Η���5d�'��9A-��J��>{�_l+�`��A���[�'��յ�ϛ#w:݅�%��X�}�&�PSt�Q�"�-��\縵�/����$Ɨh�Xb�*�y��BS����;W�ջ_mc�����vt?2}1�;qS�d�d~u:2k5�2�R�~�z+|HE!)�Ǟl��7`��0�<�,�2*���Hl-��x�^����'_TV�gZA�'j� ^�2Ϊ��N7t�����?w�� �x1��f��Iz�C-Ȗ��K�^q�;���-W�DvT�7��8�Z�������� hK�(P:��Q- �8�n�Z���܃e貾�<�1�YT<�,�����"�6{/ �?�͟��|1�:�#g��W�>$����d��J��d�B��=��jf[��%rE^��il:��B���x���Sּ�1հ��,�=��*�7 fcG��#q� �eh?��2�7�����,�!7x��6�n�LC�4x��},Geǝ�tC.��vS �F�43��zz\��;QYC,6����~;RYS/6���|2���5���v��T��i����������mlv��������&� �nRh^ejR�LG�f���? �ۉҬܦƩ��|��Ȱ����>3����!v��i�ʯ�>�v��オ�X3e���_1z�Kȗ\<������!�8���V��]��?b�k41�Re��T�q��mz��TiOʦ�Z��Xq���L������q"+���2ۨ��8}�&N7XU7Ap�d�X��~�׿��&4e�o�F��� �H����O���č�c�� 懴�6���͉��+)��v;j��ݷ�� �UV�� i��� j���Y9GdÒJ1��詞�����V?h��l����l�cGs�ځ�������y�Ac�����\V3�? �� ܙg�>qH�S,�E�W�[�㺨�uch�⍸�O�}���a��>�q�6�n6����N6�q������N ! 1AQaq�0@����"2BRb�#Pr���3C`��Scst���$4D���%Td�� ?���N����a��3��m���C���w��������xA�m�q�m���m������$����4n淿t'��C"w��zU=D�\R+w�p+Y�T�&�պ@��ƃ��3ޯ?�Aﶂ��aŘ���@-�����Q�=���9D��ռ�ѻ@��M�V��P��܅�G5�f�Y<�u=,EC)�<�Fy'�"�&�չ�X~f��l�KԆV��?�� �W�N����=(� �;���{�r����ٌ�Y���h{�١������jW����P���Tc�����X�K�r��}���w�R��%��?���E��m�� �Y�q|����\lEE4���r���}�lsI�Y������f�$�=�d�yO����p�����yBj8jU�o�/�S��?�U��*������ˍ�0������u�q�m [�?f����a�� )Q�>����6#������� ?����0UQ����,IX���(6ڵ[�DI�MNލ�c&���υ�j\��X�R|,4��� j������T�hA�e��^���d���b<����n�� �즇�=!���3�^�`j�h�ȓr��jẕ�c�,ٞX����-����a�ﶔ���#�$��]w�O��Ӫ�1y%��L�Y<�wg#�ǝ�̗`�x�xa�t�w��»1���o7o5��>�m뭛C���Uƃߜ}�C���y1Xνm�F8�jI���]����H���ۺиE@I�i;r�8ӭ����V�F�Շ| ��&?�3|x�B�MuS�Ge�=Ӕ�#BE5G�����Y!z��_e��q�р/W>|-�Ci߇�t�1ޯќd�R3�u��g�=0 5��[?�#͏��q�cf���H��{ ?u�=?�?ǯ���}Z��z���hmΔ�BFTW�����<�q�(v� ��!��z���iW]*�J�V�z��gX֧A�q�&��/w���u�gYӘa���; �i=����g:��?2�dž6�ى�k�4�>�Pxs����}������G�9��3 ���)gG�R<>r h�$��'nc�h�P��Bj��J�ҧH� -��N1���N��?��~��}-q!=��_2hc�M��l�vY%UE�@|�v����M2�.Y[|y�"Eï��K�ZF,�ɯ?,q�?v�M 80jx�"�;�9vk�����+ ֧�� �ȺU��?�%�vcV��mA�6��Qg^M����A}�3�nl� QRN�l8�kkn�'�����(��M�7m9و�q���%ޟ���*h$Zk"��$�9��: �?U8�Sl��,,|ɒ��xH(ѷ����Gn�/Q�4�P��G�%��Ա8�N��!� �&�7�;���eKM7�4��9R/%����l�c>�x;������>��C�:�����t��h?aKX�bhe�ᜋ^�$�Iհ �hr7%F$�E��Fd���t��5���+�(M6�t����Ü�UU|zW�=a�Ts�Tg������dqP�Q����b'�m���1{|Y����X�N��b �P~��F^F:����k6�"�j!�� �I�r�`��1&�-$�Bevk:y���#yw��I0��x��=D�4��tU���P�ZH��ڠ底taP��6����b>�xa����Q�#� WeF��ŮNj�p�J* mQ�N����*I�-*�ȩ�F�g�3 �5��V�ʊ�ɮ�a��5F���O@{���NX��?����H�]3��1�Ri_u��������ѕ�� ����0��� F��~��:60�p�͈�S��qX#a�5>���`�o&+�<2�D����: �������ڝ�$�nP���*)�N�|y�Ej�F�5ټ�e���ihy�Z �>���k�bH�a�v��h�-#���!�Po=@k̆IEN��@��}Ll?j�O������߭�ʞ���Q|A07x���wt!xf���I2?Z��<ץ�T���cU�j��]��陎Ltl �}5�ϓ��$�,��O�mˊ�;�@O��jE��j(�ا,��LX���LO���Ц�90�O �.����a��nA���7������j4 ��W��_ٓ���zW�jcB������y՗+EM�)d���N�g6�y1_x��p�$Lv:��9�"z��p���ʙ$��^��JԼ*�ϭ����o���=x�Lj�6�J��u82�A�H�3$�ٕ@�=Vv�]�'�qEz�;I˼��)��=��ɯ���x �/�W(V���p�����$ �m�������u�����񶤑Oqˎ�T����r��㠚x�sr�GC��byp�G��1ߠ�w e�8�$⿄����/�M{*}��W�]˷.�CK\�ުx���/$�WPw���r� |i���&�}�{�X� �>��$-��l���?-z���g����lΆ���(F���h�vS*���b���߲ڡn,|)mrH[���a�3�ר�[1��3o_�U�3�TC�$��(�=�)0�kgP���� ��u�^=��4 �WYCҸ:��vQ�ר�X�à��tk�m,�t*��^�,�}D*� �"(�I��9R����>`�`��[~Q]�#af��i6l��8���6�:,s�s�N6�j"�A4���IuQ��6E,�GnH��zS�HO�uk�5$�I�4��ؤ�Q9�@��C����wp�BGv[]�u�Ov���0I4���\��y�����Q�Ѹ��~>Z��8�T��a��q�ޣ;z��a���/��S��I:�ܫ_�|������>=Z����8:�S��U�I�J��"IY���8%b8���H��:�QO�6�;7�I�S��J��ҌAά3��>c���E+&jf$eC+�z�;��V����� �r���ʺ������my�e���aQ�f&��6�ND��.:��NT�vm�<- u���ǝ\MvZY�N�NT��-A�>jr!S��n�O 1�3�Ns�%�3D@���`������ܟ 1�^c<���� �a�ɽ�̲�Xë#�w�|y�cW�=�9I*H8�p�^(4���՗�k��arOcW�tO�\�ƍR��8����'�K���I�Q�����?5�>[�}��yU�ײ -h��=��% q�ThG�2�)���"ו3]�!kB��*p�FDl�A���,�eEi�H�f�Ps�����5�H:�Փ~�H�0Dت�D�I����h�F3�������c��2���E��9�H��5�zԑ�ʚ�i�X�=:m�xg�hd(�v����׊�9iS��O��d@0ڽ���:�p�5�h-��t�&���X�q�ӕ,��ie�|���7A�2���O%P��E��htj��Y1��w�Ѓ!����  ���� ࢽ��My�7�\�a�@�ţ�J �4�Ȼ�F�@o�̒?4�wx��)��]�P��~�����u�����5�����7X ��9��^ܩ�U;Iꭆ 5 �������eK2�7(�{|��Y׎ �V��\"���Z�1� Z�����}��(�Ǝ"�1S���_�vE30>���p;� ΝD��%x�W�?W?v����o�^V�i�d��r[��/&>�~`�9Wh��y�;���R��� ;;ɮT��?����r$�g1�K����A��C��c��K��l:�'��3 c�ﳯ*"t8�~l��)���m��+U,z��`(�>yJ�?����h>��]��v��ЍG*�{`��;y]��I�T� ;c��NU�fo¾h���/$���|NS���1�S�"�H��V���T���4��uhǜ�]�v;���5�͠x��'C\�SBpl���h}�N����� A�Bx���%��ޭ�l��/����T��w�ʽ]D�=����K���ž�r㻠l4�S�O?=�k �M:� ��c�C�a�#ha���)�ѐxc�s���gP�iG��{+���x���Q���I= �� z��ԫ+ �8"�k�ñ�j=|����c ��y��CF��/��*9ж�h{ �?4�o� ��k�m�Q�N�x��;�Y��4膚�a�w?�6�>e]�����Q�r�:����g�,i"�����ԩA�*M�<�G��b�if��l^M��5� �Ҩ�{����6J��ZJ�����P�*�����Y���ݛu�_4�9�I8�7���������,^ToR���m4�H��?�N�S�ѕw��/S��甍�@�9H�S�T��t�ƻ���ʒU��*{Xs�@����f�����֒Li�K{H�w^���������Ϥm�tq���s� ���ք��f:��o~s��g�r��ט� �S�ѱC�e]�x���a��) ���(b-$(�j>�7q�B?ӕ�F��hV25r[7 Y� }L�R��}����*sg+��x�r�2�U=�*'WS��ZDW]�WǞ�<��叓���{�$�9Ou4��y�90-�1�'*D`�c�^o?(�9��u���ݐ��'PI&� f�Jݮ�������:wS����jfP1F:X �H�9dԯ���˝[�_54 �}*;@�ܨ�� ð�yn�T���?�ןd�#���4rG�ͨ��H�1�|-#���Mr�S3��G�3�����)�.᧏3v�z֑��r����$G"�`j �1t��x0<Ɔ�Wh6�y�6��,œ�Ga��gA����y��b��)��h�D��ß�_�m��ü �gG;��e�v��ݝ�nQ� ��C����-�*��o���y�a��M��I�>�<���]obD��"�:���G�A��-\%LT�8���c�)��+y76���o�Q�#*{�(F�⽕�y����=���rW�\p���۩�c���A���^e6��K������ʐ�cVf5$�'->���ՉN"���F�"�UQ@�f��Gb~��#�&�M=��8�ט�JNu9��D��[̤�s�o�~������ G��9T�tW^g5y$b��Y'��س�Ǵ�=��U-2 #�MC�t(�i� �lj�@Q 5�̣i�*�O����s�x�K�f��}\��M{E�V�{�υ��Ƈ�����);�H����I��fe�Lȣr�2��>��W�I�Ȃ6������i��k�� �5�YOxȺ����>��Y�f5'��|��H+��98pj�n�.O�y�������jY��~��i�w'������l�;�s�2��Y��:'lg�ꥴ)o#'Sa�a�K��Z� �m��}�`169�n���"���x��I ��*+� }F<��cГ���F�P�������ֹ*�PqX�x۩��,� ��N�� �4<-����%����:��7����W���u�`����� $�?�I��&����o��o��`v�>��P��"��l���4��5'�Z�gE���8���?��[�X�7(��.Q�-��*���ތL@̲����v��.5���[��=�t\+�CNܛ��,g�SQnH����}*F�G16���&:�t��4ُ"A��̣��$�b �|����#rs��a�����T�� ]�<�j��BS�('$�ɻ� �wP;�/�n��?�ݜ��x�F��yUn�~mL*-�������Xf�wd^�a�}��f�,=t�׵i�.2/wpN�Ep8�OР���•��R�FJ� 55TZ��T �ɭ�<��]��/�0�r�@�f��V��V����Nz�G��^���7hZi����k��3�,kN�e|�vg�1{9]_i��X5y7� 8e]�U����'�-2,���e"����]ot�I��Y_��n�(JҼ��1�O ]bXc���Nu�No��pS���Q_���_�?i�~�x h5d'�(qw52] ��'ޤ�q��o1�R!���`ywy�A4u���h<קy���\[~�4�\ X�Wt/� 6�����n�F�a8��f���z �3$�t(���q��q�x��^�XWeN'p<-v�!�{�(>ӽDP7��ո0�y)�e$ٕv�Ih'Q�EA�m*�H��RI��=:��� ���4牢) �%_iN�ݧ�l]� �Nt���G��H�L��� ɱ�g<���1V�,�J~�ٹ�"K��Q�� 9�HS�9�?@��k����r�;we݁�]I�!{ �@�G�[�"��`���J:�n]�{�cA�E����V��ʆ���#��U9�6����j�#Y�m\��q�e4h�B�7��C�������d<�?J����1g:ٳ���=Y���D�p�ц� ׈ǔ��1�]26؜oS�'��9�V�FVu�P�h�9�xc�oq�X��p�o�5��Ա5$�9W�V(�[Ak�aY錎qf;�'�[�|���b�6�Ck��)��#a#a˙��8���=äh�4��2��C��4tm^ �n'c���]GQ$[Wҿ��i���vN�{Fu ��1�gx��1┷���N�m��{j-,��x�� Ūm�ЧS�[�s���Gna���䑴�� x�p 8<������97�Q���ϴ�v�aϚG��Rt�Һ׈�f^\r��WH�JU�7Z���y)�vg=����n��4�_)y��D'y�6�]�c�5̪�\� �PF�k����&�c;��cq�$~T�7j ���nç]�<�g ":�to�t}�159�<�/�8������m�b�K#g'I'.W�����6��I/��>v��\�MN��g���m�A�yQL�4u�Lj�j9��#44�t��l^�}L����n��R��!��t��±]��r��h6ٍ>�yҏ�N��fU�� ���� Fm@�8}�/u��jb9������he:A�y�ծw��GpΧh�5����l}�3p468��)U��d��c����;Us/�֔�YX�1�O2��uq�s��`hwg�r~�{ R��mhN��؎*q 42�*th��>�#���E����#��Hv�O����q�}�����6�e��\�,Wk�#���X��b>��p}�դ��3���T5��†��6��[��@�P�y*n��|'f�֧>�lư΂�̺����SU�'*�q�p�_S�����M�� '��c�6�����m�� ySʨ;M��r���Ƌ�m�Kxo,���Gm�P��A�G�:��i��w�9�}M(�^�V��$ǒ�ѽ�9���|���� �a����J�SQ�a���r�B;����}���ٻ֢�2�%U���c�#�g���N�a�ݕ�'�v�[�OY'��3L�3�;,p�]@�S��{ls��X�'���c�jw�k'a�.��}�}&�� �dP�*�bK=ɍ!����;3n�gΊU�ߴmt�'*{,=SzfD� A��ko~�G�aoq�_mi}#�m�������P�Xhύ����mxǍ�΂���巿zf��Q���c���|kc�����?���W��Y�$���_Lv����l߶��c���`?����l�j�ݲˏ!V��6����U�Ђ(A���4y)H���p�Z_�x��>���e��R��$�/�`^'3qˏ�-&Q�=?��CFVR �D�fV�9��{�8g�������n�h�(P"��6�[�D���< E�����~0<@�`�G�6����Hг�cc�� �c�K.5��D��d�B���`?�XQ��2��ٿyqo&+�1^� DW�0�ꊩ���G�#��Q�nL3��c���������/��x ��1�1[y�x�პCW��C�c�UĨ80�m�e�4.{�m��u���I=��f�����0QRls9���f���������9���~f�����Ǩ��a�"@�8���ȁ�Q����#c�ic������G��$���G���r/$W�(��W���V�"��m�7�[m�A�m����bo��D� j����۳� l���^�k�h׽����� ��#� iXn�v��eT�k�a�^Y�4�BN��ĕ��0 !01@Q"2AaPq3BR������?���@4�Q�����T3,���㺠�W�[=JK�Ϟ���2�r^7��vc�:�9 �E�ߴ�w�S#d���Ix��u��:��Hp��9E!�� V 2;73|F��9Y���*ʬ�F��D����u&���y؟��^EA��A��(ɩ���^��GV:ݜDy�`��Jr29ܾ�㝉��[���E;Fzx��YG��U�e�Y�C���� ����v-tx����I�sם�Ę�q��Eb�+P\ :>�i�C'�;�����k|z�رn�y]�#ǿb��Q��������w�����(�r|ӹs��[�D��2v-%��@;�8<a���[\o[ϧw��I!��*0�krs)�[�J9^��ʜ��p1)� "��/_>��o��<1����A�E�y^�C��`�x1'ܣn�p��s`l���fQ��):�l����b>�Me�jH^?�kl3(�z:���1ŠK&?Q�~�{�ٺ�h�y���/�[��V�|6��}�KbX����mn[-��7�5q�94�������dm���c^���h� X��5��<�eޘ>G���-�}�دB�ޟ� ��|�rt�M��V+�]�c?�-#ڛ��^ǂ}���Lkr���O��u�>�-D�ry� D?:ޞ�U��ǜ�7�V��?瓮�"�#���r��չģVR;�n���/_� ؉v�ݶe5d�b9��/O��009�G���5n�W����JpA�*�r9�>�1��.[t���s�F���nQ� V 77R�]�ɫ8����_0<՜�IF�u(v��4��F�k�3��E)��N:��yڮe��P�`�1}�$WS��J�SQ�N�j�ٺ��޵�#l���ј(�5=��5�lǏmoW�v-�1����v,W�mn��߀$x�<����v�j(����c]��@#��1������Ǔ���o'��u+����;G�#�޸��v-lη��/(`i⣍Pm^���ԯ̾9Z��F��������n��1��� ��]�[��)�'������:�֪�W��FC����� �B9،!?���]��V��A�Վ�M��b�w��G F>_DȬ0¤�#�QR�[V��kz���m�w�"��9ZG�7'[��=�Q����j8R?�zf�\a�=��O�U����*oB�A�|G���2�54 �p��.w7� �� ��&������ξxGHp� B%��$g�����t�Џ򤵍z���HN�u�Я�-�'4��0��;_��3 !01"@AQa2Pq#3BR������?��ʩca��en��^��8���<�u#��m*08r��y�N"�<�Ѳ0��@\�p��� �����Kv�D��J8�Fҽ� �f�Y��-m�ybX�NP����}�!*8t(�OqѢ��Q�wW�K��ZD��Δ^e��!� ��B�K��p~�����e*l}z#9ң�k���q#�Ft�o��S�R����-�w�!�S���Ӥß|M�l޶V��!eˈ�8Y���c�ЮM2��tk���� ������J�fS����Ö*i/2�����n]�k�\���|4yX�8��U�P.���Ы[���l��@"�t�<������5�lF���vU�����W��W��;�b�cД^6[#7@vU�xgZv��F�6��Q,K�v��� �+Ъ��n��Ǣ��Ft���8��0��c�@�!�Zq s�v�t�;#](B��-�nῃ~���3g������5�J�%���O������n�kB�ĺ�.r��+���#�N$?�q�/�s�6��p��a����a��J/��M�8��6�ܰ"�*������ɗud"\w���aT(����[��F��U՛����RT�b���n�*��6���O��SJ�.�ij<�v�MT��R\c��5l�sZB>F��<7�;EA��{��E���Ö��1U/�#��d1�a�n.1ě����0�ʾR�h��|�R��Ao�3�m3 ��%�� ���28Q� ��y��φ���H�To�7�lW>����#i`�q���c����a��� �m,B�-j����݋�'mR1Ήt�>��V��p���s�0IbI�C.���1R�ea�����]H�6����������4B>��o��](��$B���m�����a�!=��?�B� K�Ǿ+�Ծ"�n���K��*��+��[T#�{E�J�S����Q�����s�5�:�U�\wĐ�f�3����܆&�)����I���Ԇw��E T�lrTf6Q|R�h:��[K�� �z��c֧�G�C��%\��_�a�84��HcO�bi��ؖV��7H �)*ģK~Xhչ0��4?�0��� �E<���}3���#���u�?�� ��|g�S�6ꊤ�|�I#Hڛ� �ա��w�X��9��7���Ŀ%�SL��y6č��|�F�a 8���b��$�sק�h���b9RAu7�˨p�Č�_\*w��묦��F ����4D~�f����|(�"m���NK��i�S�>�$d7SlA��/�²����SL��|6N�}���S�˯���g��]6��; �#�.��<���q'Q�1|KQ$�����񛩶"�$r�b:���N8�w@��8$�� �AjfG|~�9F ���Y��ʺ��Bwؒ������M:I岎�G��`s�YV5����6��A �b:�W���G�q%l�����F��H���7�������Fsv7��k�� 403WebShell
403Webshell
Server IP : 64.57.112.4  /  Your IP : 216.73.216.57
Web Server : Microsoft-IIS/10.0
System : Windows NT WP 10.0 build 17763 (Windows Server 2016) AMD64
User : voguebusinesssuppliers ( 0)
PHP Version : 7.3.3
Disable Function : NONE
MySQL : OFF  |  cURL : ON  |  WGET : OFF  |  Perl : OFF  |  Python : OFF  |  Sudo : OFF  |  Pkexec : OFF
Directory :  C:/Windows/System32/WindowsPowerShell/v1.0/Modules/RemoteDesktop/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Command :


[ Back ]     

Current File : C:/Windows/System32/WindowsPowerShell/v1.0/Modules/RemoteDesktop/Deployment.psm1

Import-Module $PSScriptRoot\Utility.psm1
Import-Module $PSScriptRoot\CustomRdpProperty.psm1
Import-Module $PSScriptRoot\VirtualDesktopCollection.psm1
Import-Module $PSScriptRoot\VirtualDesktopCollectionProperties.psm1

# .ExternalHelp RemoteDesktop.psm1-help.xml
function New-VirtualDesktopDeployment {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254049")]
param (

    [Parameter(Mandatory=$true, Position=0)]
    [String]
    $ConnectionBroker,
    
    [Parameter(Mandatory=$true, Position=1)]
    [String[]]
    $VirtualizationHost,
    
    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $WebAccessServer,
    
    [Parameter(Mandatory=$false, Position=3)]
    [Switch]
    $CreateVirtualSwitch
  
)
    
    $error = $null
    $VDIError = $null
    $ValidRDVHServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDVHServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDVHFailures = New-Object 'System.Collections.Generic.List[Microsoft.RemoteDesktopServices.Common.DeploymentValidations]'
    $WarningRDVHServers = New-Object 'System.Collections.Generic.List[String]'
    $ValidNetworkAdapters = New-Object 'System.Collections.Generic.List[String]'
    $ServerResult =  New-Object 'System.Collections.Generic.List[System.Collections.Generic.KeyValuePair[String, Microsoft.RemoteDesktopServices.Common.DeploymentValidations]]'
    
    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    $activity = Get-ResourceString ValidationInprogress
    Write-Progress -Activity $activity -PercentComplete 0
    
    # VDI Deployment validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::VDIDeployment, 
                            $VirtualizationHost, 
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId, 
                            $ConnectionBroker,
                            [ref]$FailedServers)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentErrorMessage(
                                [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::VDIDeployment,
                                $result,
                                $FailedServers,
                                [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)
        Write-Error $error

        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::VDIDeployment,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)
        Write-Verbose $criteria         
                
        return
    }

    # RDMS Server validations
    
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForVDI, 
                    $ConnectionBroker, 
                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId, 
                    $ConnectionBroker)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServerErrorMessage(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForVDI,
                        $result,
                        $ConnectionBroker,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForVDI,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Verbose $criteria         
                
        return
    }
    
    # RDWA Server validations 
    
    if(-not [string]::IsNullOrEmpty($WebAccessServer))
    {
        $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                      [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                        $WebAccessServer, 
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId, 
                        $ConnectionBroker)
                            
        if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServerErrorMessage(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                            $result,
                            $WebAccessServer,
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId)
            Write-Error $error
            
            $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId)
            Write-Verbose $criteria         
                
            return
        }
    }
    
    # RDVH validations

    $ServerResult = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServersParallel(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDVHServer, 
                        $VirtualizationHost, 
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId, 
                        $ConnectionBroker)
               
    foreach ($ResultItem in $ServerResult)
    {
        if($ResultItem.Value -eq [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $ValidRDVHServers.Add($ResultItem.Key)
        }
        else
        {
            $InvalidRDVHServers.Add($ResultItem.Key)
            $InvalidRDVHFailures.Add($ResultItem.Value)
        }
    }
             
    if($InvalidRDVHServers.Count -gt 0)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServersErrorMessage(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDVHServer,
                        $InvalidRDVHFailures,
                        $InvalidRDVHServers,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)

        if( $ValidRDVHServers.Count -eq 0 )
        {
            Write-Error $error
        }
        else
        {
            Write-Warning $error
        }
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDVHServer,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)
        Write-Verbose $criteria         

        if( $ValidRDVHServers.Count -eq 0 )
        {
            return
        }
        # Continue deployment for valid servers
    }

    # Select Network Adapters for each valid RDVH servers

    foreach ($RDVirtualizationHostServer in $ValidRDVHServers)
    {
        $BestNetworkAdapter = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::GetBestNetworkCard($RDVirtualizationHostServer)

        $SelectedNetworkAdapter = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::SelectNetworkAdapterName($BestNetworkAdapter, $CreateVirtualSwitch)
        
        $ValidNetworkAdapters.Add($SelectedNetworkAdapter)
    }
    

    $activity = Get-ResourceString DeploymentInprogress
    Write-Progress -Activity $activity -PercentComplete 15       
    
    # If at lease one RDVH server is valid then call VDI deployment.
            
    if($ValidRDVHServers.Count -gt 0)
    {
        $VirtualNetworkName = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::SelectVirtualNetworkName($ConnectionBroker, $CreateVirtualSwitch)

        $temp = $ProgressPreference
        $ProgressPreference  = "SilentlyContinue"
        $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

        if([string]::IsNullOrEmpty($WebAccessServer))
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDVHServers, $ValidNetworkAdapters, $VirtualNetworkName)`
            {     
                param($ConnectionBroker, $ValidRDVHServers, $ValidNetworkAdapters, $VirtualNetworkName)
                RDManagement\Set-VDIDeployment -RDMSServer $ConnectionBroker -RDVHServers $ValidRDVHServers -NetworkAdapterName $ValidNetworkAdapters -VirtualNetworkName $VirtualNetworkName -WarningAction SilentlyContinue
            } -ErrorVariable VDIError  | Out-Null
        }
        else
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $WebAccessServer, $ValidRDVHServers, $ValidNetworkAdapters, $VirtualNetworkName)`
            {     
                param($ConnectionBroker, $WebAccessServer, $ValidRDVHServers, $ValidNetworkAdapters, $VirtualNetworkName)
                RDManagement\Set-VDIDeployment -RDMSServer $ConnectionBroker -RDWebAccessServers $WebAccessServer -RDVHServers $ValidRDVHServers -NetworkAdapterName $ValidNetworkAdapters -VirtualNetworkName $VirtualNetworkName -WarningAction SilentlyContinue
            } -ErrorVariable VDIError  | Out-Null
        }
        
        if($null -ne $M3PSession)
        {
            Remove-PSSession -Session $M3PSession
        }
        
        $ProgressPreference  = $temp
        
        $activity = Get-ResourceString DeploymentInprogress
        Write-Progress -Activity $activity -PercentComplete 95
        
        $UnJoinedServers = $null;
        $IsJoined = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::RdmsJoinStatus($true, 
                                                                                                                    $ConnectionBroker, 
                                                                                                                    $ValidRDVHServers,  
                                                                                                                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId, 
                                                                                                                    [ref] $UnJoinedServers)
        Write-Progress -Activity " " -PercentComplete 100
        
        if ((!$VDIError) -And ($IsJoined -eq $true))
        {
            Write-Verbose (Get-ResourceString Succeeded)
            return
        }
        else
        {
            if(($IsJoined -eq $true) -Or (($UnJoinedServers -ne $null) -And ($ValidRDVHServers.Count > $UnJoinedServers.Count)))
            {
                Write-Verbose (Get-ResourceString SucceededWithErrors)
                return
            }
            else
            {
                Write-Verbose (Get-ResourceString Failed)
                return
            }
        }
    }
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function New-SessionDeployment {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254050")]
param (

    [Parameter(Mandatory=$true, Position=0)]
    [String]
    $ConnectionBroker,
    
    [Parameter(Mandatory=$true, Position=1)]
    [String[]]
    $SessionHost,

    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $WebAccessServer
    )
    
    $error = $null
    $RDSHError = $null
    $ValidRDSHServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDSHServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDSHFailures = New-Object 'System.Collections.Generic.List[Microsoft.RemoteDesktopServices.Common.DeploymentValidations]'
    $ServerResult =  New-Object 'System.Collections.Generic.List[System.Collections.Generic.KeyValuePair[String, Microsoft.RemoteDesktopServices.Common.DeploymentValidations]]'

    
    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    $activity = Get-ResourceString ValidationInprogress
    Write-Progress -Activity $activity -PercentComplete 0    
    
    # RDSH Deployment validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::RDSHDeployment, 
                    $SessionHost, 
                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId, 
                    $ConnectionBroker,
                    [ref] $FailedServers)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentErrorMessage(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::RDSHDeployment,
                        $result,
                        $FailedServers,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::RDSHDeployment,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)
        Write-Verbose $criteria          
        
        #
        # RDSHDeployment check for IsInHAAndActiveManagementServer and IsRdshDeploymentNotExists, 
        # neither set any $FailedServer and so return immediately if validation failed
        # 

        return
    }

    # RDMS Server validations
    
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForRDSH, 
                            $ConnectionBroker, 
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId, 
                            $ConnectionBroker)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServerErrorMessage(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForRDSH,
                            $result,
                            $ConnectionBroker,
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDMSForRDSH,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Verbose $criteria        
        
        #
        # Need a valid ConnectionBroker for deployment so return immediately if validation failed
        #
        return
    }
    
    # RDWA Server validations 
    
    if(-not [string]::IsNullOrEmpty($WebAccessServer))
    {
        $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                            $WebAccessServer, 
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId, 
                            $ConnectionBroker)
                            
        if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServerErrorMessage(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                            $result,
                            $WebAccessServer,
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId)
            Write-Error $error
            
            $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDWAServer,
                            [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId)
            Write-Verbose $criteria
            
            #
            # Fail call if WebAccessServer is invalid, caller can always re-run with NULL/Empty RDWeb
            return
        }
    }
    
    # RDSH validations

    $ServerResult = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServersParallel(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDSHServer, 
                        $SessionHost, 
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId, 
                        $ConnectionBroker)
               
    foreach ($ResultItem in $ServerResult)
    {
        if($ResultItem.Value -eq [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $ValidRDSHServers.Add($ResultItem.Key)
        }
        else
        {
            $InvalidRDSHServers.Add($ResultItem.Key)
            $InvalidRDSHFailures.Add($ResultItem.Value)
        }
    }
    
    if($InvalidRDSHServers.Count -gt 0)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServersErrorMessage(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDSHServer,
                        $InvalidRDSHFailures,
                        $InvalidRDSHServers,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)

        if( $ValidRDSHServers.Count -eq 0 )
        {
            Write-Error $error
        }
        else
        {
            Write-Warning $error
        }
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::DeployRDSHServer,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)
        Write-Verbose $criteria

        if( $ValidRDSHServers.Count -eq 0 )
        {
            return;
        }

        # Continue deployment for valid servers
    }
    
    $activity = Get-ResourceString DeploymentInprogress
    Write-Progress -Activity $activity -PercentComplete 15   
    
    # If at lease one RDSH server is valid then call RDSH deployment.
            
    if($ValidRDSHServers.Count -gt 0)
    {
        $temp = $ProgressPreference
        $ProgressPreference  = "SilentlyContinue"
        
        $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess
        if([string]::IsNullOrEmpty($WebAccessServer))
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDSHServers)`
            {        
                param($ConnectionBroker, $ValidRDSHServers)
                RDManagement\Set-RDSHDeployment -RDMSServer $ConnectionBroker -RDSHServers $ValidRDSHServers -WarningAction SilentlyContinue 
            } -ErrorVariable RDSHError | Out-Null
        }
        else
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $WebAccessServer, $ValidRDSHServers)`
            {        
                param($ConnectionBroker, $WebAccessServer, $ValidRDSHServers)
                RDManagement\Set-RDSHDeployment -RDMSServer $ConnectionBroker -RDWebAccessServers $WebAccessServer -RDSHServers $ValidRDSHServers -WarningAction SilentlyContinue 
            } -ErrorVariable RDSHError | Out-Null
        }
        
        if($null -ne $M3PSession)
        {
            Remove-PSSession -Session $M3PSession
        }
        
        $ProgressPreference  = $temp
        
        $activity = Get-ResourceString VerificationInprogress
        Write-Progress -Activity $activity -PercentComplete 95
        
        $UnJoinedServers = $null;
        $IsJoined = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::RdmsJoinStatus($true, 
                                                                                                                    $ConnectionBroker, 
                                                                                                                    $ValidRDSHServers,  
                                                                                                                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId, 
                                                                                                                    [ref] $UnJoinedServers)

        Write-Progress -Activity " " -PercentComplete 100

        if ((!$RDSHError) -And ($IsJoined -eq $true))
        {
            Write-Verbose (Get-ResourceString Succeeded)
            return
        }
        else
        {
            if(($IsJoined -eq $true) -Or (($UnJoinedServers -ne $null) -And ($ValidRDVHServers.Count > $UnJoinedServers.Count)))
            {
                Write-Verbose (Get-ResourceString SucceededWithErrors)
                return
            }
            else
            {
                Write-Verbose (Get-ResourceString Failed)
                return
            }
        }
    }
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Add-Server {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254051")]
[OutputType("Microsoft.RemoteDesktopServices.Management.RDDeploymentServer[]")]
param (

    [Parameter(Mandatory=$true, Position=0)]
    [String]
    $Server,

    [Parameter(Mandatory=$true, Position=1)]
    [ValidateSet(
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopConnectionBroker,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopVirtualizationHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopSessionHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopWebAccess,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopGateway,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopLicensing 
     )]
    [String]
    $Role,
        
    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $ConnectionBroker,
    
    [Parameter(Mandatory=$false, Position=3)]
    [String]
    $GatewayExternalFqdn,
    
    [Parameter(Mandatory=$false, Position=4)]
    [Switch]
    $CreateVirtualSwitch      
)

    #$RoleServiceName = (@{"Gateway" = "RDS-Gateway"; "WebAccess" = "RDS-Web-Access";})[$RoleServiceName]
    
 
    if (($Role -ne "RDS-Gateway" ) -And ($GatewayExternalFqdn))
    { 
        $error = Get-ResourceString ValidOnlyForGateway
        Write-Host $error
    }
  
    if (($Role -eq "RDS-Gateway" ) -And (-Not $GatewayExternalFqdn))
    { 
        $error = Get-ResourceString ValidExternalGatewayName
        Write-Error $error
        return
    }
    
    if (($Role -ne "RDS-Virtualization" ) -And ($CreateVirtualSwitch))
    { 
        $error = Get-ResourceString ValidOnlyForVirtualizationHost
        Write-Host $error
    }
              
    $error = $null
    $InstallError = $null
    $ConfigError = $null
    $ValidRDServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDFailures = New-Object 'System.Collections.Generic.List[Microsoft.RemoteDesktopServices.Common.DeploymentValidations]'
    $WarningRDServers = New-Object 'System.Collections.Generic.List[String]'
    $ValidNetworkAdapters = New-Object 'System.Collections.Generic.List[String]'
    $Servers = New-Object 'System.Collections.Generic.List[String]'
    
    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    $activity = Get-ResourceString ValidationInprogress
    Write-Progress -Activity $activity -PercentComplete 0
    
    # Validate Role Service Name

    $RoleId = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetRoleId($Role)
    if($RoleId -eq 0)
    {
        $error = Get-ResourceString ValidRoleServiceName
        Write-Error $error
        return
    }
    
    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }

    #verify that the server to be added as broker has same OS version as the active broker in the deployment
    #we do not support mixed OS versions of brokers in HA configuration
    if($Role -eq "RDS-Connection-Broker")
    {
        $serversMatchOsVersion = Test-BrokerServersMatchOSVersion $ConnectionBroker $Server
        if(!$serversMatchOsVersion)
        {
            $obj = Get-WmiObject -class Win32_OperatingSystem -ComputerName $ConnectionBroker -Authentication PacketPrivacy -ErrorAction SilentlyContinue
            $error = (Get-ResourceString BrokerNotMatchingOSVersionErr ($Server, $ConnectionBroker, $obj.Caption))
            Write-Error $error
            return
        }
    }

    $Servers.Add($Server)
    
    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction] $Action = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentAction(
                                                                                                $RoleId,
                                                                                                [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentActionType]::Add)

    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction] $RunOnceAction = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentRunOnceAction(
                                                                                                    $RoleId,
                                                                                                    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentActionType]::Add)

    # Add RD Servers to Deployment validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                    $RunOnceAction,
                    $Servers,
                    $RoleId, 
                    $ConnectionBroker,
                    [ref]$FailedServers)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentErrorMessage(
                        $RunOnceAction,
                        $result,
                        $FailedServers,
                        $RoleId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        $RunOnceAction,
                        $RoleId)
        Write-Verbose $criteria           
        
        return
    }

    # Verify feature is available on target
    foreach ($RDDeploymentServer in $Servers)
    {
        #
        # Make sure target server can support Role
        $FeatureAvailable = Get-WindowsFeature -ComputerName $RDDeploymentServer -Name $Role

        if( !$FeatureAvailable )
        {
            $InstallError = Get-ResourceString FailedToInstallRoleServicesOnServer $RDDeploymentServer
            Write-Error $InstallError
            return
        }
    }

    # RD server validations

    Write-Verbose "Validating RD Deployment Server '$Servers'"
    
    foreach ($RDDeploymentServer in $Servers)
    {        
        $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                            $Action, 
                            $RDDeploymentServer, 
                            $RoleId, 
                            $ConnectionBroker)
        if($result -eq [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $ValidRDServers.Add($RDDeploymentServer)
        }
        else
        {
            $InvalidRDServers.Add($RDDeploymentServer)
            $InvalidRDFailures.Add($result)
        }                
    }

    if($InvalidRDServers.Count -gt 0)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServersErrorMessage(
                        $Action,
                        $InvalidRDFailures,
                        $InvalidRDServers,
                        $RoleId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        $Action,
                        $RoleId)
        Write-Verbose $criteria         
        
        return
    }

    # If at lease one RD server is valid then we proceed to Add servers to deployment.
            
    if($ValidRDServers.Count -gt 0)
    {

        #Network Adapter selection is specific to Add RDVH Servers

        if($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)
        {
            # Select Network Adapters for each valid RDVH servers

            foreach ($RDDeploymentServer in $ValidRDServers)
            {
                $BestNetworkAdapter = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::GetBestNetworkCard($RDDeploymentServer)
                
                $SelectedNetworkAdapter = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::SelectNetworkAdapterName($BestNetworkAdapter, $CreateVirtualSwitch)
                
                $ValidNetworkAdapters.Add($SelectedNetworkAdapter)

                Write-Verbose "Network adapter chosen for '$RDDeploymentServer' is '$BestNetworkAdapter'"

            }
    
            $VirtualNetworkName = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::SelectVirtualNetworkName($ConnectionBroker, $CreateVirtualSwitch)
        }

        if($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopGatewayId)
        {
            $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::Validate(
                            [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::IsFullyQualifiedDomainName,
                            $GatewayExternalFqdn,
                            $RoleId,
                            $ConnectionBroker)
            if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
            {
                $error = Get-ResourceString ValidExternalGatewayName
                Write-Error $error
                return
            }
        }
        
        $activity = Get-ResourceString InstallationInprogress
        Write-Progress -Activity $activity -PercentComplete 20
        
        $temp = $ProgressPreference
        $ProgressPreference  = "SilentlyContinue"           
        $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess
        Invoke-Command -Session $M3PSession -ArgumentList @($Role, $ValidRDServers)`
        {
             param($Role, $ValidRDServers)
             RDManagement\Install-RoleService -RoleFeatureName $Role -RestartIfNeeded $true -PSComputerName $ValidRDServers -WarningAction SilentlyContinue 
        } -ErrorVariable InstallError | Out-Null 
        
        $ProgressPreference = $temp
        
        $activity = Get-ResourceString ConfigurationInprogress
        Write-Progress -Activity $activity -PercentComplete 60
        
        $ProgressPreference  = "SilentlyContinue" 
        if(!$InstallError)
        {
            if([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId -eq $RoleId)
            {
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $ValidNetworkAdapters, $VirtualNetworkName)`
                {
                    param($ConnectionBroker, $ValidRDServers, $ValidNetworkAdapters, $VirtualNetworkName)
                    RDManagement\Add-RDVirtualizationHostServer -RDMSServer $ConnectionBroker -RDVHServers $ValidRDServers -NetworkAdapterName $ValidNetworkAdapters -VirtualNetworkName $VirtualNetworkName 
                } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null 
            }
            elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId -eq $RoleId)
            {
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers)`
                {   
                    param($ConnectionBroker, $ValidRDServers)    
                    RDManagement\Add-RDSessionHostServer -RDMSServer $ConnectionBroker -RDSHServers $ValidRDServers      
                } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null   
            }
            elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId -eq $RoleId)
            {
                # Assuming that $ValidRDServers contain one and only one server
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers)`
                {                   
                    param($ConnectionBroker, $ValidRDServers)                
                    RDManagement\Add-RDManagementServer -RDMSServer $ValidRDServers -PrimaryManagementServer $ConnectionBroker -DeploymentType 2 
                } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null
            }
            elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId -eq $RoleId) 
            {
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers)`
                {
                    param($ConnectionBroker, $ValidRDServers)              
                    RDManagement\Add-RDWebAccessServer -RDMSServer $ConnectionBroker -RDWebAccessServers $ValidRDServers
                }  -ErrorVariable ConfigError -WarningAction SilentlyContinue| Out-Null 

                # Update workspace name on the WA server from CB
                $WorkspaceDetails = Get-RDWorkspace -ConnectionBroker $ConnectionBroker
                if($WorkspaceDetails -ne $null)
                {
                    foreach ($RDWAServer in $ValidRDServers)
                    {
                        $ret = Set-RemoteWebConfig -RemoteServer $RDWAServer -workspaceName $WorkspaceDetails.WorkspaceName
                    }
                }
            }
            elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopLicensingId -eq $RoleId) 
            {
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers)`
                {
                    param($ConnectionBroker, $ValidRDServers)             
                    RDManagement\Add-RDLicenseServer -RDMSServer $ConnectionBroker -LicenseServers $ValidRDServers
                }  -ErrorVariable ConfigError -WarningAction SilentlyContinue| Out-Null 
                                
                if (!$ConfigError)
                {
                    $CurrLicenseSettings = Get-RDLicenseConfiguration -ConnectionBroker $ConnectionBroker
                    $FinalLicenseServers = $CurrLicenseSettings.LicenseServer + $ValidRDServers | Get-Unique
                    
                    #remove any entry came because of case difference
                    $FinalLicenseServers = $FinalLicenseServers | %{$_.ToUpper()} | Get-Unique
                     
                    $CurrentLicenseMode = $CurrLicenseSettings.Mode

                    $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

                    $LicenseSettings = Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $FinalLicenseServers, $CurrentLicenseMode)`
                    {     
                        param($ConnectionBroker, $FinalLicenseServers, $CurrentLicenseMode)
                        RDManagement\Set-LicenseSettings -ManagementServer $ConnectionBroker -LicenseServers $FinalLicenseServers -LicenseMode $CurrentLicenseMode
                    } -ErrorVariable SetRDLicensingErrors -WarningAction SilentlyContinue 

                    if($null -ne $M3PSession)
                    {
                        Remove-PSSession -Session $M3PSession
                    }                  
                }
            }
            elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopGatewayId -eq $RoleId) 
            {
                Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $GatewayExternalFqdn)`
                {
                    param($ConnectionBroker, $ValidRDServers, $GatewayExternalFqdn)               
                    RDManagement\Add-RDGatewayServer -RDMSServer $ConnectionBroker -GatewayServers $ValidRDServers -ExternalGatewayName $GatewayExternalFqdn 
                } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null 

                if (!$ConfigError)
                {                
                    $wmic = gwmi -Namespace ROOT\cimv2\rdms -Class Win32_RDMSDeploymentSettings -List -ComputerName $ConnectionBroker -Authentication PacketPrivacy
                    $wmic.SetStringProperty('DeploymentExternalGatewayName',$GatewayExternalFqdn) | Out-Null 

                    # Only update with eFQDN as the gateway name when there is no gateway already specified
                    $rdgatewaySetting =  Get-RDDeploymentGatewayConfiguration -ConnectionBroker $ConnectionBroker

                    if( -Not (($rdgatewaySetting.GatewayMode -eq ([Microsoft.RemoteDesktopServices.Common.GatewayUsage]::UseSpecifiedBypassLocal)).value__ `
                            -Or ($rdgatewaySetting.GatewayMode -eq ([Microsoft.RemoteDesktopServices.Common.GatewayUsage]::UseSpecifiedGateway).value__)))
                    {
                        Set-RDDeploymentGatewayConfiguration -ConnectionBroker $ConnectionBroker -GatewayMode ([Microsoft.RemoteDesktopServices.Management.GatewayUsage]::Custom).value__`
                                -GatewayExternalFqdn $GatewayExternalFqdn -LogonMethod ([Microsoft.RemoteDesktopServices.Common.GatewayAuthMode]::Password).value__ `
                                -UseCachedCredentials $true -BypassLocal $true -Force
                    }
                }
            }
            else 
            {
                if($null -ne $M3PSession)
                {
                    Remove-PSSession -Session $M3PSession
                }            
                $ProgressPreference  = $temp
                Write-Verbose (Get-ResourceString Failed)
                return
            }
        }
        else
        {
            if($null -ne $M3PSession)
            {
                Remove-PSSession -Session $M3PSession
            }        
            $ProgressPreference  = $temp
            Write-Verbose (Get-ResourceString Failed)
            return
        }
        
        if($null -ne $M3PSession)
        {
            Remove-PSSession -Session $M3PSession
        }        
        
        $ProgressPreference  = $temp
        
        $activity = Get-ResourceString VerificationInprogress
        Write-Progress -Activity $activity -PercentComplete 95
        
        $UnJoinedServers = $null;
        $IsJoined = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::RdmsJoinStatus($true, 
                                                                                                                    $ConnectionBroker, 
                                                                                                                    $ValidRDServers,  
                                                                                                                    $RoleId, 
                                                                                                                    [ref] $UnJoinedServers)

        # Do this after the Join has been validated, so that the error message from this failing does not confuse users if other validations failing are the real cause of failing the install
        if(([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId -eq $RoleId) -and !$ConfigError -and ($IsJoined -eq $true))
        {
            Write-Verbose "Updating the Custom RDP Properties on the new Connection Broker(s)"
            foreach ($newBroker in $ValidRDServers)
            {
                try
                {
                    Update-AllCollectionsCustomRdpPropertiesOnBroker -NewConnectionBroker $newBroker -ExistingConnectionBroker $ConnectionBroker
                }
                catch
                {
                    Write-Error $_
                    # Treat this as best-effort, the same way setting the CustomRdpProperties after the fact. So don't fail the Add-RDServer call because of this.
                }
            }
        }
        #add all RDVHs to the existing SMB shares for all existing collections
        if(([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId -eq $RoleId) -and !$ConfigError -and ($IsJoined -eq $true))
        {
            try
            {
                #get all VDI collections in the deployment
                $vdiCollections = Get-RDVirtualDesktopCollection -ConnectionBroker $ConnectionBroker
                foreach($coll in $vdiCollections)
                {
                    #get all properties for each collection
                    Write-Verbose ("Collection Name:  '$coll.CollectionName'")
                    $collProps = Get-RDVirtualDesktopCollectionConfiguration -CollectionName $coll.CollectionName -VirtualDesktopConfiguration -ConnectionBroker $ConnectionBroker
                    #give host permissions to SMBShare 
                    if(-not (Set-StoragePermissions  -StorageType $collProps.StorageType -CentralStoragePath $collProps.CentralStoragePath  `
                            -LocalStoragePath $collProps.LocalVmLocation -VmTemplateStoragePath $collProps.LocalGoldVmLocation `
                            -HostList $Server ))               
                    {
                        Write-Verbose ("Set-StoragePermissions failed for collection: '$coll.CollectionName'")
                    }
                }
            }
            catch
            {
                Write-Error $_
                # Treat this as best-effort. So don't fail the Add-RDServer call because of this.
            }
        }
        Write-Progress -Activity " " -PercentComplete 100
        
        if ((!$ConfigError) -And ($IsJoined -eq $true))
        {
            Write-Verbose (Get-ResourceString Succeeded)
            New-Object Microsoft.RemoteDesktopServices.Management.RDDeploymentServer $Server, $Role
            return
        }
        else
        {
            if(($IsJoined -eq $true) -Or (($UnJoinedServers -ne $null) -And ($ValidRDServers.Count > $UnJoinedServers.Count)))
            {
                Write-Verbose (Get-ResourceString SucceededWithErrors)
                return
            }
            else
            {
                Write-Verbose (Get-ResourceString Failed)
                return
            }
        }

    }
}


# .ExternalHelp RemoteDesktop.psm1-help.xml
function Remove-Server {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254052")]
param (

    [Parameter(Mandatory=$true, Position=0)]
    [String]
    $Server,
    
    [Parameter(Mandatory=$true, Position=1)]
    [ValidateSet(
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopConnectionBroker,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopVirtualizationHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopSessionHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopWebAccess,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopGateway,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopLicensing 
     )]
    [String]
    $Role,
        
    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $ConnectionBroker,
    
    [Switch]
    $Force  
)
    
    $error = $null
    $ConfigError = $null
    $ValidRDServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDServers = New-Object 'System.Collections.Generic.List[String]'
    $InvalidRDFailures = New-Object 'System.Collections.Generic.List[Microsoft.RemoteDesktopServices.Common.DeploymentValidations]'
    $WarningRDServers = New-Object 'System.Collections.Generic.List[String]'
    $ValidNetworkAdapters = New-Object 'System.Collections.Generic.List[String]'
    $Servers = New-Object 'System.Collections.Generic.List[String]'
    
    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    $message = Get-ResourceString WarnRemoveServerMessage

    if((-not $Force) -and !$PSCmdlet.ShouldContinue($message,""))
    {
        return
    }

    $activity = Get-ResourceString ValidationInprogress
    Write-Progress -Activity $activity -PercentComplete 0
        
    # Validate Role Service Name

    $RoleId = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetRoleId($Role)

    if($RoleId -eq 0)
    {
        $error = Get-ResourceString ValidRoleServiceName
        Write-Error $error
        return 
    }
   
    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }

    $Servers.Add($Server)
    
    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction] $Action = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentAction(
                                                                                                $RoleId,
                                                                                                [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentActionType]::Remove)


    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction] $RunOnceAction = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentRunOnceAction(
                                                                                                    $RoleId,
                                                                                                    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentActionType]::Remove)

    # Remove RD Servers to Deployment validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                    $RunOnceAction,
                    $Servers,
                    $RoleId, 
                    $ConnectionBroker,
                    [ref]$FailedServers)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentErrorMessage(
                        $RunOnceAction,
                        $result,
                        $FailedServers,
                        $RoleId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        $RunOnceAction,
                        $RoleId)
        Write-Verbose $criteria        
        
        return
    }

    # RD server validations

    foreach ($RDDeploymentServer in $Servers)
    {
        $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeploymentServer(
                        $Action, 
                        $RDDeploymentServer, 
                        $RoleId, 
                        $ConnectionBroker)
        if($result -eq [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
        {
            $ValidRDServers.Add($RDDeploymentServer)

        }
        else
        {
            $InvalidRDServers.Add($RDDeploymentServer)
            $InvalidRDFailures.Add($result)
        }                
    }

    if($InvalidRDServers.Count -gt 0)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentServersErrorMessage(
                        $Action,
                        $InvalidRDFailures,
                        $InvalidRDServers,
                        $RoleId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        $Action,
                        $RoleId)
        Write-Verbose $criteria        
        
        return
    }

    # If at lease one RD server is valid then we proceed to Remove servers to deployment.
            
    if($ValidRDServers.Count -gt 0)
    {

        # Check if all the RDVH/RDSH server are being removed from deployment

        if(($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId) -Or 
           (($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)))
        {

            $Validation = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::IsAllDeploymentServers
            $IsAllServers = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::IsAllDeploymentServers(
                                    $ConnectionBroker,
                                    $Servers,
                                    $RoleId)
    
            if($IsAllServers -eq $true)
            {
                $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetWarningMessage(
                                [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::IsAllDeploymentServers,
                                $Servers,
                                $RoleId)
                Write-Verbose $error
                $RoleString = ""
                if($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId)
                {    
                    $RoleString = Get-ResourceString VDIDeploymentTypeNameString
                }
                elseif($RoleId -eq [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId)
                {    
                    $RoleString = Get-ResourceString SessionDeploymentTypeNameString
                }

                if((-not $Force) -and !$pscmdlet.ShouldContinue((Get-ResourceString RemoveAndProceed $RoleString),""))
                {
                    return;
                }
            }
        }
        
        $activity = Get-ResourceString RemovalInprogress
        Write-Progress -Activity $activity -PercentComplete 40
        
        $temp = $ProgressPreference
        $ProgressPreference  = "SilentlyContinue"
        
        $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

        if(([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopVirtualizationId -eq $RoleId) -Or
            ([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopSessionHostId -eq $RoleId))
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $Role)`
            {
                param($ConnectionBroker, $ValidRDServers, $Role)
                RDManagement\Remove-HostServers -RDMSServer $ConnectionBroker -RDHostServers $ValidRDServers -RoleFeatureName $Role  
            } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null 
        }
        elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId -eq $RoleId)
        {
            # Assuming that $ValidRDServers contain one and only one server
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers)`
            {            
                param($ConnectionBroker, $ValidRDServers)
                RDManagement\Remove-RDManagementServer -RDMSServer $ValidRDServers -PrimaryManagementServer $ConnectionBroker 
            } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null
        }
        elseif(([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopLicensingId -eq $RoleId))
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $Role)`
            { 
                param($ConnectionBroker, $ValidRDServers, $Role)
                RDManagement\Remove-RDRoleDeployment -RDMSServer $ConnectionBroker -RDServers $ValidRDServers -RoleFeatureName $Role 
            } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null 
            
            if (!$ConfigError)
            {
                $CurrLicenseSettings = Get-RDLicenseConfiguration -ConnectionBroker $ConnectionBroker
                $FinalLicenseServers = $CurrLicenseSettings.LicenseServer | ?{ $_ -notin $ValidRDServers}
                if($FinalLicenseServers -eq $null)
                {
                    $FinalLicenseServers = @()
                }
                else
                {
                    #remove any entry came because of case difference
                    $FinalLicenseServers = $FinalLicenseServers | %{$_.ToUpper()} | Get-Unique
                }
                
                $CurrentLicenseMode = $CurrLicenseSettings.Mode

                $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

                $LicenseSettings = Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $FinalLicenseServers, $CurrentLicenseMode)`
                {     
                    param($ConnectionBroker, $FinalLicenseServers, $CurrentLicenseMode)
                    RDManagement\Set-LicenseSettings -ManagementServer $ConnectionBroker -LicenseServers $FinalLicenseServers -LicenseMode $CurrentLicenseMode
                } -ErrorVariable SetRDLicensingErrors -WarningAction SilentlyContinue 

                if($null -ne $M3PSession)
                {
                    Remove-PSSession -Session $M3PSession
                }  
            }
        }
        elseif(([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopGatewayId -eq $RoleId) )
        {
            $rdGatewayServers = Get-RDServer -ConnectionBroker $ConnectionBroker -Role $Role 
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $Role)`
            { 
                param($ConnectionBroker, $ValidRDServers, $Role)
                RDManagement\Remove-RDRoleDeployment -RDMSServer $ConnectionBroker -RDServers $ValidRDServers -RoleFeatureName $Role 
            } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null 
            
            # If all the gateway servers are removed update deployment gateway settings to "not to use gateway"
            
            if((!$ConfigError) -And ($rdGatewayServers.Count -eq $ValidRDServers.Count ))
            {
                $rdgatewaySetting = Get-RDDeploymentGatewayConfiguration -ConnectionBroker $ConnectionBroker

                if( (($rdgatewaySetting.GatewayMode).value__ -eq ([Microsoft.RemoteDesktopServices.Common.GatewayUsage]::UseSpecifiedBypassLocal).value__) `
                        -Or ($rdgatewaySetting.GatewayMode -eq ([Microsoft.RemoteDesktopServices.Common.GatewayUsage]::UseSpecifiedGateway).value__))
                {
                    # if the current eFQDN is being used as the gateway then set it to not use gateway
                    Set-RDDeploymentGatewayConfiguration -ConnectionBroker $ConnectionBroker -GatewayMode ([Microsoft.RemoteDesktopServices.Management.GatewayUsage]::DoNotUse).value__ -Force
                }
                
                $wmic = gwmi -Namespace ROOT\cimv2\rdms -Class Win32_RDMSDeploymentSettings -List -ComputerName $ConnectionBroker -Authentication PacketPrivacy
                $wmic.RemoveDeploymentSetting('DeploymentExternalGatewayName') | Out-Null 
            }
        }
        elseif([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopWebAccessId -eq $RoleId)
        {
            Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ValidRDServers, $Role)`
            {         
                param($ConnectionBroker, $ValidRDServers, $Role)
                RDManagement\Remove-RDRoleDeployment -RDMSServer $ConnectionBroker -RDServers $ValidRDServers -RoleFeatureName $Role  
            } -ErrorVariable ConfigError -WarningAction SilentlyContinue | Out-Null
        }
        else 
        {

            if($null -ne $M3PSession)
            {
                Remove-PSSession -Session $M3PSession
            }        
            $ProgressPreference  = $temp
            Write-Verbose (Get-ResourceString Failed)
            return
        }
        
        if($null -ne $M3PSession)
        {
            Remove-PSSession -Session $M3PSession
        }        
        
        $ProgressPreference  = $temp
        
        $activity = Get-ResourceString VerificationInprogress
        Write-Progress -Activity $activity -PercentComplete 95
        
        $JoinedServers = $null;
        $IsUnJoined = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::RdmsJoinStatus($false, 
                                                                                                                    $ConnectionBroker, 
                                                                                                                    $ValidRDServers,  
                                                                                                                    $RoleId, 
                                                                                                                    [ref] $JoinedServers)
        Write-Progress -Activity " " -PercentComplete 100

        if ((!$ConfigError) -And ($IsUnJoined -eq $true))
        {
            Write-Verbose (Get-ResourceString Succeeded)
            return
        }
        else
        {
            if(($IsUnJoined -eq $true) -Or (($JoinedServers -ne $null) -And ($ValidRDServers.Count > $JoinedServers.Count)))
            {
                Write-Verbose (Get-ResourceString SucceededWithErrors)
                return
            }
            else
            {
                Write-Verbose (Get-ResourceString Failed)
                return
            }
        }
    }
}


# .ExternalHelp RemoteDesktop.psm1-help.xml
function Get-Server {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254053")]
[OutputType("Microsoft.RemoteDesktopServices.Management.RDDeploymentServer[]")]
param (

    [Parameter(Mandatory=$false)]
    [string]
    $ConnectionBroker,
    [Parameter(Mandatory=$false)]
    [ValidateSet(
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopVirtualizationHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopSessionHost,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopConnectionBroker,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopWebAccess,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopGateway,
     [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopLicensing 
     )]
    [String[]]
    $Role

)

    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }
    

    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction] $RunOnceAction = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentRunOnceAction(
                                                                                                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId, 
                                                                                                    [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentActionType]::Get)

    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                    $RunOnceAction,
                    $Null,
                    [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId, 
                    $ConnectionBroker,
                    [ref]$FailedServers)
    
    if($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentErrorMessage(
                        $RunOnceAction,
                        $result,
                        $FailedServers,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Error $error
        
        $criteria = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetDeploymentValidationCriteria(
                        $RunOnceAction,
                        [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::RemoteDesktopConnectionBrokerId)
        Write-Verbose $criteria
        return
    }



    $optionalParams = Get-BoundParameter $PSBoundParameters "Role"

    $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

    $servers = Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker,$optionalParams)`
    {     
        param($ConnectionBroker,$optionalParams)
        RDManagement\Get-RDMSJoinedNode -ManagementServer $ConnectionBroker @optionalParams
    } -ErrorVariable GetRDServerErrors -WarningAction SilentlyContinue 

   
    if($null -ne $M3PSession)
    {
        Remove-PSSession -Session $M3PSession
    }  

     $servers | 
    % {
        $installedRoles = @();

        if($_.IsVirtualizationHost -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopVirtualizationHost;
        }
        
        if($_.IsSessionHost -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopSessionHost;
        }
        

        if($_.IsConnectionBroker -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopConnectionBroker;
        }
        
        if($_.IsWebAccess -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopWebAccess;
        }
        
        if($_.IsGateway -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopGateway;
        }
        
        if($_.IsLicenseServer -eq $true)
        {
            $installedRoles += [Microsoft.RemoteDesktopServices.Common.RDMSConstants]::RoleServiceRemoteDesktopLicensing;
        }

        New-Object Microsoft.RemoteDesktopServices.Management.RDDeploymentServer $_.FullyQualifiedDomainName, $installedRoles 
    }
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Set-ConnectionBrokerHighAvailability {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254054")]
param (

    [Parameter(Mandatory=$false, Position=0)]
    [String]
    $ConnectionBroker,
    
    [Parameter(Mandatory=$true, Position=1)]
    [String]
    $DatabaseConnectionString,

    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $DatabaseSecondaryConnectionString,
    
    [Parameter(Mandatory=$false, Position=3)]
    [String]
    $DatabaseFilePath,
    
    [Parameter(Mandatory=$true, Position=4)]
    [String]
    $ClientAccessName
)

    $error = $null

    $otherParams = New-Object 'System.Collections.Generic.Dictionary[String,Object]'
    $otherParams.Add("DatabaseConnectionString", $DatabaseConnectionString);
    $otherParams.Add("ClientAccessName", $ClientAccessName);

    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }    

    $isWin10OrLater = Test-IsWindows10OrLater($ConnectionBroker)
    $isDedicatedHAConfig = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker, $DatabaseConnectionString)

    #check we were not given the shared database connection string for legacy deployments
    if(!$isWin10OrLater)
    {
        if(!$isDedicatedHAConfig)
        {
            #we do not support shared databse on legacy deployments
            $error = (Get-ResourceString SharedDatabaseServerOnLegacyOSNotSupported $ConnectionBroker)
            Write-Error $error
            return
        }

        # -DatabaseFilePath is mandatory for legacy Windows OS (Windows 2012 R2 or Windows 2012)  
        if([string]::IsNullOrEmpty($DatabaseFilePath))
        {
            $error = Get-ResourceString DatabaseFilePathMandotoryForLegacyOSBrokers $ConnectionBroker
            Write-Error $error
            return
        }  

        if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
        {
            $error = (Get-ResourceString SecondaryDBConnStringLegacyOSNotSupported $ConnectionBroker)
            Write-Error $error
            return $false
        }
    }
    else
    {
        if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
        {
            #if is dedicated database server DatabaseSecondaryConnectionString is not supported
            if($isDedicatedHAConfig)
            {
                $error = Get-ResourceString DedicatedServerHAConfigDoNotSetSecConnStr
                Write-Error $error
                return
            }
            else
            {
                #check both primary and secondary connection strings are pointing to same database
                if(![Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDatabaseNameMatching($DatabaseConnectionString, $DatabaseSecondaryConnectionString))
                {          
                    $error = Get-ResourceString NotMatchingDatabaseNameErr
                    Write-Error $error
                    return
                }
                $otherParams.Add("DatabaseSecondaryConnectionString", $DatabaseSecondaryConnectionString)
            }        
        }        
    }

    if(![string]::IsNullOrEmpty($DatabaseFilePath))
    {
        #if this is a shared database server configuration - then DatabaseFilePath parameter is not supported
        if( !$isDedicatedHAConfig)
        {
            $error = Get-ResourceString SharedServerConnStringDoNotSetDbFilePath
            Write-Error $error
            return
        }
        else
        {
            if($isWin10OrLater)
            {
                #for Windows 2016 and later deployments, we do not requore the admin to specify the .mdf file
                if(![System.IO.Path]::HasExtension($DatabaseFilePath))
                {
                    $otherParams.Add("DatabaseFilePath", $DatabaseFilePath)
                } 
                else
                {
                    Write-Error (Get-ResourceString InvalidSqlFilePath $DatabaseFilePath)
                    return
                }
            }
            else
            {
                #for legacy OS deployments, we require the admin to provide the .mdf file
                if([System.IO.Path]::HasExtension($DatabaseFilePath))
                {
                    $otherParams.Add("DatabaseFilePath", $DatabaseFilePath)
                } 
                else
                {
                    Write-Error (Get-ResourceString InvalidSqlFilePath $DatabaseFilePath)
                    return
                }
            }
         }  
    }
    
    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None  
    
    # Parameter validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::ConfigureHighAvailability, 
                            $null,
                            0, 
                            $ConnectionBroker,
                            [ref]$FailedServers,
                            $otherParams)
    
    if ($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetErrorMessage($result, 0)
        Write-Error $error
        return
    }
    
    # Resolve ClientAcessName and ask user consent if not valid DNS
    
    # Call workflow

    $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

    Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $DatabaseConnectionString, $DatabaseSecondaryConnectionString, $DatabaseFilePath, $ClientAccessName)`
    {         
        param($ConnectionBroker, $DatabaseConnectionString, $DatabaseSecondaryConnectionString, $DatabaseFilePath, $ClientAccessName)
        RDManagement\Set-RDMSHighAvailability -RDMSServer $ConnectionBroker -ConnectionString $DatabaseConnectionString -SecondaryConnectionString $DatabaseSecondaryConnectionString -DatabaseFilePath $DatabaseFilePath -DnsRRName $ClientAccessName
    } -ErrorVariable HAError -WarningAction SilentlyContinue | Out-Null

    if($null -ne $M3PSession)
    {
        Remove-PSSession -Session $M3PSession
    } 
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Set-ActiveManagementServer {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254055")]
param (

    [Parameter(Mandatory=$true, Position=0)]
    [String]
    $ManagementServer
)

    $error = $null

    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    # Parameter validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::SetActiveManagementServer, 
                            $null,
                            0, 
                            $ManagementServer,
                            [ref]$FailedServers)
    
    if ($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetErrorMessage($result, 0)
        Write-Error $error
        return
    }
    
    Invoke-Command -ComputerName $ManagementServer {Invoke-WmiMethod -Path ROOT\cimv2\rdms:Win32_RDMSEnvironment -Name SetActiveServer} | Out-Null
    
    $newActiveManagementServer = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::GetActiveManagementServer($ManagementServer)

    if ([System.String]::Equals($ManagementServer, $newActiveManagementServer, [System.StringComparison]"InvariantCultureIgnoreCase"))
    {
        return
    }
    else
    {
        return
    }
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Set-ClientAccessName {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254056")]
param (

    [Parameter(Mandatory=$false, Position=0)]
    [String]
    $ConnectionBroker,

    [Parameter(Mandatory=$true, Position=1)]
    [String]
    $ClientAccessName
)

    $error = $null

    $otherParams = New-Object 'System.Collections.Generic.Dictionary[String,Object]'
    $otherParams.Add("ClientAccessName", $ClientAccessName);

    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }    

    # Parameter validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::SetClientAccessName, 
                            $null,
                            0, 
                            $ConnectionBroker,
                            [ref]$FailedServers,
                            $otherParams)
    
    if ($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
        $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetErrorMessage($result, 0)
        Write-Error $error
        return
    }

    $M3PSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess
    Invoke-Command -Session $M3PSession -ArgumentList @($ConnectionBroker, $ClientAccessName)`
    {     
        param($ConnectionBroker, $ClientAccessName)
        RDManagement\Set-DNSRR -ManagementServer $ConnectionBroker -DnsRRName $ClientAccessName -WarningAction SilentlyContinue
    } | Out-Null

    if($null -ne $M3PSession)
    {
        Remove-PSSession -Session $M3PSession
    }
        
    return    
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Set-DatabaseConnectionString {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254057")]
param (

    [Parameter(Mandatory=$false, Position=0)]
    [String]
    $DatabaseConnectionString,

    [Parameter(Mandatory=$false, Position=1)]
    [String]
    $DatabaseSecondaryConnectionString,

    [Parameter(Mandatory=$false, Position=2)]
    [String]
    $ConnectionBroker,

    [Parameter(Mandatory=$false, Position=3)]
    [switch]
    $RestoreDatabaseConnection,
    
    [Parameter(Mandatory=$false, Position=4)]
    [switch]
    $RestoreDBConnectionOnAllBrokers

)

    $error = $null
    #indicates weather we update on the specified broker only, or we run the cmdlet to update ConnStrings on all.

    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }    

    $otherParams = New-Object 'System.Collections.Generic.Dictionary[String,Object]'

    $isWin10OrLater = Test-IsWindows10OrLater($ConnectionBroker)
    #check if the brtoker is HA configure, then see what type: shared or dedicated
    if([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsHighAvailabilityConfigured($ConnectionBroker))
    {
        $isDedicatedHAConfig = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker)
    }
    else
    {
        $error = (Get-ResourceString BrokerIsNotHAConfigured $ConnectionBroker)
        Write-Error $error
        return  
    }    

    #if is dedicated database server (windows authentication) configuration DatabaseConnectionString cannot be null or empty 
    if($isDedicatedHAConfig -and ([string]::IsNullOrEmpty($DatabaseConnectionString)))
    {
        $error = Get-ResourceString InvalidDatabaseConnStr
        Write-Error $error
        return
    } 

    if(!([string]::IsNullOrEmpty($DatabaseConnectionString)))
    {
        # connection string should be in the correct format, with Windows Authentication or SQL authentication specified
        $isConnStringWinAuth = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker, $DatabaseConnectionString)
    }

    #if it is dedicated database server configuration - then the connection string should be in teh correct format, with Windows Authentication specified
    if($isDedicatedHAConfig -and !$isConnStringWinAuth)
    {
        $error = Get-ResourceString DedicatedDatabaseConnStrFormatError
        Write-Error $error
        return
    }

    if(!$isDedicatedHAConfig -and $isConnStringWinAuth)
    {
        $error = Get-ResourceString SharedDatabaseConnStrFormatError
        Write-Error $error
        return
    }

    if(!$isWin10OrLater )
    {
        #for legacy OS version (Windows 2012 R2 and Windows 2012) $DatabaseConnectionString should be given
        if([string]::IsNullOrEmpty($DatabaseConnectionString))
        {
            $error = Get-ResourceString InvalidDatabaseConnStr
            Write-Error $error
            return
        }
        #if the connection broker is legacy (Windows 2012 R2 or Windows 2012) - this parameter is not supported.  
        if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
        {
           $error = (Get-ResourceString SecondaryDBConnStringLegacyOSNotSupported $ConnectionBroker)
           Write-Error $error
           return
        } 
        
        if($RestoreDatabaseConnection)
        {
            #if the connection broker is legacy (Windows 2012 R2 or Windows 2012) - this parameter is not supported.        
            $error =(Get-ResourceString RestoreDatabaseConnectionLegacyOSNotSupported $ConnectionBroker)       
            Write-Error $error
            return
        }    

        if($RestoreDBConnectionOnAllBrokers)
        {
            #if the connection broker is legacy (Windows 2012 R2 or Windows 2012) - this parameter is not supported.        
            $error =(Get-ResourceString RestoreDatabaseConnectionOnAllBrokersNotSupported $ConnectionBroker)       
            Write-Error $error
            return            
        }
        
        #check if the -DatabaseConnectionString parameter is for shared database server and legacy OS      
        if( !$isDedicatedHAConfig)
        {
            $error = (Get-ResourceString SharedDatabaseServerOnLegacyOSNotSupported $ConnectionBroker)
            Write-Error $error
            return
        }   
    }  
    else
    {
        #check if -RestoreDatabaseConnection parameter was given with -RestoreDBConnectionOnAllBrokers - for Windows 2016 and later OS versions
        if($RestoreDBConnectionOnAllBrokers)
        {
            if($RestoreDatabaseConnection)
            {
                $onSpecifiedBrokerOnly = $false
            }
            else
            {
                $error = Get-ResourceString RestoreOnAllBrokersWithoutRestoreDBConnString
                Write-Error $error
                return
            }        
        }
        else
        {
            $onSpecifiedBrokerOnly = $true
        }    

        #if it is not shared database(SQL/database authentication) configuration DatabaseSecondaryConnectionString is not supported
        if($isDedicatedHAConfig)
        {
             if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
             {            
                $error = Get-ResourceString DoNotSetSecondaryDatabaseConnStr
                Write-Error $error
                return
             }
        }
        else
        {
             if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
             {            
                # connection string should be in the correct format, with SQL authentication specified, as it is supported only on shared database configuration
                $isSecondaryConnStringWinAuth = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker, $DatabaseSecondaryConnectionString)

                if($isSecondaryConnStringWinAuth)
                {
                    $error = Get-ResourceString SharedDatabaseConnStrFormatError
                    Write-Error $error
                    return
                }
             }            
        }

        # at least one connection string should be provided
        if(([string]::IsNullOrEmpty($DatabaseConnectionString)) -and ([string]::IsNullOrEmpty($DatabaseSecondaryConnectionString)))
        {
            $error = Get-ResourceString BothConnStringNullErr
            Write-Error $error
            return
        }  

        #check that the database name matches
        $matchDB = Test-DatabaseNameMatch -ConnectionBroker $ConnectionBroker -DatabaseConnectionString $DatabaseConnectionString -DatabaseSecondaryConnectionString $DatabaseSecondaryConnectionString
        if(!$matchDB)
        {
            $error = Get-ResourceString NotMatchingDatabaseNameErr
            Write-Error $error
            return
        }
    }
    

    if($RestoreDatabaseConnection)
    {        
        if($onSpecifiedBrokerOnly)
        {
            $result = Update-DBConnStringNoDatabaseAccess -ConnectionBroker $ConnectionBroker -DatabaseConnectionString $DatabaseConnectionString -DatabaseSecondaryConnectionString $DatabaseSecondaryConnectionString -OnSpecifiedBrokerOnly
        }
        else
        {
            $result = Update-DBConnStringNoDatabaseAccess -ConnectionBroker $ConnectionBroker -DatabaseConnectionString $DatabaseConnectionString -DatabaseSecondaryConnectionString $DatabaseSecondaryConnectionString
        }     
    }
    else
    {
        $result = Update-DBConnStringWithDatabaseAccess -ConnectionBroker $ConnectionBroker -DatabaseConnectionString $DatabaseConnectionString -DatabaseSecondaryConnectionString $DatabaseSecondaryConnectionString
    }

    if(!$result)
    {
        $error = Get-ResourceString ConnStringResetFailed
        Write-Error $error
        return
    }

    return
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
#need to update the help link ID (254057) once we update the help doc
function Remove-DatabaseConnectionString {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254057")]
param (

    [Parameter(ParameterSetName="DatabaseConnectionString", Mandatory=$true)]
    [switch]
    $DatabaseConnectionString,

    [Parameter(ParameterSetName="DatabaseSecondaryConnectionString", Mandatory=$true)]
    [switch]
    $DatabaseSecondaryConnectionString,

    [Parameter(Mandatory=$false, Position=0)]
    [String]
    $ConnectionBroker,

    [Parameter(Mandatory=$false)]
    [switch]
    $Force

)

    $error = $null

    $otherParams = New-Object 'System.Collections.Generic.Dictionary[String,Object]'

      
    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }   
    
    #check if the connection broker is legacy (Windows 2012 R2 or Windows 2012) - this cmdlet is not supported on legacy Windows OS.
    $isWin10OrLater = Test-IsWindows10OrLater($ConnectionBroker)
    if(!$isWin10OrLater)
    {
         $error =(Get-ResourceString LegacyOSNotSupported $ConnectionBroker)
         Write-Error $error
         return
    }

    #if it is not shared database(SQL/database authentication) configuration deleting DatabaseSecondaryConnectionString is not supported
    if([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker))
    {           
            $error = Get-ResourceString RemoveConnStringOnDedicatedDBServer
            Write-Error $error
            return
    }

    #get the secondary database connection string that we will remove from all brokers in the deployment
    $SbServiceProp = Get-WMIObject Win32_SessionBrokerServiceProperties -Namespace root\cimv2 -ComputerName $ConnectionBroker -Authentication PacketPrivacy -ErrorAction Stop
    #check if it is NULL or empty ans show a message
    if([string]::IsNullOrEmpty($SbServiceProp.SBDbSecondaryConnectionString))
    {
        $error = Get-ResourceString SecondaryConnectionStringNotSet
        Write-Debug $error
        return
    }
  
    try
    {
        # check the db connection string to be removed
        switch ($PsCmdlet.ParameterSetName)
        {
            "DatabaseConnectionString"
            {
                $error = Get-ResourceString RemovePrimaryConnStringNotSupported
                Write-Error $error
                return
            }

            "DatabaseSecondaryConnectionString"
            {

             $RemoveRDSecondaryDBConnectionStringMessageWhatif = (Get-ResourceString RemoveRDSessionCollectionServerMessageWhatif $SbServiceProp.SBDbSecondaryConnectionString)
             $RemoveRDSecondaryDBConnectionStringCaption = (Get-ResourceString RemoveRDSecondaryDBConnectionStringCaption)
             $RemoveRDSecondaryDBConnectionStringMessage = (Get-ResourceString RemoveRDSecondaryDBConnectionStringMessage $SbServiceProp.SBDbSecondaryConnectionString)
             if( -not ($PSCmdlet.ShouldProcess($RemoveRDSecondaryDBConnectionStringMessageWhatif, $RemoveRDSecondaryDBConnectionStringMessage, $RemoveRDSecondaryDBConnectionStringCaption)) )
             {
                return
             }

             if( (-not $Force) -and (-not $PSCmdlet.ShouldContinue( $RemoveRDSecondaryDBConnectionStringMessage, $RemoveRDSecondaryDBConnectionStringCaption)) )
             {
                return
             }
               
                $brokerList = Get-RDServer -ConnectionBroker $ConnectionBroker -Role RDS-CONNECTION-BROKER
                $oldDbSecondaryConnStringList = New-Object 'System.Collections.Generic.Dictionary[String,Object]'
                foreach ($broker in $brokerList) 
                {
                    Write-Debug ("Broker = " + $broker.Server)

                    $SbServiceProp = Get-WMIObject Win32_SessionBrokerServiceProperties -Namespace root\cimv2 -ComputerName $broker.Server -Authentication PacketPrivacy -ErrorAction Stop

                    if($SbServiceProp.SBDbSecondaryConnectionString)
                    {               
                        $oldDbSecondaryConnString = $SbServiceProp.SBDbSecondaryConnectionString
                        $SbServiceProp.DeleteSBDbConnectionString($true) | Out-Null
                        $oldDbSecondaryConnStringList.Add($broker.Server, $oldDbSecondaryConnString)
                    } 
                }     
            }
        }
        #update connections strings in RDMS database (only on the active broker)
        $wmic = gwmi -Namespace ROOT\cimv2\rdms -Class Win32_RDMSDeploymentSettings -List -ComputerName $ConnectionBroker -Authentication PacketPrivacy
        $OldRdmsSecondaryConnStr = $wmic.GetSecondaryConnectionString().SecondaryConnectionString

        $wmic.RemoveDeploymentSetting('DatabaseSecondaryConnectionString') | Out-Null
    }
    catch
    {
        Write-Error $_.Exception.Message        

        # Reset values in case of failure
        foreach ($broker in $oldDbSecondaryConnStringList.Keys) 
        {
            Write-Debug ("Resetting Broker = " + $broker)

            $SbServiceProp = Get-WMIObject Win32_SessionBrokerServiceProperties -Namespace root\cimv2 -ComputerName $broker -Authentication PacketPrivacy -ErrorAction SilentlyContinue
            if(![string]::IsNullOrEmpty($DatabaseSecondaryConnectionString))
            {
               $SbServiceProp.SBDbSecondaryConnectionString = $oldDbSecondaryConnStringList[$broker]               
               $SbServiceProp.Put() | Out-Null
            }
        }
        #reset values for RDMS as well (on active broker only)
        $wmic = gwmi -Namespace ROOT\cimv2\rdms -Class Win32_RDMSDeploymentSettings -List -ComputerName $ConnectionBroker -Authentication PacketPrivacy
        if(![string]::IsNullOrEmpty($OldRdmsSecondaryConnStr))
        {        
            $wmic.SetSecondaryConnectionString($OldRdmsSecondaryConnStr) | Out-Null
        }
    }
    finally
    {
    }

    return
}


# .ExternalHelp RemoteDesktop.psm1-help.xml
function Get-ConnectionBrokerHighAvailability {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254058")]
[OutputType("Microsoft.RemoteDesktopServices.Common.RDCBHADetails")]
param (

    [Parameter(Mandatory=$false, Position=0)]
    [String]
    $ConnectionBroker)
    
    $error = $null

    [Microsoft.RemoteDesktopServices.Common.DeploymentValidations] $result = [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None
    
    if([string]::IsNullOrEmpty($ConnectionBroker))
    {
        $ConnectionBroker = [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetLocalhostFullyQualifiedDomainname()
    }    
    
    # Parameter validations
    
    $FailedServers = $null
    $result = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::ValidateDeployment(
                            [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentAction]::GetHighAvailabilityDetails, 
                            $null,
                            0, 
                            $ConnectionBroker,
                            [ref]$FailedServers)
    
    if ($result -ne [Microsoft.RemoteDesktopServices.Common.DeploymentValidations]::None)
    {
       $error = [Microsoft.RemoteDesktopServices.Management.Activities.DeploymentVerification]::GetErrorMessage($result, 0)
       Write-Error $error
       return
    }

    $haConfigInfo = [Microsoft.RemoteDesktopServices.Common.DeploymentModel]::GetDeploymentHighAvailabilityProperties($ConnectionBroker)

    $isWin10OrLater = Test-IsWindows10OrLater($ConnectionBroker)
    $haConfigData = $null

    if($haConfigInfo -ne $null)
    {
         #format the data for display
        $haConfigData = new-object psobject

        Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name ConnectionBroker -Value $haConfigInfo.ConnectionBroker
        Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name ActiveManagementServer -Value $haConfigInfo.ActiveManagementServer
        Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name ClientAccessName -Value $haConfigInfo.ClientAccessName
        Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name DatabaseConnectionString -Value $haConfigInfo.DatabaseConnectionString

        #check the HA configuration: dedicated or shared database server
        if([Microsoft.RemoteDesktopServices.Common.DeploymentModel]::IsDedicatedDatabaseServerConfiguration($ConnectionBroker))
        {       
           Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name DatabaseFilePath -Value $haConfigInfo.DatabaseFilePath
           if($isWin10OrLater)
           {
             Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name DatabaseSecondaryConnectionString -Value $null
           }          
        }
        else
        {
            #SecondaryConnectionString is supported only on Windows 2016 and later deployments
            if($isWin10OrLater)
            {
                Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name DatabaseSecondaryConnectionString -Value $haConfigInfo.DatabaseSecondaryConnectionString
                Add-Member -InputObject $haConfigData -MemberType NoteProperty -Name DatabaseFilePath -Value $null
            }           
        }   
    }     

   $haConfigData
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Get-VirtualDesktopTemplateExportPath {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254059")]
[OutputType([String])]
param(
    [Parameter(Mandatory=$false)]
    [string]
    $ConnectionBroker
)
    $ConnectionBroker = Initialize-Fqdn($ConnectionBroker)
    if ([string]::IsNullOrEmpty($ConnectionBroker))
    {
        Write-Error (Get-ResourceString InvalidFqdn $ConnectionBroker)
        return
    }

    $out = Invoke-WmiMethod -Class Win32_RDMSDeploymentSettings -Name GetExportPath `
                -ComputerName $ConnectionBroker -Authentication PacketPrivacy -Namespace "root\cimv2\rdms"

    if ($out.ReturnValue -eq 0)
    {
        Write-Debug "Win32_RDMSDeploymentSettings::Get-DeploymentExportLocation method executed successfully."
        return $out.DirectoryPath
    }
    else
    {
        Write-Error (Get-ResourceString DeploymentExportLocationQueryFailed $out.ReturnValue)
        return $null
    }
}


# .ExternalHelp RemoteDesktop.psm1-help.xml
function Set-VirtualDesktopTemplateExportPath {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254060")]
param(
    [Parameter(Mandatory=$false)]
    [string]
    $ConnectionBroker,

    [Parameter(Mandatory=$true)]
    [string]
    $Path
)

    $ConnectionBroker = Initialize-Fqdn($ConnectionBroker)
    if ([string]::IsNullOrEmpty($ConnectionBroker))
    {
        Write-Error (Get-ResourceString InvalidFqdn $ConnectionBroker)
        return
    }

    $found = test-path $Path

    if ($found -eq $true)
    {
        $out = Invoke-WmiMethod -Class Win32_RDMSDeploymentSettings -Name SetExportPath  -ArgumentList ($Path) `
                    -ComputerName $ConnectionBroker -Authentication PacketPrivacy -Namespace "root\cimv2\rdms"

        if($out.ReturnValue -eq 0)
        {
            Write-Verbose (Get-ResourceString SetDeploymentExportLocationSuccess $Path)
        }
        else
        {
            Write-Error (Get-ResourceString SetDeploymentExportLocationFailed $out.ReturnValue)
        }
    }
    else
    {
        Write-Error (Get-ResourceString InvalidPath $Path)
    }
}

# .ExternalHelp RemoteDesktop.psm1-help.xml
function Test-OUAccess {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254061")]
param(

    [Parameter(Mandatory=$false)]
    [string]
    $Domain,

    [Parameter(Mandatory=$true)]
    [string]
    $OU,

    [Parameter(Mandatory=$false)]
    [string]
    $ConnectionBroker
)

    $ConnectionBroker = Initialize-Fqdn($ConnectionBroker)
    if ([string]::IsNullOrEmpty($ConnectionBroker))
    {
        Write-Error (Get-ResourceString InvalidFqdn $ConnectionBroker)
        return
    }

    if (Test-LocalUser)
    {
        Write-Error(Get-ResourceString InvalidLocalUser)
        return
    }

    if (-not (Test-RemoteDesktopDeployment -RDManagementServer $ConnectionBroker))
    {
        Write-Error (Get-ResourceString DeploymentDoesNotExist $ConnectionBroker)
        return
    }

    if(-not $Domain)
    {
        $Domain = Get-RDManagementServerDomain($ConnectionBroker)
        if(-not $Domain)
        {
            Write-Error (Get-ResourceString FailedToGetComputerObject $ConnectionBroker)
            return
        }
    }

    # Validate OU

    $distinguishedName = Get-DistinguishedName $Domain $OU

    if ($distinguishedName -eq $null)
    {
        Write-Error (Get-ResourceString InvalidDomainOrOU ($Domain, $OU))
        return
    }

    Write-Debug ("OU Validated. DistinguishedName = " + $distinguishedName)

    $brokerList = Get-RDServer -ConnectionBroker $ConnectionBroker -Role RDS-CONNECTION-BROKER

    $returnValue=$true
    try
    {
        $workflowSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

        foreach ($broker in $brokerList) {

            Write-Debug ("Broker = " + $broker.Server)
            $netbiosName = ""
            $domainName = ""
            [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetNetbiosAndDomainFromJoinedNode($ConnectionBroker, $broker.Server, [ref]$netbiosName, [ref]$domainName)
            $adObjectName = $domainName + "\" + $netbiosName

            $out = Invoke-Command -Session $workflowSession -ArgumentList @($distinguishedName, $adObjectName) `
            {
                param($dn, $adObjectName)
                RDManagement\Test-OUAccess -ContainerName $dn -ComputerName $adObjectName
            }

            if (($out) -and ($out[0] -eq 0) -and ($out[1]))
            {
                Write-Verbose (Get-ResourceString TestOUAccessSuccess ($distinguishedName, $broker.Server))
                $returnValue = ($returnValue -and $true)
            }
            else
            {
                if(($out) -and (0 -ne $out[0]))
                {
                    Write-Verbose ("Error: "+$out[0])
                }
            
                Write-Verbose (Get-ResourceString FailedToTestOUAccess ($distinguishedName, $broker.Server))
                $returnValue=$false
            }
        }
    }
    catch
    {
        Write-Error $_.Exception.Message        
    }
    finally
    {
        if($workflowSession)
        {
            Remove-PSSession -Session $workflowSession
        }
    }
    return $returnValue
}


# .ExternalHelp RemoteDesktop.psm1-help.xml
function Grant-OUAccess {
[CmdletBinding(HelpURI="https://go.microsoft.com/fwlink/?LinkId=254062")]
param(

    [Parameter(Mandatory=$false)]
    [string]
    $Domain,

    [Parameter(Mandatory=$true)]
    [string]
    $OU,

    [Parameter(Mandatory=$false)]
    [string]
    $ConnectionBroker
)

    $ConnectionBroker = Initialize-Fqdn($ConnectionBroker)
    if ([string]::IsNullOrEmpty($ConnectionBroker))
    {
        Write-Error (Get-ResourceString InvalidFqdn $ConnectionBroker)
        return
    }

    if (Test-LocalUser)
    {
        Write-Error(Get-ResourceString InvalidLocalUser)
        return
    }

    if (-not (Test-RemoteDesktopDeployment -RDManagementServer $ConnectionBroker))
    {
        Write-Error (Get-ResourceString DeploymentDoesNotExist $ConnectionBroker)
        return
    }

    if(-not $Domain)
    {
        $Domain = Get-RDManagementServerDomain($ConnectionBroker)
        if(-not $Domain)
        {
            Write-Error (Get-ResourceString FailedToGetComputerObject $ConnectionBroker)
            return
        }
    }

    # Validate OU
    $distinguishedName = Get-DistinguishedName $Domain $OU

    if ($distinguishedName -eq $null)
    {
        Write-Error (Get-ResourceString InvalidDomainOrOU ($Domain, $OU))
        return
    }

    Write-Debug ("OU Validated. DistinguishedName = " + $distinguishedName)

    $brokerList = Get-RDServer -ConnectionBroker $ConnectionBroker -Role RDS-CONNECTION-BROKER

    try
    {
        $workflowSession = New-PSSession -ConfigurationName Microsoft.Windows.ServerManagerWorkflows -EnableNetworkAccess

        foreach ($broker in $brokerList) {

            Write-Debug ("Broker = " + $broker.Server)
            $netbiosName = ""
            $domainName = ""
            [Microsoft.RemoteDesktopServices.Common.CommonUtility]::GetNetbiosAndDomainFromJoinedNode($ConnectionBroker, $broker.Server, [ref]$netbiosName, [ref]$domainName)
            $adObjectName = $domainName + "\" + $netbiosName

            $out = Invoke-Command -Session $workflowSession -ArgumentList @($distinguishedName, $adObjectName) `
            {
                param($dn, $adObjectName)
                RDManagement\Grant-OUAccess -ContainerName $dn -ComputerName $adObjectName
            }

            if ($out -eq 0)
            {
                Write-Debug "Grant-OUAccess workflow executed successfully."

                Write-Verbose (Get-ResourceString GrantOUAccessSuccess ($distinguishedName, $broker.Server))
            }
            else
            {
                Write-Error (Get-ResourceString FailedToGrantOUAccess ($distinguishedName, $broker.Server, $out))
            }
        }
    }
    catch
    {
        Write-Error $_.Exception.Message        
    }
    finally
    {
        if($workflowSession)
        {
            Remove-PSSession -Session $workflowSession
        }
    }
}

Youez - 2016 - github.com/yon3zu
LinuXploit