Secret Command?
I was looking for the official definition for the semicolon in Powershell. I came across a blog on MSDN, and the way I read it almost made me laugh and be angered at the same time…
http://blogs.msdn.com/b/mattn/archive/2012/04/28/powershell-command-separator-is-and-not-amp.aspx
cmdlet equals secret command? from a MSFT blogger?
Splatting the ScriptBlock
After making ScriptBlock work in a splat I just had to tinker. I had implemented it in a production script and it worked very well. With the usual need to tinker but more importantly to revive all of the logging I wanted to find a way to include the several lines I had in the script I was previously using for the start-job.
Using a generic script to do generic tasks I started to experiment. First was to string a few commands each separated with the semi-colon (;) which worked well but in this case would comprise of a very long line of text, defeating a huge purpose of my goal to use splatting. Here-String had to be the answer, but how do I get that to work. Doing some research I came across the ScriptBlock class which includes a Create method. I then looked around the community and this seemed like an approach that would work.
$sample = @”
write-Host ‘Test’ -ForegroundColor Green
(gwmi win32_operatingsystem).Caption
write-Host ‘Completed’ -foregroundcolor Red
“@
$sb = [scriptblock]::Create($sample)
$jobdat=@{
ScriptBlock = $sb
}
invoke-Command @jobdat
So I built the here string as my sample variable, then stored it as a script block within a new variable named sb. I included that in my splatted list of command arguments and no errors and it executed as I expected. Now to take this simple example and apply it to my production code.
Thanks to mjolinor – “The Powershell Workbench” and Steve Murawski – “Use Powershell” for some great help.
Async Copy Splat
It’s been quite some time since I last posted here. A few things derailed my Powershell activity but with a new job I am back to learning Powershell.
So there was an ongoing project for the WindowsXP to Windows7 migration company wide. As I understand it the project was behind schedule and the push to get the project underway was pressing. I was approached to write a script to address an issue that the use of USMT just wasn’t working or adequate. The request was easy enough and I drafted the code. Before it was even tested there was one of those “could you add”, after a few more of those I really wanted to re-work the whole thing but it was time to perform pilot testing so a re-work really wasn’t going to be well received.
Part of the migration is to also change the location and naming for the user “HomeDirectory” so data would have to be moved, or at least copied. I chose a copy just to be safe as their original contents would still be in place until the user was able to login and verify, less headaches.
Well now the issue was how to facilitate up to 50 user updates and the coinciding data copies. Certainly “start-job” could be used so that I can process a user, start the file copy and go to the next user while, not after, the previous file copy was processed. So I put together the code but noticed that the background jobs would be destroyed as soon as the script completed. At first I thought maybe it was an issue with running it as a scheduled task or maybe I needed to start Powershell with –STA.
So using a simple local test on my home network I started to experiment.
function copy-userdata {
Param(
[string]$srcpath,
[string]$destpath
)
"Starting backup of $srcpath to $destpath"
$jobdat = @{
'Name' = "test"
'ArgumentList' = $srcpath,$destpath
'ScriptBlock' = {copy-Item -Path $args[0] -Destination $args[1] -Recurse -Force -ea 'SilentlyContinue' -Container}
}
start-Job @jobdat
}
# Just cleaning up jobs leftover from previous test
get-Job | remove-job
copy-userdata "c:\Users\jkavanagh58" "\\jkav-homerig\public\Backup\test"
# Wait for all jobs to complete
get-job | wait-Job
Again the above code is just my test copy, but became the working model. What seemed to be the issue was instead of worrying about making the get-job specific, I could just call it and pipe that to wait-job (get-job | wait-job). So for the working copy during my ForEach statement it does the set-qaduser functions, starts the file copy job in the background and moves to the next user, when the ForEach loop is complete get-job | wait-job holds the script until the last job is completed.
Now I have to admit my first attempts to use start-job I was calling another script, but thought it would make things easier when (if) someone else looks at the code if it was a function in the same script. Hmmmm how about if we splat the start-job, that should be easy. Not as easy as I thought, at least not the ScriptBlock parameter. So I got it to work with start-job @jobdat –ScriptBlock { <code>} but there had to be a way. I found this post and now the whole start-job is splatted.
Nothing advanced here, was just fun to get back into some practical powershell.
Episode 166 - Alan Renouf talks PowerCLI
Reblogged from PowerScripting Podcast:
A Podcast about Windows PowerShell. Listen:
In This Episode
Tonight on the PowerScripting Podcast, we talk to Alan Renouf about PowerCLI!
Interview
This segment brought to you by Start-Automating
Start Scripting to Your Fullest Potential. At Start-Automating, we can help you unleash the full Power of PowerShell V2. You can use our deep PowerShell expertise to build rich PowerShell solutions, or we can train you to use PowerShell like a pro.
Having fun with remote Registry
So I have not been able to really work with Powershell much in my new job. A recent project had me involved with getting Windows 2008 R2 domain controllers into our infrastructure. All of that was pretty standard. There is one little setting that seems to get our security guys into interrogation mode. That little icon on Windows 2008R2 and Windows 7 that shows if you have internet connectivity or not… It can be turned off via Group Policy easy enough but there is not much Powershell going on in this office so…
First example I showed was how to use the CLI to make the change the value locally using:
set-itemproperty hklm:\system\currentcontrolset\services\nlasvc\parameters\internet -Name 'EnableActiveProbing' -value 0 -type dword
I then wrote a script that when logged onto a server we could run to check the current setting and update it if necessay.
This of course led to a challenge “can you show what all of our 2008R2 servers are set for”… As I said before there is not much Powershell in this shop so Remoting is not an option. That is when I rediscovered a module that I had not used in over a year… PSRemoteRegistry I was quickly able to give a brief instruction on powershell modules and then show a quick example of how to remotely check the value and then set it appropriately if necessary:
get-regdword -Computer computername -Hive LocalMachine -Key system\currentcontrolset\services\nlasvc\parameters\internet -Value EnableActiveProbing set-regdword -Computer computername -Hive LocalMachine -Key system\currentcontrolset\services\nlasvc\parameters\internet -Value EnableActiveProbing -Data 0
Wala… Now the computer just needs to be rebooted and the Security folks won’t see these machines trying to test for internet connectivity. Now I did have one machine that was my test machine that was not cooperative, matter of fact a valid set-itemproperty statement would actually cause it to duplicate the key but there was another issue on that machine at the time and I didn’t take the time to resolve what appeared to be a one-off case.
Policing Code
I have to preface this with I truly respect the idea and the gentleman who initiated ScriptCop. That said it sort of brings up a sore point that struck me during the last Scripting games.
I am all for beautiful functioning code but Powershell seems to have brought a large amount of developer oriented folks into the community and the mix with System Administrators becomes interesting. When I first started with Powershell I was doing lots of vbscript so I was able to focus on code and listening to the great minds who were not just teaching the powerful language but to optimize it.
I would love to sit and perfect my code, but as my new job dictates, there isn’t time to write beautiful code. And that is just one issue I have with the critiquing. Granted I think that an employer who wants you to apply Powershell technology but doesn’t think you should spend time doing it right is problematic but, that is how it is. Additionally when I write code, I have to think about it’s readability, and readability amongst a varied expertise. Things like long concise pipelines. They look very cool and are normally very proficient, but think about the SysAdmin who might have to perform an after hours support call when it isn’t functioning correctly. Despite the huge powershell community, my day to day experience indicates there are more Windows System Administrators that are not even looking at Powershell and most never progressed beyond batch files. Breaking a pipeline into separate steps is just a more debuggable format in my opinion.
I do think ScriptCop is a great idea but maybe applied more towards a uniform way to apply approved standards to a library of scripts.
Loyalties
So, this post is more about personal loyalties than Powershell itself. The recent changes with PowerGUI have me contemplating changing my default editor. I have found PowerGUI to be great, but part of the greatness was the Product Manager. The product is great, especially the editor. I did buy the pro version and quite frankly in my environment it didn’t give me anything I could use but it seemed right to support the product as I as endorsing it to everyone I worked with.
At this point I am considering going back to PowershellPlus but after I played with the most recent beta I miss the original version. I still use Sapien for when I have to work with vbscript code but I find it way too bloated when comparing it PowerGUI. When it’s all said and done I think I will be deciding between the ISE and the free PowerGUI.