Sunday, February 27, 2022

Powershell Tutorial: Useful CMD in Powershell

When I talk to people about Powershell, there seems to be a lot of hesitance to use it. It's always just easier for people I know to rattle off whatever obscure CMD command they know. The combination of exe programs that have no Powershell equivalent but maybe offer a few wrapper libraries or copy-paste functions can make it seem even less useful to learn how to do things in Powershell. The biggest point I can make for using Powershell is the ease of data processing. Throw that in with .Net and you actually have a very flexible toolset. If you want to advance to scripting and automation, it is in my opinion advantageous to learn whatever tools offer the best for gathering, processing, and even reporting data. Powershell fits this really well, and I am genuinely surprised at how easy it feels once you start getting into using it. To that end, here is a list of common commands I use a lot on command line and their CMD equivalent. Some are a bit more extensive just to match the output, so it may also be worth looking into making your own module or making some functions for the Powershell profile script.

  • Get the IP address
    • ipconfig
    • Get-NetIPAddress
  • Get the mac address
    • ipconfig /all
    • Get-NetAdapter
  • Get the DNS servers
    • ipconfig /all
    • Get-NetIPConfiguration
  • Trace route
    • tracert <destination>
    • Test-NetConnection -TraceRoute <destination>
  • Ping
    • ping <destination>
    • Test-Connection <destination>
  • Netstat is a little more complicated because UDP and TCP are different commands
    • netstat
    • Get-NetTCPConnection / Get-NetUDPEndpoint
  • Netstat but with process information attached (powershell uses pid, but you can fudge the names in there)
    • netstat -b
    • Get-NetTCPConnection | select localaddress,localport,remoteaddress,remoteport,state,@{N="Process";E={$(gps -pid $_.owningprocess).processname}}|ft
  • Update group policy for domain computers (Powershell can do so remotely)
    • gpupdate /force
    • Invoke-GPUpdate -Computer <computername> -Force
  • Rename a computer (Powershell works remotely here as well)
    • WMIC computersystem where caption='OldComputerName' rename NewComputerName
    • Rename-Computer -ComputerName <oldname> -NewName <newname> -Restart
This is hardly an extensive list. It is true that in most cases the CMD versions are shorter. It is also true that the CMD versions often times use very obscure abbreviated names, whereas Powershell is very verbose in naming. There is also a long list of very useful aliases that make a translation between CMD to Powershell and even Bash to Powershell, and some shortened common Powershell command. For example, list directory in Powershell Get-ChildItem is aliased to gci for short, dir for familiarity with cmd, and ls for familiarity with Bash. While it may seem inconvenient, Powershell is actually very good at dealing with large batch processes and very easily controlling data flow and even parallel processing (which may seem weird bit can be a huge time saver).

I hope this list helps some people get used to running some basic Powershell tasks, Throw in some basic loops and branching and you're already where you need to begin making very comprehensive automation scripts.


Sunday, January 30, 2022

Powershell Tutorial: Mass Renaming Items

 I want to write this down mainly to help myself remember, but maybe others will find this useful. I will probably try to spend some more time documenting various little useful Powershell snippets I have been working on and using. Mass renaming of files is something I always find myself needing to do and looking up how to do it every time. I am usually on Windows, so I will show how to with Powershell. I mostly use it when downloading a series of files that are not named the way I want or need. So let's use an example of a TV show. This TV show has multiple Seasons. I try to organize it by TvShowName\SeasonXX\TVShowName SXXEYY.mkv, or something like that. Assuming they are already in order, as they usually are, this is actually a really simple process. Let's assume we have TvShowName Season 1 I am trying to rename.


# declare an incremental value

$n = 1

# Feed everything into a loop with a "pipe"

$(Get-ChildItem).Name | Foreach-Object {

# The $_ is the current item in the loop, -f is string format, stuff in $() treats the output as a variable

Rename-Item $_ $("TvShowName S01E{0:00}.mkv" -f $n)

# Increment $n by 1

$n++

}


This would leave us with a folder resulting in:

TvShowName S01E01.mkv

TvShowNameS01E02.mkv

...


Easy, right? However, that would be a pain to type all that out every time, so let's short hand this for on-the-fly name changes in a live shell.


$n=1;$(gci).name|%{rni $_ $("TvShowName S01E{0:00}.mkv" -f $n++}


This is a bit harder to read, but it has the same results. The $n++ being on the same line as the format is possible thanks to order of operations. The incrementing of $n does not occur until after the format. I also use common aliases that Powershell has in place by default.


Now let's expand upon this just a little bit more, let's say I want to include the original extension because it might not all be the same. I will modify the expanded version to show this.


$n = 1

Get-ChildItem | Foreach-Object {

Rename-Item $_.Name $("TvShowName S01E{0:00}{1}" -f $n, $_.Extension)

$n++

}


Now it is becoming a little more robust. Luckily for us, the extension includes the period, so one less character. Now let's further re-organize this code to be just a bit more readable since we understand it a little bit better now.


Get-ChildItem | Foreach-Object {$n = 1} {

Rename-Item $_.Name $("TvShowName S01E{0:00}{1}" -f $n++, $_.Extension)

}


So the change here is super simple. The Foreach-Object block can take multiple script blocks. If it only gets one, that's the process block. If it gets 2, the first is a block it run BEFORE running the process block. If it gets 3 or more, the last becomes what it runs when it is done and the middle all become process blocks. So basically, moving the $n = 1 to be in a more traditional initialization position for a loop. The problem with this is we are looping with a lot of assumptions. We assume there will be an order to this and what we want to name will be easy to do. Generally, on the fly typing commands, this is what you would be doing. Anything more robust and you will likely want to type out a full fledge function, perhaps even create a module to do so. As you saw at the beginning, this relatively simple task can be an easy one-liner with very little typing thanks to aliases, with the final condensed version being like so.


gci|%{$n=1}{rni $_.name $("TvShowName S01E{0:00}{1}" -f $n++,$_.extension)}


To be honest, I love typing out those types of one-liners, feels like being a movie hacker and a typical passer-by is not going to easily recognize what you are doing. Granted, in a movie they would probably show you some big long graphical "hello, world!" code and tell you it's a super awesome malware that can compromise the entire nuclear system of some country. For now, I will just keep it simple with this. Experiment, tweak, and expand this to your liking.

Tag Cloud

.NET (2) A+ (5) ad ds (1) addon (4) Android (4) anonymous functions (1) application (9) arduino (1) artificial intelligence (1) backup (1) bash (6) camera (2) certifications (3) comptia (5) css (2) customize (11) encryption (3) error (13) exploit (5) ftp (1) funny (4) gadget (4) games (3) GUI (5) hardware (16) haskell (6) help (14) HTML (3) imaging (2) irc (1) it (1) java (2) javascript (13) jobs (1) Linux (19) lua (1) Mac (4) malware (1) math (6) msp (1) network (13) perl (2) php (3) plugin (2) powershell (8) privacy (2) programming (24) python (10) radio (2) regex (3) repair (2) security (16) sound (2) speakers (2) ssh (1) story (5) Techs from the Crypt (5) telnet (1) tools (13) troubleshooting (11) tutorial (9) Ubuntu (4) Unix (2) virtualization (2) web design (6) Windows (16) world of warcraft (1) wow (1) wx (1)