Kill cmd.exe

Where we are?

How many time have I heard this question from other PowerShell enthusiasts: “when cmd.exe is going to die”. Or at best “when will PowerShell.exe become default when user asks for command line”. It’s not so in Windows 8 Developer Preview, not sure what to expect in final release, but kind of don’t expect it to happen anytime soon. What is most frustrating for some is the fact, that server core still expects us to type “powershell.exe” once we boot.

Read more…

CMD and SG 2010 – Part 5.

This is today… Today I will have a chance to speak to THEM. Good day to finalize my series. Not the best day to do shopping, since my bank card expired. ;) So no real breakfast today.

Last two events were not very hard, but I had two problems to move them to CMD.

Event 9 required array manipulation but… there is no array in CMD! So what should I do? Well, I tried to ‘pretend’ I was playing with arrays. So it’s not a script I could easily defend. Probably one star only. ;)

CMD, using GeSHi 1.0.8.8 – Beginner Event 9
  1. @echo off
  2. SET Arr1=a b c d
  3. SET Arr2=d e f g
  4.  
  5. echo Array 1 = %Arr1%
  6. echo Array 2 = %Arr2%
  7. set Arr3=
  8.  
  9. call :Conc %Arr1%
  10. call :Conc %Arr2%
  11.  
  12. echo Final Array = %Arr3%
  13. goto :EOF
  14.  
  15.   :Conc
  16.   if [%1]==[] goto :EOF
  17.   echo %Arr3% | findstr /r "%1," > nul || (SET Arr3=%Arr3%%1, & echo %1)
  18.   goto :Conc
  19.  

Second was even harder: how to debug .vbs or .ps1 when I use cmd only? I decided to take other route: OK boss, I’m not fluent in either, I will get your message box in cmd, and leave those broken scripts alone. ;) There is no ‘silentlycontinue’ in cmd (unless you redirect 2> nul) so if I hit error – I will know it. So that’s what I came up with:

CMD, using GeSHi 1.0.8.8 – Beginner Event 10
  1. @echo off
  2. for /f %%M in (‘wmic ComputerSystem Get UserName ^| findstr /r ".*\.*"’) do @SET msg=%%M
  3. msg %USERNAME% %msg%

See? Message box as you expected. Title may be a little confusing, but who would read title in a window like that? ;) So again: not exactly what Scripting Guys asked for, but I had to limit my self to command line tools only.

And now I have few long hours ahead. I plan to get to bed early and today (tomorrow my time) wake up in the middle of the night, drive to work (so that I would not wake up my family while recording podcast). So two big issues ahead of me: how to concentrate on what I’m doing when at work, and how to fall asleep when at home. ;) I usually go to bed around 1-2, so it may be a real problem. So plan B is stay at home, and call podcast team from bathroom ;) Will see how it all works out for me.

CMD and SG 2010 – Part 4.

Monday at my door and I’m really worried about it. Deadline is approaching and we have no chance to meet the goal. I hate it when somebody is leading a project in a way, that prevents members from doing things in a proposed schedule. Anyway, Thursday is pretty close so I’m slowly getting excited. And still 4 scripts to go in my cmd series. So here is the one that took me most of time to figure out, mainly because both in VBS and in Powershell it was usually done with COM object, and I have no idea how to use those in CMD. But then I thought, that this type of information has to be in the registry somewhere, looked for it a while, and – there it was. :)

CMD, using GeSHi 1.0.8.8 – Beginner Event 7
  1. @echo off
  2. set /a Counter=0
  3. set AdminPath=Empty
  4. for /f "delims=" %%A in (‘reg query "hklmsoftwaremicrosoftwindowscurrentversionexplorershell folders" /v "Common Administrative Tools" ^| find "Administrative Tools"’) do call :ProcessResult %%A
  5. for %%F in (%AdminPath:~0,-2%*.lnk") do call :CountAndDisplay "%%~nF"
  6. echo Done! Total %Counter% items . . .
  7. goto :EOF
  8.  
  9.   :ProcessResult
  10.   if [%AdminPath%]==[Empty] (
  11.     if [%1]==[REG_SZ] (
  12.     set AdminPath="
  13.     ) else (
  14.       shift
  15.       goto :ProcessResult
  16.     )
  17.   )
  18.   :JoinPath
  19.   if [%1]==[] goto :EOF
  20.   set AdminPath=%AdminPath%%1
  21.   goto :JoinPath
  22.  
  23.   :CountAndDisplay
  24.   echo %~1
  25.   set /a Counter+=1
  26.   goto :EOF

I’m almost sure there is easier way to get only path from reg output. But this one works too, so I do not really care. ;)

Script # 8 was easier to write, but I still seem to have some problems with output. Anyway – it works better than I would expect, so I left it like that.

CMD, using GeSHi 1.0.8.8 – Beginner Event 8
  1. @echo off
  2. echo Process Owner
  3. for /f "skip=1" %%I in (‘wmic PROCESS where "Name!=’wmic.exe’" get ProcessID’) do call :GetOwners %%I
  4. echo Done!
  5. goto :EOF
  6.  
  7.     :GetOwners
  8.     SET ID=%1
  9.     for /f "delims=" %%P in (‘wmic PROCESS where "ProcessID=’%ID%‘ and name!=’wmic.exe’" get name ^| findstr /r /v "^$ ^Name"’) do (
  10.       set Process=%%P
  11.     )
  12.     for /f "tokens=2,3 delims=;= " %%O in (‘wmic PROCESS where "ProcessID=’%ID%‘ and name!=’wmic.exe’" call getowner ^| find "User"’) do (
  13.       set Owner=%%~O %%P
  14.     )
  15.     echo %Process% %Owner%
  16.     goto :EOF

As you can see most of stuff is done with usage of wmic.exe – pretty handy tool I must admit. Even if gwmi is easier to use and remember. ;)

CMD and SG 2010 – Part 3.

Monday. One day in week I’m not looking forward to and would sometimes like to erase it from calendar. Tomorrow will be hopefully different – mainly because we expect new furniture in our office. I really was looking forward to it, old ones didn’t behave well with stresses of equipment we kept inside (laptops, hard drives, switches…). New one should be fine with that. Will see…

One bad news: my meeting at podcast is postponed: it will happen on 1st July.

One good news: I have more time to prepare for it. But knowing myself long enough – it probably won’t have any effect on my preparations. I’m the ‘last minute’ type. Meaning: if I can do something later – I will do it too late. ;)

So now to the script. Event 5 – here I come equipped with CMD only! :D OK, I’ve used wmic.exe, but it’s not external tool for windows, so it’s valid. :)

CMD, using GeSHi 1.0.8.8 – Beginner Event 5
  1. @echo off
  2. for /f "tokens=1,2" %%A in (‘wmic CPU GET Manufacturer^, MaxClockSpeed’) do CALL :Process %%A %%B
  3. echo CPU speed on %COMPUTERNAME% is %SPEED%. The maker is %Manu%.
  4. goto :EOF
  5.  
  6.   :Process
  7.   if [%1]==[] goto :EOF
  8.   SET Manu=%1
  9.   SET SPEED=%2
  10.   goto :EOF

It’s using call :label technique I’ve learned ages ago. Almost like subs with pure ‘DOS’ as people tend to call it. Worked like charm so I have moved quickly to next event, which was quite big, and took me a while to get all pieces together. ;)

Script is pretty long:

CMD, using GeSHi 1.0.8.8 – Beginner Event 6
  1. @echo off
  2. echo IP,ServiceState,ServiceStartMode,ComputerName,IsDomainMaster,MaintainServerList
  3. for /l %%N in (1,1,255) do CALL :CheckIP %%N
  4. goto :EOF
  5.  
  6.     :CheckIP
  7.     SET IP=192.168.1.%1
  8.     ping %IP% -n 1 | find "bytes=" > nul || (
  9.         echo %IP% is not responding 1>&2
  10.         goto :EOF
  11.     )
  12.     for /f "tokens=1,2,3 skip=1 eol= " %%A in (‘wmic /node:%IP% SERVICE WHERE "Name=’Browser’" GET Started^, StartMode^, SystemName’) do call :SetService %%A %%B %%C
  13.     goto :EOF
  14.    
  15.     :SetService
  16.     if [%1]==[] (
  17.         goto :EOF
  18.     )
  19.     if [%1]==[TRUE] (SET ServiceState=Running) ELSE (SET ServiceState=Stopped)
  20.     SET ServiceStartMode=%2
  21.     SET ComputerName=%3
  22.     for /f "tokens=3" %%I in (‘reg query \%ComputerName%HKLMSystemCurrentControlSetServicesBrowserParameters /v MaintainServerList ^| find "MaintainServerList"’) do SET MaintainServerList=%%I
  23.     for /f "tokens=3" %%I in (‘reg query \%ComputerName%HKLMSystemCurrentControlSetServicesBrowserParameters /v IsDomainMaster ^| find "IsDomainMaster"’) do SET IsDomainMaster=%%I
  24.     echo %IP%,%ServiceState%,%ServiceStartMode%,%ComputerName%,%IsDomainMaster%,%MaintainServerList%
  25.     goto :EOF

What I like about that script? It uses few of my favorite techniques:

  • || to react to an error (one can expect timeouts, so script should respond to it and send info about it to ‘error’ pipe
  • subs to make code more reliable and easier to read/ debug
  • separating stdout and errout with use of 1>&2
  • for here, for there – in cmd it’s ‘for’ everywhere. Here used, besides well known and often used ‘for /f’- way in for (i=0; i<max; i++) fashion.

If you redirect 2> nul – you won’t see any error. If you redirect 1> file.csv, you will see only errors and useful data will go to file. Should help to get decent file that excel can work with. No COM object required. ;)

CMD and SG 2010 – Part 2.

Planned to do that almost a week ago, but man – it was a crazy week for me. A lot of work, a lot of travelling, a lot of unexpected issues and problems. Fortunately it’s getting peaceful now, so I have a chance to play a bit with Powershell and test tips and tricks I’ve learned during MS 50025 Training. :) Meanwhile it’s time for next two scripts from cmd:

CMD, using GeSHi 1.0.8.6 – Beginner Event 3
  1. @echo off
  2. if not exist C:FSO mkdir C:FSO
  3. pushd C:FSO
  4. >file10.txt echo CLASS:
  5. >>file10.txt echo DATE:
  6. >>file10.txt echo NOTES:
  7.  
  8. for /l %%N in (1,1,9) do copy file10.txt file%%N.txt > nul

So simple, and yet do what it should. Next one:

CMD, using GeSHi 1.0.8.6 – Beginner Event 4
  1. @echo off
  2. if %NUMBER_OF_PROCESSORS% GEQ 2 (
  3.   echo Enough : %NUMBER_OF_PROCESSORS%
  4. ) ELSE (
  5.   echo Not enough : %NUMBER_OF_PROCESSORS%
  6. )

Even simpler. In fact it all started here – while playing with that event in VBS I was thinking: it would be even easier in cmd! And yes, it could be one line of code. I even mentioned it in my comment for SG entry. Judges gave me 2 stars but to be honest – I had no intention to get more. It would be embarrassing to add comments, help and error handling for something THAT simple. And I was shocked with suggestion from expert that if you want to check this in cmd – go grab my 10-line VBS to do so. No way! :P I will do it in one line of native cmd code! ;)

Meanwhile I learned new trick for powershell profile. I thought: how nice it would be to have PS window always as big as possible. So I played a bit with $host properties and I managed to get what I want. It was rather simple. See:

PowerShell, using GeSHi 1.0.8.6
  1. $MySize = $Host.UI.RawUI.MaxPhysicalWindowSize
  2. $MySize.Width –= 3 # We need scrollbar after all… ;)
  3. $MyBuffer = $MySize
  4. $MyBuffer.Height = 5000 # Set to any value you need – I like it looong. ;)
  5. $Host.UI.RawUI.BufferSize = $MyBuffer
  6. $Host.UI.RawUI.WindowSize = $MySize

And last but not least: I entered Powershell Portable beta program and – man – I’m loving it. :> Finally I will be able to carry PS with me to other workstation if I need it. After all not everything can be done via WMI, or even if it’s possible to do something remotely – you won’t have a chance to do that on a computer that has some network issues, right? :)

CMD and SG 2010 – Part 1.

First of all: I was third in SG this year. :) It means I will have a chance to talk with Jeffrey Snover! Yupi!

That was a great news, but next one was even greater than first one: it will be on my favorite podcast, and Ed will be also there! How cool is that?! :)

I was thinking about 1000s of questions I could possibly ask, things I could say, and so long, and so forth. And while doing so I had to thing about how simple beginner events was. And I thought how cool it would be to get all events in cmd. And you know what? It worked! I learned few new tricks, so it was again learning experience. I would like to share my simple scripts, and because there is no cmd scripts repository (at least I failed to find one), I will have to copy it here. Good news – it was short, so it won’t be hard to read it. I don’t encourage you to use it however: go get Powershell and do it all in one line. ;)

CMD, using GeSHi 1.0.8.6 – Beginner Event 1
  1. @echo off
  2. if [%1] == [] (
  3.   SET KEY="HKCUSoftwareScriptingGuys2010ScriptingGames"
  4. ) ELSE (
  5.   SET KEY=%1
  6. )
  7.  
  8. if [%2] == [] (
  9.   SET VAL="LastUpdate"
  10. ) ELSE (
  11.   SET VAL=%2
  12. )
  13.  
  14. if [%3] == [] (
  15.   SET DATA="%DATE%"
  16. ) ELSE (
  17.   SET DATA=%3
  18. )
  19.  
  20. echo Setting key:%KEY% val:%VAL% with data:%DATA%
  21. REG ADD %KEY% /V %VAL% /D %DATA% /F

As you can see it work fine without any parameters, but it’s also possible to pass arguments to the script. No error handling, but I think it’s something I would not need anyway. ;)

So now for Beginner event no 2, where actual learning experience started. I’ve never used wmic.exe before. Fortunately I knew it existed and had something to start with. Read some help, googled a bit, and see what I got:

CMD, using GeSHi 1.0.8.6 – Beginner Event 2
  1. @echo off
  2. set MyDate=Unknown
  3. for /f %%T in (‘wmic NTEVENT where "LogFile=’system’ and EventCode=’6005‘" GET TimeGenerated’) do call :SetDate %%T
  4. echo Last boot date: %MyDate%
  5. goto :EOF
  6.  
  7.   :SetDate
  8.   if not [%MyDate%]==[Unknown] goto :EOF
  9.   if %1==TimeGenerated goto :EOF
  10.   SET TempDate=%1
  11.   SET Year=%TempDate:~0,4%
  12.   SET Month=%TempDate:~4,2%
  13.   SET Day=%TempDate:~6,2%
  14.   SET MyDate=%Year%-%Month%-%Day%
  15.   goto :EOF
  16.  

Next two tomorrow. :)