tag:blogger.com,1999:blog-9914466917921572312024-03-13T00:03:52.578-04:00Brian NipperNip on Tech, Life and STUFFBrian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comBlogger31125tag:blogger.com,1999:blog-991446691792157231.post-10230657196350424592021-01-02T23:36:00.003-05:002021-01-03T09:12:44.225-05:00Teaching others to learn yourself<div style="text-align: left;">I’ve never liked the expression... "those that can't do, teach". This implies that those that are not capable of completing an action on their own or perhaps are aware of some inherent limitation they have prefer not to risk making "a go of it" on their own and instead instruct others that are more adventurous.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">It has been my personal experience that to get really good at anything it's important to exercise the mental muscle to try and impart the knowledge of said skill to a novice. To impart what you have learned to someone unfamiliar with the task but is perhaps eager to learn of even just curious about it.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">To that end I'm gonna take a stab at producing <a href="https://www.youtube.com/channel/UCOM5QeM9W0OMgXQsWQq4nFA">YouTube videos</a>.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">While I have no idea what may come of this endeavor, just making the attempt has been both exciting and a self-teaching experience.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">My initial approach is to keep the videos short, less than 10 minutes. This has the advantage of feeling approachable and seems like I might actually stick to some kind of schedule. Additionally I feel like if I recommended someone review a video to learn something they might be willing to commit the time.</div><div style="text-align: left;"><br /></div><div style="text-align: left;">Time will tell how well this ages, but I'm optimistic that at least I'm going to learn something from it. </div>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com1tag:blogger.com,1999:blog-991446691792157231.post-35870036599416339552019-07-16T21:58:00.000-04:002021-07-14T22:02:01.176-04:00Reason for difference in Azure VM Scale Set applying (a.k.a. why the upgrade button isn't needed)<div class="WordSection1"> <p class="MsoNormal">Just wanted to share some info on something that came up yesterday.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">When updating a VM Scale Set (vmss) definition I found a situation where I needed to press the "Upgrade" button to apply the model in one situation and DID NOT need to press the button in another situation.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">While looking into scripting this operation I stumbled across this medium article <a href="https://medium.com/microsoftazure/updating-azure-vm-scale-set-without-downtime-with-rolling-updates-734dcb540d6b" target="_blank" title="https://medium.com/microsoftazure/updating-azure-vm-scale-set-without-downtime-with-rolling-updates-734dcb540d6b"> Updating Azure VM Scale Set without downtime with Rolling Updates</a> <o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">In the article it outlines how to get info on the "Upgrade Policy", this is something that isn't readily obvious IN the portal, so you really need to use PowerShell commands or the Azure CLI commands to see the info.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">I'm using PowerShell AZ commands (NOT CLI).<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">Using the command Get-AzVmss I found that the Upgrade Policy for the scale set which I HAD to press the upgrade was set to manual, which makes sense. Manual Upgrade would mean a user would need to take an action.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">Using the same command for the other scale set the Policy was Automatic, so again makes sense why I DID NOT need to press the button.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> <p class="MsoNormal">So as is often the case with technology pays to read the docs.<o:p></o:p></p> <p class="MsoNormal"><o:p> </o:p></p> </div> Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-67260641809750675232018-11-22T10:30:00.000-05:002018-11-23T09:27:02.227-05:00What were they thinking<div class="WordSection1">
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Face-angel.svg/240px-Face-angel.svg.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="240" data-original-width="240" src="https://upload.wikimedia.org/wikipedia/commons/thumb/d/d5/Face-angel.svg/240px-Face-angel.svg.png" /></a></div>
<span style="font-size: 14.666666984558105px;">As of late I have been spending a lot of time working on a “legacy” system. The term legacy means different things for different groups, in the circle I’m working with these days it means a system that is no longer being actively developed. As has been stated by mean, software isn’t “dead” it’s “done”.</span><br />
<span style="font-size: 14.666666984558105px;"><br /></span>
<span style="font-size: 14.666666984558105px;">The catalyst for the work I’m doing is security requirements that need to be applied. While applying the updated security polices I’ve also been tasked with migrating the system from our data center to our cloud data center. As I move through the system I’m confronted with implementations that looking at now seem crazy; however, it’s these situations where it is important to apply two mindsets. One is giving others the benefit of the doubt. In a case like this, those that were working on this system used, for the time, the best options the technology stack could offer. For example, the extensive use of WCF seems silly now; however, at the time it was a recommended approach to hooking up independent systems. When reviewing the code in light of this you can really see how those that worked on it were making thoughtful and considerate choices.</span><br />
<span style="font-size: 14.666666984558105px;"><br /></span>
<span style="font-size: 14.666666984558105px;">The second mindset that is important to apply, and in my mind is more important to adhere to, is to assume good intent. This is important because even if someone did NOT follow the prevailing approach for the time, or use the best in class technology they had a good reason, or good intent for doing what they did. Consider those that came before as doing the best work they could. Perhaps they had constraints that prevented them from making, what would seem like, a better choice. Perhaps their was a time constraint as is so often the case. Perhaps, as we so often assume, they didn’t know any better, but even then, they were trying their best, which is worthy of acknowledgement.</span><br />
<span style="font-size: 14.666666984558105px;"><br /></span>
<span style="font-size: 14.666666984558105px;">Now how does this help, well often it allows you to see the system in the light of what it does well. It will provide a perspective that can outline what the system can offer and, as I’m finding, it will allow you to find an approach to extend/adjust the system to comply with the new constraints you are tackling.</span><br />
<span style="font-size: 14.666666984558105px;"><br /></span>
<span style="font-size: 14.666666984558105px;">So the next time you work on a legacy system and you are cursing the fool that came before, stop and think... give them the benefit of the doubt and assume they had good intentions. You will land in a better spot.</span></div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-42233338215241273682018-11-08T10:30:00.000-05:002018-11-08T10:30:09.537-05:00Being a good customer means being able to complain in a way that is helpful<div class="WordSection1">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3220hJ8Uc8JeSv84HoZZ-fyMiGW1UhbK5S9po2vCL0yQezTSqpA8xX4aQzb1dTXRttuC5smmkGI_D3aL9nHu7iecGuQ1SiFkDnGWij7iAdqg44iVC7r2eHFFwMVtKKP4WcezSpKyoOow/s1600/BadSurvey.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img alt="BAD SURVEY: Tell us what you think... OK, GREAT, EXCELLENT, AMAZING!!!!" border="0" data-original-height="380" data-original-width="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg3220hJ8Uc8JeSv84HoZZ-fyMiGW1UhbK5S9po2vCL0yQezTSqpA8xX4aQzb1dTXRttuC5smmkGI_D3aL9nHu7iecGuQ1SiFkDnGWij7iAdqg44iVC7r2eHFFwMVtKKP4WcezSpKyoOow/s1600/BadSurvey.png" style="filter: drop-shadow(30px 10px 4px #4444dd);" title="BAD SURVEY" /></a>I'm often told that I deal with difficult situations in a way that results in getting what I want. To me this is quick an interesting observation because I find that most often what people mean when they say that is, when I receive a poor customer experience I'm able to turn things around so that I obtain a desirable outcome, thus turning a bad experience into a good one.<br />
<br />
This manifest itself most often when I'm out and about with my wife. We will be at a retail store, or out to dinner and something will go wrong. Often my wife will turn to me and suggest that I handle it since "I know how to deal with these things". So what is the secret to my taking a bad situation and turning it around... being a good customer.<br />
<br />
As it turns out business want to make money. Shocking, I know. The way they make money is by advertising to attract customers to frequent their brick and mortar locations to use their services or purchase their goods. Knowing this puts the customer in wonderful position. How so? Well said business has already spent a measurable amount of money to get you in the door and ideally they would like you to come back without having to spend a lot more money on advertising. If you have had a bad experience and they are made aware of this then the responsible business will train their employees to try and recover the situation by offsetting the bad with good. This can be in the form of a coupon, discount, or even the wonderful freebie.<br />
<br />
But there is the human element to these situations that can result in you missing out on ANY benefit. Case in point, let's say you are out for dinner and you have a bad experience and feel you are do some offsetting consideration how can you go about achieving this goal and turning the situation into a benefit.<br />
<br />
My tried and true method is to make someone aware and stick to the facts. Often this translates to asking to speak to the person in charge AND being specific. If you are at a retail store and find that you are charged the wrong price don't dispute the matter with the cashier. They won't have access to change a price in the Point of Sale, also they are most often NOT involved in causing the issue so don't waste their time and yours trying to make them fix the price at the register. Ask to have your ticket transferred to the customer service desk. Remember you can always get a refund on the missed price item and thus holding up the line only annoys people and will NOT get you want you want, which should be the price you expected to pay.<br />
<br />
When you find a person "in charge" stick to the facts. Can you show them in print the price you expected to pay? If so you almost are guaranteed to be able to buy the item at the price in print. If it's just the price you "thought" you say you have very little ground to stand on. But let's say you HAVE the e-mail or print ad with the price listed and it's less than what was on your receipt. If it's less than 1-2% of the overall purchase then there will probably be little discussion about the difference being refunded; however, more than that and it's possible the company could be losing money on the deal and with margins the way they are it could be a deal breaker.<br />
<br />
What to do in those situations? First, align your objective. You want the price listed and the company doesn't want to lose money, sounds like a great time to bargain. If you are committed to buying the item then any discount at all is a win, so.. start big and back down. Ask for the full difference in price, if they don't budge ask for 75% less, then 25%... nothing hurts in asking. Also this is when it helps to be mindful of your surroundings. If you think "making a stink" and drawing attention will get you what you want, along the lines of "give me what I want and I'll stop making trouble" you are slipping into the mindset of being a trouble maker. Let me ask you, do you want to help a troublemaker. Probably not. If you are polite and DO NOT draw undo attention then a person in charge is more inclined to think that they can "make you happy" without others needing to catch wind of the price change and cause a stamped.<br />
<br />
At this point once you have a "person in charge" and they realize you are looking for some type of compensation/consideration, it helps to be clear about your problem. What I mean by this is explain your desire to continue to be a customer and that this misinformation about price will make it hard for you to "trust" their advertising; however, you do really like their store and are interested in coming back; otherwise your inclined to just use the online retail which guarantees the price. This last line is the kicker. Retail in particular is very aware that it is at a disadvantage with the online competition so reminding them of this, while sometimes a risk, often results in the push to get the desired consideration.<br />
<br />
All of this advice also is mute if you are not a considerate customer. Don't be rude, don't belittle people who are employee's of the company. Be respectful and attempt to avoid making "problems" for others.<br />
<br />
I hope my approach helps you complain in a helpful way.</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-18756043650176025102018-11-01T11:08:00.002-04:002018-11-01T11:09:05.926-04:00Benefits of Working with .NET ConcurrentQueue<T><a href="https://commons.wikimedia.org/wiki/File:Kolejka.jpeg#/media/File:Kolejka.jpeg" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Kolejka.jpeg" height="174" src="https://upload.wikimedia.org/wikipedia/commons/c/c0/Kolejka.jpeg" width="320" />*</a><br />
Working with a queue in .NET is an excellent experience and provides a great way to decouple execution paths. Once you start working with in memory queues your just a hope, skip, and a jump away from using "infrastructure" queues such as Service Bus, RabbitMQ, or even MSMQ on Windows Desktop.<br />
<br />
While it is quite possible to work with the standard .NET <a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.generic.queue-1?view=netframework-4.7.2" target="_blank">Queue<T></a> object if you find that you are in need of using a lock to ensure consistent results with putting things in the queue (i.e. Enqueue) and taking things off (i.e Dequeue or Peek) or even just to obtain a consistent reliable count, well then you should probably take a look at <a href="https://docs.microsoft.com/en-us/dotnet/api/system.collections.concurrent.concurrentqueue-1?view=netframework-4.7.2" target="_blank">ConcurrentQueue<T></a>.</t></t><br />
<br />
There is a whole section of the .NET Framework with deals with concurrency concerns by creating specific objects for Dictionaries, Stacks, Queues and more that are considered thread safe.<br />
<br />
When I started working with ConcurrentQueues I found it helpful to put my own wrapper around the concurrent queue object and so I've demonstrated that in the following sample which I hope others find useful.<br />
<br />
Link to example: <a href="https://gist.github.com/briannipper/c861e708874428d4dc6dda5817411c70" target="_blank">https://gist.github.com/briannipper/c861e708874428d4dc6dda5817411c70</a><br />
<script src="https://gist.github.com/briannipper/c861e708874428d4dc6dda5817411c70.js"></script>
*Public Domain, <a href="https://commons.wikimedia.org/w/index.php?curid=38850">Link</a>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-32119430874859771712018-10-25T10:30:00.000-04:002018-10-25T10:30:07.530-04:00Things I need to remember... IIS Express ports for HTTPS and Configure WCF Rest endpoints for HTTPS<div class="WordSection1">
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTDIbc_-TKnbXSySUdKaPH5N-YKxB26bFEfx1kDl-jvOuxA33qGvDkX_MAXuomTDspIeRla5sntUyEyRfokTDkV2oO5DAqwQHgYhAfTiSV_KcEqUVYYkHLvWi7usXvftSsvvPFDoY5g2M/s1600/13428363861300088437dont-forget+smiley-md.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img alt="Don't Forget" border="0" data-original-height="297" data-original-width="300" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhTDIbc_-TKnbXSySUdKaPH5N-YKxB26bFEfx1kDl-jvOuxA33qGvDkX_MAXuomTDspIeRla5sntUyEyRfokTDkV2oO5DAqwQHgYhAfTiSV_KcEqUVYYkHLvWi7usXvftSsvvPFDoY5g2M/s1600/13428363861300088437dont-forget+smiley-md.png" title="Don't Forget" /></a>
<!--
Image obtained from http://www.clker.com which per their Trems and conditions are providing public domain clip art that can be freely used as they are NON-Copyright images.
-->
</div>
As I have been writing consistently for a bit now I've already found myself referring back to things I've posted, which has prompted me to try and post items which have taken a bit of time to work out. It seems that the act of "writing it down" causes me to remember information better. Perhaps it's all the thought into attempting to write something useful.<br />
<br />
This post includes two details which took me more than a few hours to sort out so I hope to help others who have a similar need. Funny enough it could be me in the future after I've forgotten this information.<br />
<br />
First up is a little detail that I know I've forgotten and looked up more than once, and depending on the google/bing results I find sooner or later.<br />
<br />
<h3>
Setting up IIS Express to host a site via HTTPS</h3>
<div>
When configuring your site to run in IIS Express using Visual Studio it's fairly trivial to set the attribute to use SSL (i.e. HTTP over SSL which is HTTPS) as it's just an "enable" in the drop box for use SSL. Additionally when you do this it will ensure that a local cert is setup as well which should be locally trusted so that the browser doesn't through any warnings; but a detail that could trip you up is you'll need to use a PORT within a specific pre-allocated range as IIS Express grabs the range just for this purposes.</div>
<div>
<br /></div>
<div>
<b>Port range 44300 to 44399</b></div>
<div>
<b><br /></b></div>
<div>
A great <a href="https://www.pluralsight.com/guides/visual-studio-2017-resolving-ssl-tls-connections-problems-with-iis-express" target="_blank">troubleshooting at pluralsight</a> that includes this little gem on port ranges along with other tips.</div>
</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<h3>
<span style="font-size: 14.6667px;">Setup bindings for WCF REST service end-points to use HTTPS be default</span></h3>
</div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">I'll be the first to acknowledge that this is really legacy information as WCF REST services have been essentially deprecated by .NET WebAPI technologies, and for that I'm VERY pleased; however, working with legacy technologies has NOT been deprecated so I'll post this here for others benefit.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">This nugget of information took me the better part of the morning to dig out of a the Microsoft site on <a href="https://msdn.microsoft.com/en-us/library/ee354381.aspx" target="_blank">A Developer's Introduction to Windows Communication Foundation 4</a>.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">The detail I needed was found under the sub-heading aptly named </span><b style="font-size: 14.6667px;">Default Binding Configurations </b><span style="font-size: 14.6667px;">where it outlines that if you would like a particular binding to be used by default you simply need to create the binding without a name and by this convention all service end-points will, be default utilize this binding. The same is true of a behavior configuration, omit the name property and the binding or behavior is adopted by all services defined in the project.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">From the same document they provide the following sample which I've replicated and modified to demonstrate how to enable HTTPS for all your service end-points.</span><br />
<br />
<br />
<span class="hljs-tag" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"><<span class="hljs-name" style="box-sizing: inherit;">configuration</span>></span><br />
<span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"> <</span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">system.serviceModel</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">></span><br />
<span class="hljs-tag" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"> <<span class="hljs-name" style="box-sizing: inherit;">bindings</span>></span><br />
<span style="background-color: #fafafa; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"></span><span class="hljs-tag" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"> <<span class="hljs-name" style="box-sizing: inherit;">basicHttpBinding</span>></span><br />
<span style="background-color: #fafafa; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"></span><span class="hljs-tag" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"> <<span class="hljs-name" style="box-sizing: inherit;">binding</span>></span><br />
<span class="hljs-tag" style="box-sizing: inherit;"><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;"> <</span></span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">security</span> <span class="hljs-attr" style="box-sizing: inherit; color: #0451a5; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">mode</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;">=</span></span><span class="hljs-string" style="box-sizing: inherit; color: #a31515; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">"Transport" /</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;">></span></span></span><br />
<span class="hljs-tag" style="box-sizing: inherit;"><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;"> </</span></span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">binding</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;">></span></span></span><span style="background-color: #fafafa; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">
</span><span class="hljs-tag" style="box-sizing: inherit;"><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;"> </</span></span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">basicHttpBinding</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;">></span></span></span><span style="background-color: #fafafa; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">
</span><span class="hljs-tag" style="box-sizing: inherit;"><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;"> </</span></span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">bindings</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, Lucida Console, Liberation Mono, DejaVu Sans Mono, Bitstream Vera Sans Mono, Courier New, monospace, sans-serif;"><span style="font-size: 14px; white-space: pre;">></span></span></span><br />
<span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"> </</span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">system.serviceModel</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">></span><br />
<span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"></</span><span class="hljs-name" style="box-sizing: inherit; color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">configuration</span><span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;">></span><br />
<span style="color: #0101fd; font-family: Consolas, Menlo, Monaco, "Lucida Console", "Liberation Mono", "DejaVu Sans Mono", "Bitstream Vera Sans Mono", "Courier New", monospace, sans-serif; font-size: 14px; white-space: pre;"><br /></span></div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-91549488628547661382018-10-18T10:30:00.000-04:002018-10-18T10:30:03.547-04:00.NET MSTest and DeploymentItem Attribute<div class="WordSection1">
<div class="MsoNormal">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjML9pZkaD5zAJGvJeB00Az8-ARR1IeCUFBK6hD67VyHfRpnWHpU2jlZ-pa-T3c_XxtsvlMWjOI0UKk5rN28RnPYqzTlFGHJ2CsP_3ckrIbWeZT0TrYMZYU01JuytnLN3jfQboffg1YxuA/s1600/CA5FCC3D-1D3E-4C3B-BA16-72809A47E0BA.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="311" data-original-width="499" height="199" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjML9pZkaD5zAJGvJeB00Az8-ARR1IeCUFBK6hD67VyHfRpnWHpU2jlZ-pa-T3c_XxtsvlMWjOI0UKk5rN28RnPYqzTlFGHJ2CsP_3ckrIbWeZT0TrYMZYU01JuytnLN3jfQboffg1YxuA/s320/CA5FCC3D-1D3E-4C3B-BA16-72809A47E0BA.jpeg" width="320" /></a></div>
<span style="font-size: 14.666666984558105px;">I was recently reminded that order of operation can byte you when trying to troubleshoot intermittent unit test failures.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
First, I’ll be the first to admit that if you want to avoid problems with unit testing it’s best to avoid any dependency outside of your actual code base, things like databases, API and even the file system are best avoided in execution of your unit tests. That last one, the file system, in some applications is really hard to avoid.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you happen to be using MSTest, a helpful attribute for your test is DeploymentItem. This particular attribute allows you to define a file within your unit test project assuming it’s marked as “Copy Always”. With this attribute in place you can then combine this with TestContext.DeploymentDirectory to find this sample file and then do what you need to do.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In my particular case I was having an issue with the unit tests failing on the build machine but not locally. After stumbling around for a bit I finally feel back to the old debugging standard of printing out the entire directory of files to the console. It was at this point that I realized I was able to create files in the expected location so why could I not find the DeploymentItem? The answer, side effects.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In one test I “moved” the resource item, and it had just been a situation where locally the tests “happen” to execute in an order such that the move operation was happening at the end of the test cycle, thus masking the problem. When I switch the test in question to “copy” the file, which was still a valid test mind you my problems went away.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
As an alternative approach to solving this problem you could make the file an embedded resource and then, in the arrange part of the test, write out the file to disk and then perform the test to ensure that the file always exists at the start.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
I hope this information helps others avoid wasting time with these type of silly order of operation problems.</div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com1tag:blogger.com,1999:blog-991446691792157231.post-81565762855451463002018-10-11T10:30:00.000-04:002018-10-11T10:30:02.168-04:00Keep Calm and Get the Facts<img alt="KEEP CALM and GET THE FACTS" border="0" data-original-height="450" data-original-width="300" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhLb9taI2PXdJIcGZnwVTTtsVTqyZQW99CcPhGozPtBTkCGeN9ONSa6E2CfXsOKSJEMyhkK_1OZ8TOFy7rW_giqZm7BOBscMx8NgQyAq047FaxOdcu4GwF6xLfdOWp-10bl36-xIHb7l8I/s320/keep-calm-get-the-facts.jpg" style="clear: right; float: right; margin-bottom: 1.25em; margin-left: 1.25em;" title="KEEP CALM and GET THE FACTS" width="213" />
It often amazes me at how often I find myself apologizing to others for rashly commenting on a problem before I have all the facts. In fact, after so many years as a professional in the IT space and dealing with countless critical situation/severity one problems (a.k.a. Sev1, crit-sit) I would be able to react in a more appropriate and beneficial manner. The sad truth is that, as I write this post. I JUST "did it wrong" on a Sev1 from earlier in the day and found myself sheepishly apologizing for my brash response.<br />
<br />
Perhaps by writing this down and publishing for others to read I can obtain the positive results of public shame to result in my correcting my behavior. At least there is a chance someone else can read this and benefit from my mistakes.<br />
<br />
The fundamental problem I seem to have is that I hear a few pieces of information or even just the subject line of an e-mail or short text message and immediately jump to a conclusion. Having done a bit of a personal post-mortem, I find that this tends to be my go to response when there is a heightened sense of urgency. Perhaps when there is a Sev1 and my flight or fight response kicks in the adrenaline kicks in and causes my brain to overly react, at least that is the excuse I'm going to tell myself. What can I do about this? First, remember to breath, while it is perhaps a cliche it has been proven over and over again that taking a few deep breaths and making sure you have oxygen flowing helps you to think clearly. I also, personally, think that the time it takes you to breath can help dissipate some of that "nervous" energy that is initially kicked off by the excitement.<br />
<br />
Even if you forget to take the deep breaths, the one detail that must not be forgotten is this... <b>Get the Facts</b>. This is summed up quite nicely in a wise proverb which reads "When anyone replies to a matter before he hears the facts, it is foolish and humiliating" (<a href="https://wol.jw.org/en/wol/b/r1/lp-e/nwtsty/E/2018/20/18#study=discover&v=20:18:13" target="_blank">Proverbs 18:13</a>). Let me tell you, I feel like a fool when I realize that I've spoken about a problem, incorrectly. and it all could have been avoided simply by obtaining all the facts, which often are readily available.<br />
<br />
Related to this, when you find that facts you have distributed were inaccurate, it is vital to attempt to distribute the correction as quickly as possible. Even if you find that you don't have corrected information, but you know what was previously stated was inaccurate, it's helpful for others to know that so that decisions are not made on faulty details.<br />
<br />
I hope that my faults and lessons learned will be of benefit to others going forward.Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-30176696451359443052018-10-04T10:30:00.000-04:002018-10-04T10:30:05.987-04:00Compose a message through some else’s eyes<div dir="auto">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu_5QkDcOLGwwUt_Kp6kzBqpcfRxr1Tc1s8w9qIvjMtge9hLVSQS9Wue6QbyTpLFeRHF_HYKKRWNT3OHt1blRY0VDwUXFwGnpO-fvm2j8t9iGbBN_hwn5vDBXRoFvFLJ6LKJ5APO_DXSw/s1600/TwilightZone_EyeBeholder.PNG" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="528" data-original-width="570" height="296" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiu_5QkDcOLGwwUt_Kp6kzBqpcfRxr1Tc1s8w9qIvjMtge9hLVSQS9Wue6QbyTpLFeRHF_HYKKRWNT3OHt1blRY0VDwUXFwGnpO-fvm2j8t9iGbBN_hwn5vDBXRoFvFLJ6LKJ5APO_DXSw/s320/TwilightZone_EyeBeholder.PNG" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="https://en.wikipedia.org/wiki/The_Eye_of_the_Beholder" target="_blank">Twilight Zone: The Eye of the Beholder</a></td></tr>
</tbody></table>
I've always enjoyed science fiction work that intended to make the onlooker reflect on their world view, you know, really make you think about yourself. A wonderful example of that is the classic Twilight Zone: The Eye of the Beholder.<br />
<br />
Although I don't think it's needed at this point I will mention there are spoilers about this particular episode.<br />
<br />
The story outlines the tragic plight of a woman who has been horrible disfigured and all other attempts to make her look "normal" have failed until this final last ditch attempt. Through out you don't see the woman or the faces of the other characters. That is until the end when they unveil the woman by removing the bandages and you see, what at the time of filming, would have been considered an attractive movie star and as the camera pans around you also realize that everyone else appears to be "disfigured" according to what the vast majority of humans look like. Now your mind is blown and you spend the rest of the day really thinking about what you consider "normal". Mission accomplished.<br />
<br />
Clearly this is a story that attempts to drive home the point that, as the old adage goes "beauty is in the eye of the beholder". Well the principle can hold true for our communication. The meaning of our words, written, spoken, etc. are in the minds of the recipient.<br />
<br />
While I agree that what constitutes a normal appearance is very subjective and is driven by cultural biases and trends of the time I would propose that communication can fall into this same arena, but in a sort of microcosm of time. Most of us have probably experienced a situation where you've sent a text, e-mail or social media post and the results where widely varied. After getting this feedback and re-reading the message through the lens of those other readers you can clearly see why they interpreted your words as they did.<br />
<br />
This does not always mean that something horrible was conveyed or that you horrible offended a portion of the population, it could simply be that there was a misalignment, but still wouldn't it be great to find ways to avoid it in the first place. Perhaps these next communication tips could help you as they have helped me.<br />
<br />
Know your audience and write to them, not to yourself. When you draft communication or are speaking to a group consider the audience and avoid the trap of assuming they know what you know. This doesn't mean you have to spell out every little detail and link to a thousand different references, but be aware that terms often have context and you should try to explain the context when possible as this can avoid a great deal of misalignment.<br />
<br />
Tone of voice DOES NOT travel across written word without a HINT. This is easily illustrated in the form of j/k. When you write a text message to someone that is clearly meant to be sarcastic tacking a little j/k at the end avoids the possibility of the other person taking your words literally. It is wise to do this in all formal settings, such as speaking to a larger group beyond your immediate colleges or friends that probably better understand your sense of humor.<br />
<br />
When you have the benefit of having some time to draft a response consider re-reading a message after some time passes from initially writing it. Not only will you catch obvious typos you may find that portions of the message carry a tone you didn't intend. Maybe you were hungry when you were writing and rushed through something or you had a bad morning due to something completely unrelated. Take a break and return to re-read with a "fresh" pair of eyes.<br />
<br />
I hope this will benefit you as much as it has benefited me. As I've found effective communication and the conveying of ideas in a way that aligns two unique personalities is like having a super power and I'm sure if harnessed correctly it can be used to conquer the world.</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-36701518310505986792018-09-27T10:30:00.000-04:002018-09-30T10:00:37.808-04:00HTTP BIN - Developer Tools<div class="WordSection1">
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJ9iNuTJXXRxvnKo1miaZ3zq5Cz8oLXqirr7SIMO-gD6uxLMUfFvSnZLfgZBZuscaV9rz8uMq0433o1kBXy5yO94JR7ZuQoS-IQWz_BF-6swFYNWTVtQKTYkqgkfjeQRJejBK_uV8rSA/s1600/10_in_1_screwdriver.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="259" data-original-width="414" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgDJ9iNuTJXXRxvnKo1miaZ3zq5Cz8oLXqirr7SIMO-gD6uxLMUfFvSnZLfgZBZuscaV9rz8uMq0433o1kBXy5yO94JR7ZuQoS-IQWz_BF-6swFYNWTVtQKTYkqgkfjeQRJejBK_uV8rSA/s320/10_in_1_screwdriver.jpg" width="320" /></a></div>
<div class="MsoNormal">
One of my favorite tools in my 10 in 1 screwdriver. The appeal is that in a single tool, just by flipping some pieces around you have just what you are looking for. In many minor jobs around the house I can do everything needed just with this single tool.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
When writing software you can find similar valuable tools and one such valuable tool is <a href="http://httpbin.org/" target="_blank">http://httpbin.org</a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 11pt;">Like with most tools, the simplicity can be </span><span style="font-size: 14.6667px;">deceptive because how hard could it be to have an API that just echo's back what you sent. But then that is what is so great about httpbin, it's done and it's very robust.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">By way of example, when building a front-end you may find that the API isn't complete and thus you want to "stub out" the calls. With httpbin you can send a call such that it echo's back what you want and thus you are wiring up to an actual HTTP call.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">On the server side you might have the same need to wire up to a service that isn't something you are allowed to call from your local machine, but with httpbin you have the means of mocking with an actual HTTP call.</span></div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-84884581834690888572018-09-20T10:30:00.000-04:002018-09-20T10:30:12.338-04:00Using telnet to troubleshoot connectivity.... and watch Star Wars<div class="WordSection1">
<div class="MsoNormal">
So the teaser I'll lead off with is, at the end of this post you'll know how to watch Star Wars A New Hope in ASCII art form (i.e. text based graphics)... So let's begin.<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN6V4oder0z-3xmDt1tNIxzJhsv6NK3xUBZ3KP_KiPdbKUJ5kJl_sRQdEGRGmYgxuEh9X50MglUoWZNPvHcfWr_P-o27XWX6e1MASypG8tpB7ChtbFBczFcmD68Zb771rYXZWisZJnMaA/s1600/watching-star-wars-cmd-4telnet.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="340" data-original-width="676" height="201" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiN6V4oder0z-3xmDt1tNIxzJhsv6NK3xUBZ3KP_KiPdbKUJ5kJl_sRQdEGRGmYgxuEh9X50MglUoWZNPvHcfWr_P-o27XWX6e1MASypG8tpB7ChtbFBczFcmD68Zb771rYXZWisZJnMaA/s400/watching-star-wars-cmd-4telnet.jpg" width="400" /></a></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
Recently I found myself working on a legacy application such that I had to redeploy the multi-node application into in Infrastructure running in Azure. Two of the models communicate via a WCF binding over net.tcp. While I was operating under the impression that the firewall had been opened up to allow the communication I was a bit stuck on how to validate that the communication was working. So I wandered up to the networking area to chat with our Network Architect. As I often find, chatting with those who have an expertise different than your own requires patience and effort in the area of translation. Even though we both work in the IT field we each have our jargon to deal with, but the price of admission is well worth it.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
In just a few minutes of explaining my challenge I had been provided with an excellent means of confirming that, from a networking perspective, communication was possible. Enter telnet. <a href="https://en.wikipedia.org/wiki/Telnet" rel="" target="_blank">Telnet</a>, if you may not know is a protocol that has come and gone in terms of it's heyday. Also to be clear, telnet is NOT secure and should NOT be left running, but in our case it's helpful as a tool for a short period of time.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
As originally stated I need to confirm communication via net.tcp between two nodes in a network was working, so how can one accomplish this "easily", well what we want to do is emulate the communication, so you can use telnet on the same port as the net.tcp listener and if you get a blank screen you've got connectivity. When a telnet client calls out to the target server over a port that is listening for traffic, say for an HTTP or NET.TCP request the response will come back and the telnet client won't know what to do other than show a blank screen. BUT it proves that the communication is working on that port. So the primary question is answered.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
So to the example of how this work and on to watching Star Wars.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b>Enable Telnet Client</b></div>
<div class="MsoNormal">
<i>BE SURE TO DISABLE TELNET WHEN YOU ARE DONE WHICH I'LL MENTION AT THE END.</i></div>
<div class="MsoNormal">
<i><br /></i></div>
<div class="MsoNormal">
- Open a PowerShell command as Admin</div>
<div class="MsoNormal">
- Enter the command<br />Enable-WindowsOptionalFeature -Online -FeatureName "TelnetClient"</div>
<div class="MsoNormal">
- Close PowerShell</div>
<div class="MsoNormal">
- Open command prompt</div>
<div class="MsoNormal">
- Enter the command replacing your info as needed</div>
<div class="MsoNormal">
Telnet [IP or DNS] [Port for net.tcp listener]</div>
<div class="MsoNormal">
Example: Telnet google.com 443</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
If you get a blank screen then an application is listening on the target port and communication is possible via NET.TCP (or HTTPS, etc).</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
if you get the error "Could not open connection to the host, on port xxx: connect faild" then you might need to go back to the Firewall to see if something else is blocking.</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b>What about Star Wars</b></div>
<div class="MsoNormal">
As promised, if you have enabled telnet and are done troubleshooting you can check out Star Wars via telnet by opening a telnet connection as follows.<br /><br />telnet towel.blinkenlights.nl</div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<b>Disable Telnet Client</b></div>
<div class="MsoNormal">
- Open a PowerShell command as Admin</div>
<div class="MsoNormal">
- Enter the command</div>
<div class="MsoNormal">
Disable-WindowsOptionalFeature -Online -FeatureName "TelnetClient"</div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-48521698519962953402018-09-13T10:30:00.000-04:002018-09-13T10:30:12.322-04:00Talk to the Rubber Duck<div class="WordSection1">
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjABQC_yUTT3xyYT4-JZH1WRuc6R18Wt7p9gRNDqf0f7qju39LoT0b-Mvjrh4_nP-_J9-C5UK6_BU0TJonj5UnooDMpGqX7r9n7WpgrG6C3IsGq1Y5hiIq2G_tMh-bz_zlZ0AYkCObLHd4/s1600/640px-Rubber_duckies_So_many_ducks.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" data-original-height="480" data-original-width="640" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjABQC_yUTT3xyYT4-JZH1WRuc6R18Wt7p9gRNDqf0f7qju39LoT0b-Mvjrh4_nP-_J9-C5UK6_BU0TJonj5UnooDMpGqX7r9n7WpgrG6C3IsGq1Y5hiIq2G_tMh-bz_zlZ0AYkCObLHd4/s320/640px-Rubber_duckies_So_many_ducks.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">*See attribution of image at the bottom.</td></tr>
</tbody></table>
<span style="font-size: 14.6667px;">One of the greatest tricks I have had the pleasure of participating in is that of helping someone solve a problem simply by listening. I'm sure there is a more accurate description of this phenomenon, but in the world of programming it's called <a href="https://en.wikipedia.org/wiki/Rubber_duck_debugging" target="_blank">Rubber Duck Debugging</a>. I was first introduced to this idea from listening to <a href="https://en.wikipedia.org/wiki/Jeff_Atwood" target="_blank">Jeff Atwood</a> podcasts/interviews as well as reading his blog under <a href="https://blog.codinghorror.com/">CodingHorror.com</a> he wrote about the topic under the title <a href="https://blog.codinghorror.com/rubber-duck-problem-solving/">Ruber Duck Problem Solving</a>.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">Why the term Rubber Duck? Really it has nothing to do with the rubber duck, the intent is to encourage someone to solve their own problems by working through the very difficult challenge of describing what the problem actually is. It is often surprising to people when they discover that simply the act of attempting to describe a problem helps them to find the answer they were looking for.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">So my approach to assist others is by asking questions that I often ask myself to help them work through the Rubber Duck process. For example if a developer where to ask me to help them with a particular bug the questions I ask them are seemingly obvious, but surprisingly, their answering them can often lead to an answer. </span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">So what type of questions should you ask? The most obvious is "what is the problem" this question alone can often help you find the root of the issue and resolve the problem. Let's demonstrate this by way of a contrived example.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">A developer is having a problem with her application communicating with a third party API service. So that is the "obvious" problem, but now comes the next question, are you ready... "why is that problem occurring?" </span><br />
<span style="font-size: 14.6667px;">So how can the developer answer this question? Debugging is a great place to start. A great place to start is by attempting to reproduce the issue locally. It's worth noting that in our example this doesn't result in re-producing the issue found on the sever. Now in some cases, such as when the developer isn't permitted to remotely access the server being impacted, there is still much that has been found. How so? We now know that the application is NOT the issue, nor is the API service broken. This points to an environmental issue. So even when you can't reproduce the bug locally you obtain more information. In our derived example the developer now has facts that he can presented to other IT engineers such as networking, security or even server admins to engage with in a meaningful conversation to solve the problem.</span><br />
<span style="font-size: 14.6667px;"><br /></span>
<span style="font-size: 14.6667px;">Another interesting side effect of engaging in this approach is that you will find you have a broader understanding of how systems connect and interact. Additionally your "Google Fu" is improved as well as you can key in on the specific phrases related to your problem. This is an excellent skill to develop and when you find yourself in the position of the rubber duck you can ask the right questions to help someone else solve their own problem.</span><br />
<br />
So go be a rubber duck.<br />
<span style="font-size: 14.6667px;"><br /></span></div>
<span style="font-size: 11px;">*By <a class="external text" href="https://www.flickr.com/photos/gaetanlee/" rel="nofollow">gaetanlee</a> - <a class="external free" href="https://www.flickr.com/photos/gaetanlee/298160434/" rel="nofollow">https://www.flickr.com/photos/gaetanlee/298160434/</a>, <a href="https://creativecommons.org/licenses/by/2.0" title="Creative Commons Attribution 2.0">CC BY 2.0</a>, <a href="https://commons.wikimedia.org/w/index.php?curid=1456754">Link</a></span>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-26587192083442617202018-09-06T10:30:00.000-04:002018-09-30T10:11:05.322-04:00Example of using LazyInitializer.EnsureInitialized<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYPJcBNDFxHq024P3sFWbzId2xw1H5xAF6mTFaSI8-pDIef5iOKXwmMkohwk4K6hjHkrEmCf4EarX3KPVrpgx_0at1Y6IJlWK7k8Tzqcufw1VEBTyw_OxSKOIMPFD9BkeErfYyHQbAT58/s1600/LazyMeme.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="443" data-original-width="620" height="228" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjYPJcBNDFxHq024P3sFWbzId2xw1H5xAF6mTFaSI8-pDIef5iOKXwmMkohwk4K6hjHkrEmCf4EarX3KPVrpgx_0at1Y6IJlWK7k8Tzqcufw1VEBTyw_OxSKOIMPFD9BkeErfYyHQbAT58/s320/LazyMeme.jpg" width="320" /></a></div>
When looking at making systems more efficient it's helpful to think about being lazy. A helpful tool in the .NET tool belt is the static class under the System.Threading namespace LazyInitializer. In particular this class contains a method <a href="https://docs.microsoft.com/en-us/dotnet/api/system.threading.lazyinitializer.ensureinitialized?view=netframework-4.7.1" target="_blank">EnsureInitialized</a><br />
<br />
This method is very simple to use and provides a convenient way to ensure that an initialization is called only once based on the value of the target property already being populated.<br />
<br />
For example, if you need to load a file as part of the setting of values in an application you can use the EnsureInitialized method.<br />
<br />
The following is a derived example of using the class to illustrate the usage pattern.<br />
<br />
If you are having trouble viewing the below code you can use this link to view the gist github.
<a href="https://gist.github.com/briannipper/ac2778ccd0d15b4ab217083331419ae7" target="_blank">https://gist.github.com/briannipper/ac2778ccd0d15b4ab217083331419ae7</a>
<br />
<textarea cols="90" rows="49" style="display: none;">using System;
using System.Collections.Generic;
namespace Example.EnsureInitialized
{
class Program
{
static void Main(string[] args)
{
var configurationService = new ConfigurationService();
var configInfo = configurationService.ConfigInfo();
foreach(var configItem in configInfo)
{
Console.WriteLine(configItem.Value);
}
Console.ReadKey();
}
}
class ConfigurationService
{
private Dictionary<long, string> _simpleExample;
public ConfigurationService()
{
System.Threading.LazyInitializer.EnsureInitialized(ref _simpleExample, Init);
}
private Dictionary<long, string> Init()
{
// The following would be replaced with some expensive operation like reading a file from disk.
return new Dictionary<long, string>
{
{1, "Hello"},
{2, "World"}
};
}
public Dictionary<long, string> ConfigInfo()
{
return _simpleExample;
}
}
}
</textarea>
<script src="https://gist.github.com/briannipper/ac2778ccd0d15b4ab217083331419ae7.js"></script>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-52355009574275708862018-08-30T10:30:00.000-04:002018-08-30T10:30:03.882-04:00Automate Work and Life with IFTTT and Office 365 Flow<div class="WordSection1">
<div class="MsoNormal">
<div style="text-align: right;">
</div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVeXoigCs0n2kkAyA8Em9Bf3NvlA16FeLcqLJuJ-FJYRbly70k27HWqkAj2ApG8dS21PTna0iSGLJzkqhnPwBgrwRv-Er5OJWZt1Z5XJUZsOFmypIzenNDp9NBOq2206KGXYvw-pLDME/s1600/Screen+Shot+2018-08-23+at+2.27.39+PM.png" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="720" data-original-width="1004" height="229" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgZVeXoigCs0n2kkAyA8Em9Bf3NvlA16FeLcqLJuJ-FJYRbly70k27HWqkAj2ApG8dS21PTna0iSGLJzkqhnPwBgrwRv-Er5OJWZt1Z5XJUZsOFmypIzenNDp9NBOq2206KGXYvw-pLDME/s320/Screen+Shot+2018-08-23+at+2.27.39+PM.png" width="320" /></a></div>
<span style="font-size: 14.6667px;">I'm a huge fan of automation for situations where I find myself doing something mindlessly over and over again, like punching a clock. The way I approach these problems is to find a way to eliminate some portion of the task and iterate till it just happens on it's own.</span></div>
<div class="MsoNormal">
<br /></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">To avoid confusion, when I say punching a clock what I mean is knowing a rough approximation of how long I worked on a given day so that when I need to put in my "billable vs. non-billable" time at the end of the week I have a rough idea of how much time I spent on working each day. As such the way I "manually" accomplished this was putting the time I arrived at work and the time I left into a spread sheet.</span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">So, step one, avoid having to open excel to enter the information. This was easy using a feature of Office 365 called <a href="https://us.flow.microsoft.com/en-us/" target="_blank">Flow</a>. It's an application that smells very similar to the populate If This Then That site (a.k.a. <a href="http://ifttt.com/">IFTTT.com</a>). Flow makes it easy to setup operations that interact with other parts of Office 365, such as creating files in OneDrive based off of attachments in an e-mail, creating reminders in Outlook, even putting info into a spreadsheet.</span></div>
<div class="MsoNormal">
<span style="font-size: 11.0pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">Quick aside, Microsoft is bad at naming things, like really bad. In the case of Flow it's both the application as well as an instance of an activity that you create. So going forward when I say I created a "Flow" I mean I created an activity within the application Flow... right, bad at naming things... but I digress.</span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">All flows are comprised of at least two parts. An event/trigger and an action. For example, I could create a flow which would be described as follows...</span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">Every time I receive an e-mail (i.e. trigger/event) take all attachments on the e-mail and place them in OneDrive under a folder with the same name as the "from" e-mail address (i.e. action taken).</span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">Pretty handy. </span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;">So in my case, the action was pretty easy, put a row of data in a spread sheet. But what would be my trigger? After some digging I landed on an interesting feature of Flow the application. Along with the Web Site/App up in the Office 365 subscription there is a mobile application you can install on any mobile device. Along with that you can create a "button" which can act as a trigger, so right from your phone you just tap and the trigger is fired. It has the added bonus of providing GPS data, if you chose, which can also be embedded in the flow for use in the action. So now my flow could be described as..</span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;">Every time I press a button in the mobile Flow App on my device (i.e. trigger/event) put a row of data in a spread sheet I specify that includes the time the flow started to represent when I start/end work along with the GPS of where I pressed the button (i.e. action taken)</span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 14.6667px;">At first I thought this was great and wonderful and was impressed that I had done all of this in the course of a few hours. </span><span style="font-size: 11pt;">However, after the novelty wore off I found that often I would forgot to press the button, and per my original goal I was still mindlessly doing something, even if it was a much smaller process.</span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;">Enter IFTTT. IFTTT is probably also something that an enterprise could use; however, I most often think of it as a consumer service. IFTTT has a much easier way to describe creating activities, which they refer to as </span><span style="font-size: 14.6667px;">recipes</span><span style="font-size: 11pt;">. These recipes have the same "ingredients" as a flow. A trigger followed by an action. I should mention that Flow seems to be easier to customize as well as to support more extensive chained activities, but I digress. IFTTT also has a mobile app and, unlike flow, it supports GEO-Fencing, or the idea of a trigger based on entering or exiting a set of geo coordinates.</span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;"><br /></span></div>
<div class="MsoNormal">
<span style="font-size: 11pt;">I had already been using IFTTT for my "personal" automation projects. As such I had already had been using IFTTT to trigger an SMS to my lovely wife when I arrived at work or when I was heading out. In hindsight I'm wondering why this didn't hit me right away, but simply forwarding the SMS I sent to my spouse as an e-mail to my work address could be the I needed for the FLOW.</span></div>
<div class="MsoNormal">
<span style="font-size: 11.0pt;"><o:p><br /></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 11.0pt;"><o:p>So by "coupling" IFTTT and FLOW I was able to get the best of all worlds. I just go about my business and my spread sheet is updated for me. I even left the button flow in place so that when I work remote I can still keeping things down to a single button press and move on.</o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 11.0pt;"><o:p><br /></o:p></span></div>
<div class="MsoNormal">
<span style="font-size: 11.0pt;"><o:p>What type of activities would like to automate in your day to day routine?</o:p></span></div>
</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-41864445791491241672018-08-23T10:00:00.001-04:002018-08-30T10:27:50.985-04:00Fire in London helped preserve the city of Savannah GA through the modern age<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right; width: 405px;"><tbody>
<tr><td style="text-align: center;"><a href="https://upload.wikimedia.org/wikipedia/commons/4/41/A_view_of_Savannah_as_it_stood_the_29th_of_March_1734.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img alt="A view of Savannah as it stood the 29th of March 1734" border="0" data-original-height="641" data-original-width="800" height="320" src="https://upload.wikimedia.org/wikipedia/commons/4/41/A_view_of_Savannah_as_it_stood_the_29th_of_March_1734.jpg" title="A view of Savannah as it stood the 29th of March 1734" width="400" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: left;">By Pierre Fourdrinier and James Oglethorpe<br />
[Public domain or Public domain], via Wikimedia Commons</td></tr>
</tbody></table>
<div style="text-align: left;">
Once upon a time, before my wife and I had kids, we visited the city of Savannah, GA. We had the opportunity to take a carriage ride through some of the most oldest portions of the planned city. A detail of the tour that has stuck out in my mind was how much of the original street remained unchanged. The reason this stuck out was, as I had found in visiting a few other historic locations on the east cost of the US, many locations as old, if not older, had to be altered to accommodate motor vehicles. So why was that not the case for the planned city of Savannah GA? Because of fires in London. Huh?<br />
<br />
The founder of Savannah was <a href="https://en.wikipedia.org/wiki/James_Oglethorpe" target="_blank">James Oglethorpe</a>. Born in England in 1696, he would have been familiar with the fires that ravaged that part of the world in 1666. The <a href="https://en.wikipedia.org/wiki/Great_Fire_of_London" target="_blank">great fire of London</a> burned through much of the city due to many factors, one of which was the way homes were built, basically right up against one another. Out of that fire a new approach to city building came into fashion that of having easements between homes to help avoid the spread of fire.<br />
<br />
This fascinated me as it turned out that in attempting to address the concern of fire by spacing out plots of lands and having larger pathways between the homes it resulted in a design that allowed the original layout to survive, more or less, down to our modern age.<br />
<br />
As time progressed and the advent of items such as cars came along Savannah found it self having plenty of room to allow cars to flow in both directions, for sidewalks to be put in, for construction of sewers and electricity to be distributed all without the need to tear down or reroute the flow of movement.<br />
<br />
Understanding the chain of events that caused choices to be made can be one of the most rewarding results in study of history.<br />
<br />
So dear reader, what historical tidbits have captured your interest?</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-64391240220410645272018-08-16T10:00:00.000-04:002018-08-18T16:56:29.692-04:00Creating a DSC module to install Oracle Client and disable enable UACYou ever get a task and think, how hard can this be? Then you begin down what turns into a seemingly never ending journey.<br />
<br />
Welcome to mixing old and new technologies.<br />
<br />
I found myself in the position of needing to install the Oracle Client on a Windows VM running in Azure using Desired State Configuration (a.k.a. DSC) and, well, let's just say it was an interesting journey.<br />
<br />
Listed directly after this is the snippet of the DSC which I'm posting here in hopes that others who have a similar need may stumble across this and save themselves from headache.<br />
<br />
I'll provide a break down of the major pieces. I have intentionally left the logging pieces in the script so that any who would be so bold as to cut and paste without reading over at least have a log to dig into.<br />
<br />
A few important prerequisites to using this script.<br />
<br />
<ul>
<li>You'll need a DSC module that downloads the Oracle Client Package, the one I used was for 11gR2 and includes an answer file for the client.</li>
<ul>
<li>These items will be specific to your situation.</li>
</ul>
<li>Your Local Configuration Manager (a.k.a. LCM) should be set to allow DSC to reboot.</li>
<li>This script WILL disable UAC and if for some odd reason after the reboot the script did NOT continue running UAC is LEFT in a disabled state...</li>
</ul>
<div>
<span style="color: #cc0000;"><b>!! WARNING !! UAC SHOULD NOT BE LEFT DISABLED</b></span></div>
<div>
Be sure you understand what this script is doing and how to diagnose the state of the VM once the script runs.</div>
<br />
<br />
<br />
<div style="background-color: #1e1e1e; color: #d4d4d4; font-family: Menlo, Monaco, "Courier New", monospace; font-size: 12px; line-height: 18px;">
<div>
Script InsallOracleWithAnswerFile {</div>
<div>
TestScript = {</div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oraclePathTest</span> = <span style="color: #dcdcaa;">Test-Path</span> HKLM:\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span> = <span style="color: #dcdcaa;">Get-ItemProperty</span> -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #c586c0;">if</span> ((<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oraclePathTest</span>) -and (<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span><span style="color: #dcdcaa;">.EnableLUA</span> -eq <span style="color: #b5cea8;">1</span>)) {</div>
<div>
<span style="color: #c586c0;">return</span> <span style="color: #569cd6;">$True</span></div>
<div>
}</div>
<div>
<span style="color: #c586c0;">else</span> {</div>
<div>
<span style="color: #c586c0;">return</span> <span style="color: #569cd6;">$False</span></div>
<div>
}</div>
<div>
}</div>
<div>
SetScript = {</div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">continueProcessing</span> = <span style="color: #569cd6;">$True;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logTimestamp</span> = <span style="color: #dcdcaa;">Get-Date</span> -Format yyMMddHHmm<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logPath</span> = <span style="color: #ce9178;">"C:\MyFolder\OracleInstallStatus"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> = <span style="color: #ce9178;">"</span><span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logPath</span><span style="color: #ce9178;">\install-</span><span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logTimestamp</span><span style="color: #ce9178;">.log"</span><span style="color: #569cd6;">;</span></div>
<div>
</div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Begin Overall Oracle Install With Awnser --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Opening - Get Curernt UAC VALUE --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span> = <span style="color: #dcdcaa;">Get-ItemProperty</span> -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"UAC Reg Key:"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span><span style="color: #569cd6;">;</span></div>
<br />
<div>
<span style="color: #c586c0;">if</span> (<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span><span style="color: #dcdcaa;">.EnableLUA</span> -eq <span style="color: #ce9178;">"1"</span>) {</div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Change UAC to disable (i.e. 0) --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Set-ItemProperty</span> -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA -Value <span style="color: #b5cea8;">0</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Set Global Falg to trigger Reboot --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$global</span>:<span style="color: #9cdcfe;">DSCMachineStatus</span> = <span style="color: #b5cea8;">1</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">continueProcessing</span> = <span style="color: #569cd6;">$False;</span></div>
<div>
}</div>
<br />
<div>
<span style="color: #c586c0;">if</span> (<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">continueProcessing</span>) {</div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Begin Check for Oracle Install --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oracleRegPath</span> = <span style="color: #ce9178;">"HKLM:\SOFTWARE\Wow6432Node\ORACLE\KEY_OraClient11g_home1"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"Oracle Reg Path:"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oracleRegPath</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oraclePathTest</span> = <span style="color: #dcdcaa;">Test-Path</span> <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oracleRegPath</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"Results of Testing Reg Path"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oraclePathTest</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #c586c0;">if</span> (<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oraclePathTest</span> -eq <span style="color: #569cd6;">$False</span>) {</div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">params</span> = <span style="color: #ce9178;">"-silent -nowelcome -noconsole -waitforcompletion -noconfig -responseFile C:\MyFolder\OraclePackage\Oracle11gClientx86\11g\x86\client\response\client_030514.rsp"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oracleClientExe</span> = <span style="color: #ce9178;">"C:\MyFolder\OraclePackage\Oracle11gClientx86\11g\x86\client\setup.exe"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"--- Starting Oracle Install ---"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Start-Process</span> -FilePath <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">oracleClientExe</span> -ArgumentList <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">params</span> -Wait -Passthru<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"--- Finish Oracle Install ---"</span><span style="color: #569cd6;">;</span></div>
<div>
}</div>
<div>
<span style="color: #c586c0;">else</span> {</div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"Oracle Reg Key was found so NOT running install."</span></div>
<div>
}</div>
<br />
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Secondary - Get Current UAC Value --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span> = <span style="color: #dcdcaa;">Get-ItemProperty</span> -Path HKLM:\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA<span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"UAC Reg Key:"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #c586c0;">if</span> (<span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">regVal</span><span style="color: #dcdcaa;">.EnableLUA</span> -eq <span style="color: #ce9178;">"0"</span>) {</div>
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Change UAC to enable (i.e. 1) --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #dcdcaa;">Set-ItemProperty</span> -Path registry::HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System -Name EnableLUA -Value <span style="color: #b5cea8;">1</span><span style="color: #569cd6;">;</span></div>
<div>
}</div>
<br />
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- Set Global Falg to trigger Reboot --"</span><span style="color: #569cd6;">;</span></div>
<div>
<span style="color: #569cd6;">$global</span>:<span style="color: #9cdcfe;">DSCMachineStatus</span> = <span style="color: #b5cea8;">1</span><span style="color: #569cd6;">;</span></div>
<div>
}</div>
<br />
<div>
<span style="color: #dcdcaa;">Add-Content</span> -Path <span style="color: #569cd6;">$</span><span style="color: #9cdcfe;">logFile</span> -Value <span style="color: #ce9178;">"-- FINISH Overall Oracle Install with Answer --"</span></div>
<div>
}</div>
<div>
GetScript = {<span style="color: #569cd6;">@</span>{<span style="color: #9cdcfe;">Result</span> = <span style="color: #ce9178;">"InsallOracleWithAnswerFile"</span>}}</div>
<div>
DependsOn = <span style="color: #ce9178;">"[Archive]OraclePackageExtract"</span></div>
<div>
}</div>
</div>
<br />
<h3>
Test Script</h3>
<div>
In short the test script is confirming two things.</div>
<div>
<ol>
<li>Is the Oracle Client installed based on the expected registry key being present.</li>
<li>Is UAC in the ENABLED state, also checked by looking at the expected registry key value.</li>
</ol>
<div>
If either of these conditions are FALSE there is a need to run the set script.</div>
</div>
<div>
<br /></div>
<h3>
Set Script</h3>
<div>
This is where it gets <strike>hairy</strike> interesting.</div>
<div>
I'll skip commenting on the logging as it should be clear what the logs are doing, an interesting point about the way the logging is done is that it can indicate how many times this script is run since the log is written to a file with a date time stamp as the name which I found handy since I put myself into an infinite loop a few times.</div>
<div>
<br /></div>
<div>
Since I'll have to essentially provide myself a circuit breaker I set a continue flag at the start that I can use later on.</div>
<div>
<br /></div>
<div>
Due to the way the Oracle Installer works, even WITH the answer file you'll still get a UAC prompt before you can begin the install, thus the first part of this set script will obtain the value of the UAC via a registry call.</div>
<div>
<br /></div>
<div>
Once I have the UAC value I check to see the state of the value, in the case where it is ON (i.e. 1) I want to disable it so I change the registry value, also setting my continue flag to false and set the environment variable to tell DSC to reboot after this script is completed. Namely...<br />
$gobal:DSCMachineStatus = 1;</div>
<div>
<br /></div>
<div>
At this point I'm checking my flag to ensure that I SKIP attempting to install the oracle client, this is because even thought we updated the registry it does go into effect until we reboot and thus no need to run the Oracle Installer.</div>
<div>
<br /></div>
<div>
So we log that we can't install the oracle client and continue on.</div>
<div>
<br /></div>
<div>
The next bit also results in NOT applying changes since the UAC value in the registry is technically STILL 1 because UAC isn't ACTUALLY persisted until reboot.</div>
<div>
<br /></div>
<div>
I am being sloppy at the end and RESETTING the DSCMachineStatus. Meh.</div>
<div>
<br /></div>
<div>
So now we reboot.</div>
<div>
<br /></div>
<div>
Now running through the script a second time AFTER the reboot we will be left in a state where the UAC IS disabled but we DO NOT have the Oracle Client installed, so when we run through the set script the oracle install WILL occur.</div>
<div>
<br /></div>
<div>
We finish out the second run by enabled UAC and another reboot.</div>
<div>
<br /></div>
<div>
When the system comes up on the third time UAC is ENABLED and Oracle Client is installed.</div>
<div>
<br /></div>
<div>
Do please let me know if you run into issues with this script in the comments.</div>
Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-21164637759403588152018-08-09T17:47:00.000-04:002018-08-18T16:56:08.903-04:00Resilient Scripting is scripting that can be rerun... safely<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuCD6GUAXNKmEOqmXKxloMYMKEulz2H_Yv_9KNftl4GY_hGLQbQSjd5Tbf7Fs7xOhpfu5DEMLLSXKpuTjPV2HPbleuwUl5NePuSFkjLho1OCdl2HQga6ensJBiYmpmfoKOROw24mGEHos/s1600/saftey-first.jpg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em; text-align: center;"><img border="0" data-original-height="381" data-original-width="315" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjuCD6GUAXNKmEOqmXKxloMYMKEulz2H_Yv_9KNftl4GY_hGLQbQSjd5Tbf7Fs7xOhpfu5DEMLLSXKpuTjPV2HPbleuwUl5NePuSFkjLho1OCdl2HQga6ensJBiYmpmfoKOROw24mGEHos/s320/saftey-first.jpg" width="264" /></a><br />
Making a script that is resilient can mean many different things to different people, IMHO an important one is to be able to re-run a script "safely". By safely I mean to minimize side effects and to prevent negative consequences.<br />
<br />
To illustrate let's say we have an install process and we need to log details about what happens when we run the install.<br />
<br />
To keep this simple let's just focus on the logging requirement.<br />
<br />
We want a log file that we can look at when an install happens. So a simple approach would be as follows.<br />
<br />
<span style="background-color: blue; color: white; font-family: "arial" , "helvetica" , sans-serif;">Set-Content log.txt "Information about Install"</span><br />
<br />
Nice and simple, we have satisfied the requirement. But let's see if we can make this one liner more resilient.<br />
<br />
<div style="text-align: left;">
<span style="background-color: blue; color: white; font-family: "arial" , "helvetica" , sans-serif;">$logFileTime = Get-Date yyMMddhhmmss</span></div>
<div style="text-align: left;">
<span style="background-color: blue; color: white; font-family: "arial" , "helvetica" , sans-serif;">$logFileName = $logFileTime + "_log.txt"</span></div>
<div style="text-align: left;">
<span style="background-color: blue; color: white; font-family: "arial" , "helvetica" , sans-serif;">Set-Content $logFileName "Information About Install"</span></div>
<div style="text-align: left;">
<span style="font-family: "arial" , "helvetica" , sans-serif;"><br /></span></div>
<span style="font-family: "times" , "times new roman" , serif;">Now even if we run this install multiple times we will have a script for each instance of the install even when it happens on the same day during the same minute. Further more an interesting side effect of making a script more resilient is that we know can see how many times this install is run because we have a file for each instal attempt. So the benefits of making it more resilient compound.</span><br />
<span style="font-family: "times" , "times new roman" , serif;"><br /></span>
<span style="font-family: "times" , "times new roman" , serif;">I hope this simple example helps you dear reader see how taking a second pass at making a script more resilient, even a one liner can benefit from a second pass. </span><br />
<br />
<br />Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.comtag:blogger.com,1999:blog-991446691792157231.post-10457307749550216942018-08-02T13:42:00.001-04:002018-08-02T13:42:47.605-04:00Dogfooding is important for business policies as well<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHBundf6F9m6kMl5uX17LFzrBaw-GsZzabmMcKWJXTAPoIaBQ5kqgUGUqmOYLmU5Bh-BAK_FyyXmqLXCPvK6SozROAcjXMfZ6yilNV-jpLD7RhCkkbm0UTPU_RX-fIpS0lGeEWPz4M7fk/s1600/DogDish.jpeg" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" data-original-height="1200" data-original-width="1600" height="240" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgHBundf6F9m6kMl5uX17LFzrBaw-GsZzabmMcKWJXTAPoIaBQ5kqgUGUqmOYLmU5Bh-BAK_FyyXmqLXCPvK6SozROAcjXMfZ6yilNV-jpLD7RhCkkbm0UTPU_RX-fIpS0lGeEWPz4M7fk/s320/DogDish.jpeg" width="320" /></a></div>
Perhaps you are unfamiliar with the term "dogfooding", in short it is the idea that a company or organization use its own Product or Service in addition to providing it to the others. A more complete definition can be found on Wikipedia under <a href="https://en.wikipedia.org/wiki/Eating_your_own_dog_food" target="_blank">Eating your own dog food</a>.<br />
<br />
The reasons a group might chose to dogfood are varied, but an important reason is to ensure that they are familiar with the challenges with using the good or service, or to put it in business jargon... they want to find opportunities to make, what they make, better.<br />
<br />
For groups that are just starting to do this it can be EYE OPENING what their customers/patrons are dealing with to use their stuff. Often the overall impact is great and everybody wins. So why not do this for policies within, let's say an IT organization. How would one go about dogfooding a policy you may ask? Thanks for asking... let me tell ya what I think.<br />
<br />
For any organization to be successful there needs to be consistency in the way it approaches work. This is especially true for IT groups. The term consistent and repeatable is often spoken when discussing how to approach various aspects of the IT assembly line. At times the way to achieve this goal is to determine a policy that governs the way IT associates do their work. Examples of this could be found in policies about documenting changes, how to request access to a system. You can see this even outside of IT, such as when a communications department issues a corporate policy on how to setup your e-mail signatures.<br />
<br />
So back to the point I was making, it can be of GREAT benefit if the ones making the policy are sure to follow their own policy to ensure they are not creating any undo burden on those that the policy is enforced on. This can best be illustrated with a concrete example. Let's look at having a source code repository based on the GIT system with a Pull Request policy...<br />
<br />
Now, most GIT systems have the concept of a branch policy that permits the owner to require a Pull Request to merge changes along with some level of approvers and perhaps even all comments to be resolved and a CI build to complete successful. If the corporate policy is to have this as the branch policy it stands to reason that even repos for the said owners should also have this policy. So why wouldn't they?<br />
<br />
This is why a slippery slope mindset can occur and what can wind up causing groups to NOT dogfood their own policy. Further along our example, the policy maker has a repo which only he uses, so no reason to have a PR model, right I mean who is going to approve it if he's the only one working on the repo? This is where the real benefit of dogfooding the policy comes into play. Right off the bat it will require the policy maker to grasp the need of doing one of two things.<br />
<br />
The first option would be to create an addendum to the policy which lifts the branch policy in terms of self review or having any reviews at all, but perhaps they still need to create a CI build which would again be ideal and help ensure the intent of the policy stick, i.e. that the intent of the policy is to have repos which are of high quality and the CI build on the PR prevents the master branch from being in a "unbuildable" state.<br />
<br />
The second option, and the one I personally prefer, the policy owner would need to invite someone into the repo to do reviews thus further ensuring that policy is more fully adopted.<br />
<br />
So if you find yourself in a position of setting policy it is helpful for all involved, including you dear policy maker, to adhere to the policy yourself. Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com4tag:blogger.com,1999:blog-991446691792157231.post-46751093762285724562012-11-06T16:05:00.000-05:002012-11-06T16:05:46.600-05:00There is NEVER one person working on your code<em>Alternate Title: Avoid “Black Boxes” and “Works on my Machine”</em><br />
<br />
<div class="separator" style="clear: both; text-align: center;">
<br /></div>
<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0aKNwIJe3F-NOJ6lXMbvKtjpMiIkjU_XFPh9sFw9uKsrGGearMuiHh3s6dpXz3BfKP13HW2NLPKvL_z5aA-Wk51TalBGp3uZks2rZoMFpegOX9o4qlmQMPIEetIFVaTX-rQIS9z_yYug/s1600/blackbox.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEg0aKNwIJe3F-NOJ6lXMbvKtjpMiIkjU_XFPh9sFw9uKsrGGearMuiHh3s6dpXz3BfKP13HW2NLPKvL_z5aA-Wk51TalBGp3uZks2rZoMFpegOX9o4qlmQMPIEetIFVaTX-rQIS9z_yYug/s200/blackbox.png" width="192" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBT9mjQVa2iwP4iNBsl9w0EFVbfetTFdrpj3mE-1-8P2olu0ZRSokeTgQu6GRsmu6bYF5IbXk-wiUuEEA6XVjxqs4ZJDQE2omtGQOKRjYV_ikia-lxWQxMi1isj8RyMPr8k139zJS4Il0/s1600/works_on_my_machine_sticker-p217270569836645009envb3_400.jpg" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhBT9mjQVa2iwP4iNBsl9w0EFVbfetTFdrpj3mE-1-8P2olu0ZRSokeTgQu6GRsmu6bYF5IbXk-wiUuEEA6XVjxqs4ZJDQE2omtGQOKRjYV_ikia-lxWQxMi1isj8RyMPr8k139zJS4Il0/s200/works_on_my_machine_sticker-p217270569836645009envb3_400.jpg" width="192" /></a>
</div>
Even when working on a project by yourself it is important to try and create a build script that will “fully” build your project with a single click. But, you may be asking, why would I bother with a build script if there is only one person working on the project? Well the reality is that there is NEVER one person that works on a project.<br />
<br />
There may only be one person working on a project at a given point in time, but if the project succeeds (a.k.a. it has additional releases in the future) there will be other developers involved. Either a future developer will work on the project on their own, or additional developers will join in. I’m of the opinion that the latter is far more likely if a build script already exists and those other developers will thank you (as would I) that they have some transparency into how the code should be orchestrated for a deployment or in other words avoid the “black box” problem.<br />
<br />
In addition to just a build script that compiles and perhaps packages for release, a helpful goal that I think a developer should strive for is to attempt to create a package (a.k.a. source code and build script) that can be checked out to any machine and be built immediately. With the caveat that the build tool (a.k.a. nAnt, Bash Script, etc.) is a pre-requisite of building. Alas it’s impossible to have 0 pre-requisites for most build processes, i.e. the OS already has the build tool installed, except for things like a batch file approach to build scripts, which I’m not a fan of. By attempting to achieve this goal a developer helps avoid the “works on my machine” syndrome that is often present when only one or two developers ever work on a project and there is no build script present. It is also VERY helpful for “the new guy” joining the project. I should note that I specifically stated that a developer should “strive” to achieve this single check-out/single click build because often there are some pieces that will require pre-setup or local dependencies to be installed prior to building, such as DB clients or third party plugins. By attempting to achieve the “ever more automated build” goal it can greatly reduce frustration for others down the road.<br />
<br />
One last tip to those diving into build scripts, it is helpful to establish a process where the build script is versioned along with the code base. In a continuous integration environment, ideally, a developer can change the build script and check-in and that will trigger a build to ensure that the change to the script did not in-itself break the build.<br />
<br />Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-37507202715628333422012-10-11T11:53:00.001-04:002012-10-11T11:53:20.263-04:00Help users help themselves with built-in Microsoft toolsCredit to <a href="http://www.hanselman.com/blog/AboutMe.aspx">Scott Hanselman</a> for reminding me of this very helpful tool with his blog post entitled <a href="http://www.hanselman.com/blog/HelpYourUsersRecordAndReportBugsWithTheProblemStepsRecorder.aspx">Helpyour users record and report bugs with the Problem Steps Recorder</a>. Below are the same highlights from Mr. Hanselman’s blog with a few of my own notes as to additional features of this tool.<br />
<br />
When you are technically inclined you tend to get a lot of “support requests” from friends and family. Even at work various colleges may come up with scenarios where they have a problem and would like your assistance with resolving the problem. However, often is the case where the problem is “no-repo” or in normal speak not reproducible, as is often listed next to various items in numerous bug reports. With Windows 7 Microsoft has provided a nice utility that can, hopefully, make it easier for you, the professional geek, to have a user help themselves by being able to provide you with the needed info to reproduce the issue in question.<br />
<br />
The name of this fabulous tool is the <strong>Problem Steps Recorder</strong> (available starting with Windows 7); this little gem is quite straight forward for any user at any expertise level to navigate. The UI only has three buttons, Start Record, Stop Record and Add Comment. I will mention that there are settings having to do with frame captures and location to drop files, but the default of 25 frames would seem to be plenty and once a user clicks Stop Record they are prompted for where they would like to save the results so I would assume that most users will not need to access these settings.<br />
<br />
The shortest way to get to the tool is via the start menu any typing Steps or PSR. The EXTRA LONG way is, Start Menu --> Control Panel --> Troubleshooting --> Get help from a friend (left side of screen) --> Problem Steps Recorder (bottom of screen)<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiteyOC5-nylq_SXikFTmVKoRhd3_jkPS6poqSiMG919Pn4ZgmWxLYhQhAg8CIMwcopfmo4Z8pqTDDvThCw4oUm-S_uLYxf4Blr2zFevBby8KA9CCWUQLD0GgOGz1v6G2eBED8w7gOdSIM/s1600/problem_steps_recorder.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiteyOC5-nylq_SXikFTmVKoRhd3_jkPS6poqSiMG919Pn4ZgmWxLYhQhAg8CIMwcopfmo4Z8pqTDDvThCw4oUm-S_uLYxf4Blr2zFevBby8KA9CCWUQLD0GgOGz1v6G2eBED8w7gOdSIM/s1600/problem_steps_recorder.png" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Problem Steps Recorder<br />available starting with Windows 7</td></tr>
</tbody></table>
<br />
<br />
<br />
<br />
<br />
<br />
I believe the first two buttons speak for themselves, the third button, when pressed, after pressing Start Record, allows the user to create a rectangular area highlighted on the current screen as well as add a comment that will be added to the final results.<br />
<br />
The results are a single MHT file. MHT is short for MIME HTML, which essentially allows a single file to contain both the words and images of a webpage, along with the layout of course. This is then packaged into a ZIP file for easier transport, since the MHT would include the screen shots represented as text the file site can be quite large.<br />
<br />
After the user presses Stop Record then can use the drop down arrow next to the question mark and send the an e-mail with the resulting ZIP file attached, dependent of course on the user having an e-mail client setup on the OS.<br />
<br />
The results contain quite a bit of useful information, the most direct are the screen shots with notations of the actions the user took as well as the order taken, and this can even be viewed as a slide show. Another useful feature is the “Additional Details” section of the report which shows specific program information and more details about the UI elements being interacted with.<br />
<br />
In summary, the PSR tool can be seen as a simple screen capture based on user clicks along with the ability to add notations and detailed results to review later.<br />
<br />
Additional resources:<br />
<a href="http://windows.microsoft.com/en-US/windows7/How-do-I-use-Problem-Steps-Recorder">http://windows.microsoft.com/en-US/windows7/How-do-I-use-Problem-Steps-Recorder</a><br /><br /> <br /><br /> <br /><br /> Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-60781511782144154972012-08-03T11:59:00.002-04:002012-08-03T12:41:46.112-04:00The Deceptive Complex Problem<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0vSqiRvh_M9AoRuVwiiOy0WhRl6M2w6-l8c90WU8yGY95r9mXHzup4PB7vyYqeBIQmsWBIyYYzXE98ahktJO9WjC0Pvdl0N4QzWGvezClZGmXo-Y6T3lm0k9irSz-leBStDhhTZhfxbQ/s1600/complex_communication_channel.gif" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="257" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEh0vSqiRvh_M9AoRuVwiiOy0WhRl6M2w6-l8c90WU8yGY95r9mXHzup4PB7vyYqeBIQmsWBIyYYzXE98ahktJO9WjC0Pvdl0N4QzWGvezClZGmXo-Y6T3lm0k9irSz-leBStDhhTZhfxbQ/s320/complex_communication_channel.gif" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Complex Communcation arises<br />
when everyone "communcaties" with <br />
everyone else all the time.</td></tr>
</tbody></table>
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">A
while back, I wrote about <a href="http://briannipper.blogspot.com/2010/09/really-big-problem.html" target="_blank">the "really big" problem</a> that companies faced and how they were looking to tools like
SharePoint 2010 to aid them in solving it. In my post I made reference to an
article in <i style="mso-bidi-font-style: normal;">Inc. Magazine,</i> written by
Joel Spolsky, CEO and founder of Fog Creek Software. The title of the article
is <em><a href="http://www.inc.com/magazine/20100201/a-little-less-conversation.html" target="_blank">A Little Less Conversation</a></em> and by way of a brief overview, the article
explains that when you are working in a group on any given problem its best if
the group can be small, and if it can NOT be small then try to keep “control”
over the communication channel.</span><br />
<br />
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">As
I’ve pondered on the “really big” problem, a.k.a. Communication within a group,
I’ve come to appreciate another perspective brought out in this article, which
is that everyone needs to respect other people’s expertise in a specific
problem area when working at a large company. As noted in the article, at large
companies people tend to be highly specialized, meaning that they focus on a
specific domain area, such as Databases, Server Administration, Networking,
Security, etc.; however, what I’ve come to appreciate about approach is that it
creates a deceptive complex problem in the communication front. Or to put it
another way, it creates a “hidden” problem. The reason I say hidden or
deceptive complexity is that with all the specialized people it would seem like
you don’t need all the team members to really have a complete picture, or do
you?</span></span><br />
<br />
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">Often
people will seem to think that each team member has to focus on their little
section of the puzzle and doesn’t need to concern themselves with the whole
picture. I don’t mean to say that you don’t want everyone to have access to the
full requirements or write-up of what the problem is; however, when you create
this segmentation of responsibility it can result in a culture where everyone
is “only” responsible for a small section of the puzzle and thus no one is
really responsible for the entire puzzle.</span></span></span><br />
<br />
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">So
how can you address this deceptive complex problem? As is the case with most
problems it would seem communication is the key. When projects begin it is
typical to bring in the team to identify what is being done and who will tackle
each section; however, it would be unwise to think that a weekly “team” meeting
with EVERYONE should be held and the reasons are noted in the article in Inc.
Magazine in terms of communication cost. Instead, it would be best to identify
where the sections connect and then “encourage” those smaller groups to
collaborate on the resolution.</span></span></span></span><br />
<br />
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">At
this point if you’ve worked on software development projects before you might
begin to visualize an intersecting web of parts, databases, application
servers, web servers, end users, etc. and then the people responsible for the
pieces and how they interact and you would perhaps draw the same conclusion
that I have which is that as a developer you are the center piece which will
require all those pieces to come together. So am I suggesting that a developer
should play a key role in ensuring that the communication within a team happens
in a meaningful manner? <strong>YES.</strong></span></span></span></span></span><br />
<br />
<span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;"><span style="font-family: "Calibri","sans-serif"; font-size: 11pt; line-height: 115%; mso-ansi-language: EN-US; mso-ascii-theme-font: minor-latin; mso-bidi-font-family: "Times New Roman"; mso-bidi-language: AR-SA; mso-bidi-theme-font: minor-bidi; mso-fareast-font-family: Calibri; mso-fareast-language: EN-US; mso-fareast-theme-font: minor-latin; mso-hansi-theme-font: minor-latin;">As
developers we should concern ourselves with every piece of the overall
solution. Why you may ask, well what does the code we write impact… EVERYTHING.
Another <span style="mso-spacerun: yes;"> </span>way to express this thought,<span style="mso-spacerun: yes;"> </span>is to<span style="mso-spacerun: yes;">
</span>ask what is needed for an application to work? At least a single server
and CODE (technically you need users otherwise why are you doing what you are
doing, but that’s a topic for another post). You would probably like more than
1 server, and it would be nice to separate out concerns like security and
networking to others that focus on these areas, but as a developer all the pieces
come together around what you are working on, and if you don’t think that you’ll
need to communicate effectively to accomplish the evergreen goal of ever
developer to “ship the code”, then please connect me so I can steer clear of
your projects because I’m fairly certain that you’ve succumbed to the deceptive
complex problem.</span></span></span></span></span></span>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com1tag:blogger.com,1999:blog-991446691792157231.post-86033750781800270652012-02-17T22:50:00.000-05:002012-02-17T23:00:52.844-05:00Good Shoes and Microsoft Outlook<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBssT2CkAAJPfMcHG5z1hPmyabicenU21GyMKaGcxZpub6Ojjf8gXIv67GHqL6HRmhbVOru84pIo7RbT-PYIdFGXm4Rxu8rBq6oaF5Ql9Vh1UdpTbrrtxfPRN0vqJcWA7o0dbNfjYGkRA/s1600/style_shoes.jpg" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="169" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjBssT2CkAAJPfMcHG5z1hPmyabicenU21GyMKaGcxZpub6Ojjf8gXIv67GHqL6HRmhbVOru84pIo7RbT-PYIdFGXm4Rxu8rBq6oaF5Ql9Vh1UdpTbrrtxfPRN0vqJcWA7o0dbNfjYGkRA/s320/style_shoes.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;"><a href="http://www.florsheim.com/" target="_blank">FLORSHEIM</a></td></tr>
</tbody></table>
I think I've found my favorite pair of shoes in the latest black slip-on Florsheim shoes that my wife picked up for me a few weeks ago. At this point they are still not broken in and rub my ankles raw if I have them on for any length of time, based on past experience I'd estimate I have a good 4 weeks before they are "comfortable" enough that my feet won't hurt after wearing them. So you may be asking yourself, why is this guy think these new shoes are so great? Because they look awesome, mind you I'm not saying they make ME look awesome. They are simple with clean lines, they have a nice shine, and I really like the way they look. The reason I like the way they look is because I like anything that has a minimalist feel. I enjoy pieces that don't attempt to look good by having tons of extra "stuff" that just isn't needed. This is also something I've found very appealing in the UI for the 2010 version of Microsoft Outlook. In particular to be able to shape the UI so that you only need what is necessary while performing various tasks.<br />
<br />
Below are the two views I switch back and forth between while using Microsoft Outlook. Since using e-mail at work is synonymous with breathing it goes without saying that I spend a substantial amount of time using outlook; however, I would guess (meaning I haven't done any actual measurement/testing) that I spend far less time looking at my e-mail. The reason I believe this to be true is because I do not fear my inbox. It is NOT a source of stress for me.<br />
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMn5UA3wTpkIWfuavXa6GYBfrkzPU2Y_d_gyVxI_dcBKMXv1Qeu1yfBy7ibGNZDvIpD42ksDRmw5HFr-UEkt6yL2ZWpyrPFToMBpUQgXeYDuHg745Kw9iYtvPadoOfhb4723sr5yjk5CY/s1600/MENU_SHOWING.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjMn5UA3wTpkIWfuavXa6GYBfrkzPU2Y_d_gyVxI_dcBKMXv1Qeu1yfBy7ibGNZDvIpD42ksDRmw5HFr-UEkt6yL2ZWpyrPFToMBpUQgXeYDuHg745Kw9iYtvPadoOfhb4723sr5yjk5CY/s320/MENU_SHOWING.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Default view with menus expanded</td></tr>
</tbody></table>
<br />
<div class="separator" style="clear: both; text-align: center;">
</div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="margin-left: auto; margin-right: auto; text-align: center;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7uxuWqFSBnHVS6ioDmFPaOoEU8FY9u_0Gb8CJjl0dk7Y6zzj0HMnWzOO8kkhtdASkmp1F96I-fRB-1vmpsYmp6EeG1xgc4ubcYzwNhFXie-fWSor1GGDoa6RJfu74m5xPRhCzL9qaPRQ/s1600/MENU_COLLAPSE.jpg" imageanchor="1" style="margin-left: auto; margin-right: auto;"><img border="0" height="200" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEi7uxuWqFSBnHVS6ioDmFPaOoEU8FY9u_0Gb8CJjl0dk7Y6zzj0HMnWzOO8kkhtdASkmp1F96I-fRB-1vmpsYmp6EeG1xgc4ubcYzwNhFXie-fWSor1GGDoa6RJfu74m5xPRhCzL9qaPRQ/s320/MENU_COLLAPSE.jpg" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Reading view with menus collapsed</td></tr>
</tbody></table>
<br />
One way I accomplish "conquering my inbox" is by switching to the "reading view" (as the name implies) when I need to focus on responding to messages. This view allows me to focus on reading my e-mail and responding as needed. When I to organize, archive, setup tasks, manage my calendar, etc. I switch to the default view. However as a rule I DO NOT leave outlook in the default view, so as to encourage focusing on messages as they arrive and not the other tasks as listed previously. This often results in my being able to read and absorb more information from my e-mails.<br />
<br />
Just as with code, if the viewing area for displaying lines of code is larger you tend to get a better "overview" of what the code is attempting to do. The same holds true (at least in my case) of the reading pane in Outlook. If you can see more of the e-mail thread at one time you tend to absorb more of what has transpired, this is often helpful when you are looped into a discussion after it has been initiated.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYfhpb80B_vL4fN3tq3Dv_fjWpVi0Xc3p7DIU9sC2dp_JCVkC8u7PAV8hNONFWj7RcGX-aoh52q5Ql1i89Z_d7Fafd-qEMbfVhQNKE5pngx5BspOvegUJAdRFoQ-UAWdwzEweHPOCLxVI/s1600/reading_default_switch_view.jpg" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="80" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgYfhpb80B_vL4fN3tq3Dv_fjWpVi0Xc3p7DIU9sC2dp_JCVkC8u7PAV8hNONFWj7RcGX-aoh52q5Ql1i89Z_d7Fafd-qEMbfVhQNKE5pngx5BspOvegUJAdRFoQ-UAWdwzEweHPOCLxVI/s200/reading_default_switch_view.jpg" width="200" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Reading and default view in MS Outlook</td></tr>
</tbody></table>
To toggle between the two views there are two tiny icons located in the bottom right corner of the window next to the scale slider as depicted in the image here.Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-1348746320195673042012-02-09T22:09:00.000-05:002012-02-09T22:40:06.027-05:00Don't leave your users hanging<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJSwTBBySIBr3HZHuWnrz4-Z1qZAoN55de4DZ25SpdwUygyJMVj8zKr2je5uXV3-GlUSe99riO2U4jw7uQbZiHj3MWRJPBmU7nnaj-gxdC8ki3SKlHcRtngxs7Yqkzxlkhr3mO5I4fAMU/s1600/command_interface.png" imageanchor="1" style="clear: left; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="320" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEiJSwTBBySIBr3HZHuWnrz4-Z1qZAoN55de4DZ25SpdwUygyJMVj8zKr2je5uXV3-GlUSe99riO2U4jw7uQbZiHj3MWRJPBmU7nnaj-gxdC8ki3SKlHcRtngxs7Yqkzxlkhr3mO5I4fAMU/s320/command_interface.png" width="245" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">command prompt can show actions as they are taken</td></tr>
</tbody></table>
If you create software one of the worst experiences you can create for your users is the "hanging" dialog. Recently I obtained a somewhat older MP3 player; to be specific it is a SanDisk Sansa Express 2GB. The device itself is on pair with most MP3 players that are not an iPod. One interesting feature is that you can record from the radio and it just so happen that the weekend past I had a need to record some audio from an FM station being used to broadcast at an assembly I was attending. To skip to the interesting point I found myself attempting to install new firmware to make it possible to listed to the WAV files created from the recording. After installing something to install something else (can you say inception) I found myself in a state of frustration because it "seemed" like the firmware update was going through just fine; however, the dialog box which indicates the progress had been "seemingly" stuck for quite a bit of time. So as any rational person would do I ignored all the warnings on the screen telling me NOT to remove the device while it is being updated, I yanked the cord out of the plug and started over, after turning my computer on and off again at least twice as any good technician will tell you is critical after just about any action you take. After attempting to install the firmware the "easy" way (using other software from the vendor) I again got "stuck" and gave up. At this point I believed I could overcome the problem by "manually" installing the firmware.<br />
<br />
<table cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;"><tbody>
<tr><td style="text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicveCfBBlnOmuKQt-ltgeY_l3Uq69qryN-Om7vGFU2WT900J8_spzhpJcJ9o_QDpxi9qHF7r-DUBZC6pUDpQN9U19zmQOMbI5SHO86VO6etv1i_09SPuk4U1kMxf9iU-Agv9PGMSVN5Cc/s1600/sansafirmware.png" imageanchor="1" style="clear: right; margin-bottom: 1em; margin-left: auto; margin-right: auto;"><img border="0" height="171" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEicveCfBBlnOmuKQt-ltgeY_l3Uq69qryN-Om7vGFU2WT900J8_spzhpJcJ9o_QDpxi9qHF7r-DUBZC6pUDpQN9U19zmQOMbI5SHO86VO6etv1i_09SPuk4U1kMxf9iU-Agv9PGMSVN5Cc/s320/sansafirmware.png" width="320" /></a></td></tr>
<tr><td class="tr-caption" style="text-align: center;">Sansa Updater dialog without any progress (in oh so many ways)<br />
Sansa Express - SanDisk (c) 2006-2008</td></tr>
</tbody></table>
After jumping through the seemingly random steps of extracting the various ZIP files and installing different drivers and ensuring I held down the "volume down button" (a.k.a. -) while plugging in the device I managed to get back to the same install screen that had haunted me before. Oh, and somewhere along the way I had to format the drive to continue so I lost the file I was attempting to use in the first place.<br />
<br />
While weaving through the various steps I realized that I may have cause myself a great deal of frustration simply because I was impatient, but is that really my fault? Well in some small way yes, after all patience is a virtue. However, I tend to think most of the blame rests with the software developers who created such an uninformative update process. If this had just been a command dialog via dos and they just listed of each file being impacted or perhaps a list of actions being taken I may have been more patient. Now to be fair this is a simple firmware update for a seemingly simply MP3 player and so the thought put into making sure a progress bar was accurately capturing the progress of the installation may have been a lower priority, but if there is nothing moving, no blinking indicator that something is still happening it is easy to expect that a user will abandon the cause and move on to something more shiny.<br />
<br />
So don't leave your users hanging. Give them the ability to peer into the goings on and inform them of what to expect in terms of responsiveness.<br />
<br />
<span style="font-size: x-small;"><b>UPDATE</b>: After 10 minutes after writing this post I came across additional information that outlined that the underlying issue with updating the firmware was it had to be done using a windows XP machine. Fortunatlly I have an old laptop with the legacy OS (along with various versions of Ubuntu) so I was able to get everything working and update the firmware, I did mange to lose a recording that I didn't have a back-up of, but such is life.</span>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0tag:blogger.com,1999:blog-991446691792157231.post-22838361138634659812012-02-08T01:06:00.000-05:002012-02-08T14:17:30.249-05:00Why we have to "Ask Why"<div class="separator" style="clear: both; text-align: center;">
<a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWADanhAQciiDm8Bgp2gd0oZOpBA9gckll_beUsMosg50E68Qg5ZHGtegOA7DzX7DTdvpwAoVphtqvD9s3FRYllfOAxYAQRtMj4xEq8qjbQRm52q4Phq5E-0G821dJEGA2cvYFbKe9CGA/s1600/WhyImage.gif" imageanchor="1" style="clear: right; float: right; margin-bottom: 1em; margin-left: 1em;"><img border="0" height="135" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhWADanhAQciiDm8Bgp2gd0oZOpBA9gckll_beUsMosg50E68Qg5ZHGtegOA7DzX7DTdvpwAoVphtqvD9s3FRYllfOAxYAQRtMj4xEq8qjbQRm52q4Phq5E-0G821dJEGA2cvYFbKe9CGA/s200/WhyImage.gif" width="200" /></a></div>
I'm always interested to find personality traits that seem to be common to "smart" people. When I use the term "smart" I don't mean to imply that they have some knowledge that is unattainable by others, also I don't mean to imply that they are more intelligent than the average person (although I suspect that if we were going off IQ that could be true). To be clear, I don't typically include myself in the "smart" category, I tend to think that I just happen to have a good memory which gives the impression of being smart, as well as being prone to asking the question <b>why, </b>which I have observed as being a trait of "smart" people.<br />
<br />
When people passively accept information that is given them without asking the question why, the result is often that the person receiving the information winds up with only a cursory understanding of the subject matter. In some cases I would completely agree that the "right approach" is to only obtain the cursory overview so as to be able to quickly dive into whatever task prompted obtaining the needed information in the first place. However, it seems to be that too often this cursory understanding becomes the default level for most persons even after the use of the information becomes more critical. To put it another way, after a person gets the "minimum" information to accomplish a given task there is no further effort put into obtaining a better understanding of why "things work the way they do".<br />
<br />
In a large enterprise (such as the one I spend my days currently) the end result of NOT asking why is that people go about their jobs doing completely unnecessary tasks simply because the default understanding is to "do it the way the person before me did it". I'll admit that this is probably easier in terms of the mental energy needed to have someone learn a set of tasks; however, I'd argue that anyone who has to complete a particular task repeatedly over the course of many months and perhaps years would benefit from a deeper understanding of what is attempting to be accomplished.<br />
<br />
In the case of a developer the need to ask the question why, IMHO, is NOT optional. If you are a developer and you DO NOT ask "why" at least once a day there is a good chance that you are NOT a good developer. It is easy to fall into the snare of believing that getting a good requirement document means that the "why" question has already been asked and answered and you simply need to implement the technical aspects of the requirement; however, this is almost never the case (except perhaps in the most fundamental of features).<br />
<br />
At every level of the development process all parties involved will be benefited by having a deeper understanding of asking the question why at each step along the way. In fact there is even a "method" called the <a href="http://en.wikipedia.org/wiki/5_Whys" target="_blank">5 whys</a> which shows how asking the question 5 successively (at least 5 times) will help to uncover the root cause. It would be good to note that as quoted by Jeff Atwood (of <a href="http://www.codinghorror.com/blog/" target="_blank">Coding Horror</a> fame) if you ask why too many times the answer winds up "because there are people on the earth" which is a good indication that you may have dived too deep.<br />
<br />
So if you are a developer don't forget to ask why, in fact in life in general it's probably a good idea to remember to ask why, just to keep things interesting.Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com1tag:blogger.com,1999:blog-991446691792157231.post-69589747415246921912012-02-02T23:54:00.001-05:002012-02-03T01:01:12.554-05:00Perspective and Puzzles<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: right; margin-left: 1em; text-align: right;">
<tbody>
<tr>
<td style="text-align: center;"><img alt="" border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/4/4b/Two_silhouette_profile_or_a_white_vase.jpg/320px-Two_silhouette_profile_or_a_white_vase.jpg" style="float: right; height: 226px; margin-bottom: 5px; margin-left: 10px; margin-right: 0px; margin-top: 0px; width: 320px;" />
</td>
</tr>
<tr>
<td class="tr-caption" style="text-align: center;"><span style="font-family: inherit; font-size: xx-small;"><a href="http://en.wikipedia.org/wiki/File:Two_silhouette_profile_or_a_white_vase.jpg" target="_blank">Reversible figures and vase. From Wikimedia Commons</a></span>
</td>
</tr>
</tbody>
</table>
I recently remembered a <a href="http://www.ted.com/">ted talk</a> from a while back about <a href="http://blog.ted.com/2009/10/08/optical_illusio/">optical illusions</a> and how our eyes can be heavily influenced by the context of what they see, or as mentioned in the talk, "the light that hits our eyes is not what is important, rather it is what we do with the information once it hits our brain that matters." To help illustrate this point the image here shows a famous "illusion" in that depending on your perspective the black area is the silhouette of two faces, or the white area forms a vase, in reality both are true and it is a mater of perspective on which view is "correct". FYI, I believe depending on how my day is going one or the other is true. :)</div>
<br />
<br />
<div>
I've also been rediscovering the fun I have playing <a href="http://en.wikipedia.org/wiki/Sudoku">Sudoku</a>. It's interesting how organizing numbers into patterns according to rules fosters a sense of accomplishment. Probably informs my career choice of "professional geek" (a.k.a. programmer).
</div>
<br />
<br />
<div>
<table align="center" cellpadding="0" cellspacing="0" class="tr-caption-container" style="float: left; margin-right: 1em; text-align: left;">
<tbody>
<tr>
<td style="text-align: center;"><img alt="" border="0" src="http://upload.wikimedia.org/wikipedia/commons/thumb/f/ff/Sudoku-by-L2G-20050714.svg/200px-Sudoku-by-L2G-20050714.svg.png" style="float: left; height: 200px; margin-bottom: 5px; margin-left: 0px; margin-right: 10px; margin-top: 0px; width: 200px;" />
</td>
</tr>
<tr>
<td class="tr-caption" style="text-align: center;"><span style="font-family: inherit; font-size: xx-small;"><a href="http://en.wikipedia.org/wiki/File:Sudoku-by-L2G-20050714.svg" target="_blank">Sudoku Puzzle. From Wikimedia Commons</a></span>
</td>
</tr>
</tbody></table>
<div style="text-align: left;">
That's not to say that enjoying puzzle games and being a good programmer are inextricably linked, in fact I'd dare say that in some sense, being fascinated with solving puzzles can be a detriment to being a good programmer. For example, solving a sudoku puzzle requires a very strong adherence to the rules of the game so that you can "predictive" the combination of numbers in the correct sequence to solve the puzzle. This same strict adherence to the "rules" of programming will result in the idea that given a particular situation there is only one solution which will work; however, as has been proven time and time again in the world of software there are plenty of choices to solve any given problem and often the "right" choice is more influenced by perspective.</div>
</div>
<br />
<div>
I often find that at one level a programmer is a plummer. You connect the pipes and/or tubes if you will. (You didn't know that the internet is a series of tubes?) Then turn on the information faucet and have the data flow from point a to point b and then it all goes down the drain. From this vantage point programming would seem like it's just a puzzle, if only all problems could be that simple. The reality is that the issue is not moving information through tubes, the issue is figuring out if you even have the right information in the first place.</div>
<br />
<div>
This is where perspective comes into play. You have to be able to obtain the context of a problem and appreciate the subtle shades of gray that come into the black and white world of programming. Who are your users? What are their objectives? How do you want them to feel after they use your software? And a hundred other questions that even make me cringe when I think about attempting to answer these questions for all but the simplest of problems.</div>
<br />
<div>
If you do figure out what the right "perspective" is then you can dive into the "fun stuff", where you get to enjoy the straightforward challenge of programming and relish the sense of "solving the puzzle, the right way".</div>Brian Nipperhttp://www.blogger.com/profile/02705572509133155804noreply@blogger.com0