July 12, 2010

Network Adapters with Powershell

Filed under: Script — Tags: — Kevmar @ 6:26 am

One of the first things I discovered with Windows 7 was that they moved access to network adapters. I had some quick way to get to it and now I need to visit a few more screens. Today a coworker was talking about that same issue. He wanted a faster way to get to it. My response was, “I bet we can do that with Powershell”. The most common reason we end up looking at network adapters is to change ip settings to static or to DHCP. The only other things we do can be done with IPConfig. So I set out to write a little powershell that would give a computer a static IP address.

This turned out to be very simple with the Win32_NetworkAdapterConfiguration WMI object. I can use it to manage everything that was done with the GUI. The usual way we set static addresses is by first taking the dhcp address, entering it as static to the computer, then go into the dhcp server and exclude that address.

Set-NetworkStatic.ps1

$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq “TRUE”}
Foreach($NIC in $NICs) {

    $IP =$NIC.IPAddress -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"

    $Subnet = $NIC.IPSubnet -match "\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b"

    $Gateway = $NIC.DefaultIPGateway
    $DNSServers = $NIC.DNSServerSearchOrder
    $Domain = $NIC.DNSDomain

    $NIC.EnableStatic($IP, $Subnet)
    $NIC.SetGateways($Gateway)
    $NIC.SetDNSServerSearchOrder($DNSServers)
    $NIC.SetDynamicDNSRegistration(“TRUE”)
    $NIC.SetDNSDomain($Domain)
}

And then a second script to set it back to DHCP.

Set-NetworkDHCP.ps1

$NICs = Get-WMIObject Win32_NetworkAdapterConfiguration | where{$_.IPEnabled -eq “TRUE”}
Foreach($NIC in $NICs) {

    $NIC.EnableDHCP()
    $NIC.SetDNSServerSearchOrder()
}

July 5, 2010

Chaocipher: the algorithm in PowerShell

Filed under: Script — Tags: — Kevmar @ 5:24 pm

Cypher Mysteries just revealed a old substitution cypher from 1918. Here is a detailed example on how to work the method by hand.  After I read both of those sites I decided to flesh out the code for it in PowerShell.  This turned out to be very easy to put to code.  Review the linked example then take a look at my PowerShell sample.

I used ArrayLists to hold the left and right alphabets. When I thought about the circular nature and shifting of the alphabets, linked lists where the first things to come to mind. I think this sample can easily be translated in to other languages.

# Kevin Marquette
# www.ithinkincode.com
$cipher = ""

for($index=0; $index -ne $message.length;$index++)
{
    # Find the plain text letter and shift it to the front
    while($message[$index] -ne $right[0])
        {
        $right.Add($right[0]); $right.removeat(0); # Shift left
        $left.add($left[0]);    $left.removeat(0); # Shift Left
        }
    $cipher += $left[0];   

    # move from zenith + 1 to nadar (zenith + 13) position
    $left.insert(14,$left[1]);
    $left.removeat(1);

    # rotate right one more letter
    $right.Add($right[0]);   $right.removeat(0);  #Shift left

    # move from zenith + 2 to nadar (zenith + 13) position
    $right.insert(14,$right[2]);
    $right.removeat(2);
}

Write-Host $cipher;

Thats the base implementation of the Chaocipher. Here is my full implementation that also includes decryption.

# Kevin Marquette
# www.ithinkincode.com

function get-chaocipher([string]$message = "WELLDONEISBETTERTHANWELLSAID", [string]$leftalphabet = "HXUCZVAMDSLKPEFJRIGTWOBNYQ", [string]$rightalphabet="PTLNBQDEOYSFAVZKGJRIHWXUMC", [bool]$encrypt=1)
{
Write-Host "Message: $message";
Write-Host "Left: $leftalphabet";
Write-Host "Right: $rightalphabet";
Write-Host "Encrypt: $encrypt";

# Validate Input
if($message -cmatch "^[A-Z]+$")
    {Write-Host "Message is Valid";}
else
    {
    Write-Host "Message is not Valid";
    return;
    }
if($leftalphabet -cmatch "^[A-Z]{26}$")
    {Write-Host "Left is Valid";}
else
    {
    Write-Host "Left is not Valid";
    return;
    }
if($rightalphabet -cmatch "^[A-Z]{26}$")
    {Write-Host "Right is Valid";}
else
    {
    Write-Host "Right is not Valid";
    return;
    }

# I want to use a linked list to manage the rotations
$left = New-Object System.Collections.ArrayList
$right = New-Object System.Collections.ArrayList
$cipher = New-Object System.Collections.ArrayList

# convert left and right to linked lists
for($i=0;$i -le 25; $i++)
    {
        $left.add($leftalphabet[$i]);
        $right.add($rightalphabet[$i]);
    }

$cipher = ""

#for each letter in the message
for($index=0; $index -ne $message.length;$index++)
{
    # Find the plain text letter and shift it to the front
    while(($message[$index] -ne $right[0] -and $encrypt -eq 1) -or ($message[$index] -ne $left[0] -and $encrypt -ne 1) )
        {
        $right.Add($right[0]); $right.removeat(0); # Shift left
        $left.add($left[0]);    $left.removeat(0); # Shift Left
        }
    if($encrypt -eq 1)
        {$cipher += $left[0];}
    else
        {$cipher += $right[0];}

    # move from zenith + 1 to nadar (zenith + 13) position
    $left.insert(14,$left[1]);
    $left.removeat(1);

    # rotate right one more letter
    $right.Add($right[0]);   $right.removeat(0);  #Shift left

    # move from zenith + 2 to nadar (zenith + 13) position
    $right.insert(14,$right[2]);
    $right.removeat(2);
}
Write-Host $cipher;
}

#encrypt
get-chaocipher "WELLDONEISBETTERTHANWELLSAID" "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" 1
#decrypt
get-chaocipher "OAHQHCNYNXTSZJRRHJBYHQKSOUJY" "HXUCZVAMDSLKPEFJRIGTWOBNYQ" "PTLNBQDEOYSFAVZKGJRIHWXUMC" 0

Decryption is as simple as checking from the other list. All the other steps are the same.

June 26, 2010

Signing Powershell and Applications the easy way

Filed under: Script — Tags: , — Kevmar @ 4:19 pm

My last post showed you an easy way to sign windows scripting host files. The same thing is available for Powershell and other executables. I found a lot of complicated way to sign applications before I figured out that Powershell can sign them too. This still assumes you have a Code Singing Cert already. Here is my Powershell signing script

$cert = @(gci cert:\currentuser\my -CodeSigningCert )[0]
Set-AuthenticodeSignature $args[0] $cert

I save that in a file called SignScript.ps1 on my computer where my cert is installed into the local store. The script I want signed is passed as $args[0] from the command line like this:

PS C:\> .\SignScript.ps1 myScript.ps1
PS C:\> .\SignScript.ps1 myApp.exe

I take this one step further by adding a sign option on the right click context menu from explorer. This is very easy to set up if you get it working from the command line. From regedit, open HKEY_CLASS_ROOT, and find Microsoft.PowerShellScript.1 (and exefile). Under the key called Shell, add a key called “Sign”. This is what will show up in the context menu. Under the key you added, add a new key called “command”. Then set the default value on that “command” key to match this .reg file.

[HKEY_CLASSES_ROOT\Microsoft.PowerShellScript.1\Shell\Sign\Command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" \"-file\" \"C:\\Scratch\\Scripts\\SignScript.ps1\" \"%1\""

[HKEY_CLASSES_ROOT\exefile\shell\Sign\command]
@="\"C:\\Windows\\System32\\WindowsPowerShell\\v1.0\\powershell.exe\" \"-file\" \"C:\\Scratch\\Scripts\\SignScript.ps1\" \"%1\""

Now when you right click a .ps1 or .exe file, you can digitally sign it.

Signing scripts the easy way: VBS, JS, WScript, CScript

Filed under: Script,Uncategorized — Tags: — Kevmar @ 4:06 pm

If you have a code signing cert, it is very easy to sign scripts.  Here is the VBS script I use to sign them with.

Set objSigner = WScript.CreateObject("Scripting.Signer")
objSigner.SignFile WScript.Arguments(0), "Kevin Marquette"

I save that in a file called SignScript.vbs on my computer where my cert is installed into the local store. My cert is named “Kevin Marquette” and the script I want signed is passed as arg0 from the command line like this:

c:\> SignScript myScript.vbs

I take this one step further by adding a sign option on the right click context menu from explorer. This is very easy to set up if you get it working from the command line. From regedit, open HKEY_CLASS_ROOT, and find VBSFile (or JSFile). Under the key called Shell, add a key called “Sign”. This is what will show up in the context menu. Under the key you added, add a new key called “command”. Then set the default value on that “command” key to match this .reg file.

[HKEY_CLASSES_ROOT\VBSFile\Shell\Sign\command]
@="\"c:\\windows\\System32\\CScript.exe\" C:\\Scripts\\SignScript.vbs \"%1\""

Now when you right click a .vbs file, you can sign it.

March 8, 2010

Powershell: List the size of folders or sub folders

Filed under: Script — Tags: — Kevmar @ 6:29 am

I was wanting to see how big my users’ home folders are.  With out quotas in place, I decided to use powershell.  I put together a function that will list the size of a folder that I pass to it. I wrote it in a way that if I pass a collection of folders to it, it will list the sizes of those folders individually.   This way I can spot check individual folders or check every folder in the home folders location.

This works even better for me because I need it to list the sub folder of each folder in the home folder location.  My home folders are placed in department folders.  So I have to add that extra step to every script I use to make sure it processes at the right level.  Allowing my function to work on a collection of folders allows powershell to handle this for me. Here is the syntax in action:

#Single folder
PS> Get-Item . | Get-FolderSize

#Sub folders
PS> Get-ChildItem . | Get-FolderSize

#Sub Sub Folders
PS> Get-ChildItem . | %{Get-ChildItem $_.FullName} | Get-FolderSize

It is required that you pass your directory objects to it.  I may update it to allow you to pass a folder path later. But for my needs, this is exactly how I will use it in my scripts.  Here is the full code for Get-FolderSize:

function Get-FolderSize ($_ = (get-item .))  {
  Process {
    $ErrorActionPreference = "SilentlyContinue"
    $length = (Get-ChildItem $_.fullname -recurse | Measure-Object -property length -sum).sum
    $obj = New-Object PSObject
    $obj | Add-Member NoteProperty Name ($_.Name)
    $obj | Add-Member NoteProperty FullName ($_.FullName)
    $obj | Add-Member NoteProperty Length ($length)
    $obj | Add-Member NoteProperty MB ("{0,13:N2}" -f ($length / 1MB))
    Write-Output $obj
  }
}

March 4, 2010

Powershell: WGet as Get-WebPage

Filed under: Script — Tags: — Kevmar @ 5:10 am

WGet is an old favorite of mine.  It is very easy to replicate in powerhshell by calling out to the system.web.WebClient object.

function Get-WebPage{
  Process {
   if($_ -ne $null){
      Write-Output (new-object system.net.WebClient).DownloadString($_)
    }
    elseif ($args[0] -ne $null){
      Write-Output (new-object system.net.WebClient).DownloadString($args[0])
    }
  }
}

Get-WebPage "http://www.ithinkincode.com"

All this gives you is the raw text of the page. You can then pipe it into a file or into another function.

March 2, 2010

Powershell Grep to find old server names in batchfiles

Filed under: Script,Uncategorized — Tags: — Kevmar @ 11:40 am

I was troubleshooting a user access problem today and found that they had a old mapping to an old server in the login script.  We just moved all our data to a different server so it was expected to have a few issues like this.  We do use DFS for most of our shares so the transition was very smooth for most people.  Just a few exceptions needed fixed.

I think we just over looked the log in scripts so I needed a script to check them all.  This is where I should just use grep but I wanted to see how to do it in powershell.  Here is the command I came up with:

PS> get-childitem \\domain\netlogon -include *.bat -recurse | select-string "oldserver"

Here is another way to do the same thing with a few shorcuts that could be easier to remember at the command line:

PS> cd \\domain\netlogon
PS> dir -recurse | select-string "oldserver"

dir is short for get-childitem.  If all you have are .bat files in netlogon you can skip the include.  If you have other install files or packages, use the include to save time.

December 22, 2007

Mapping a drive with custom name

Filed under: Script,Solutions — Kevmar @ 7:10 am

When mapping a drive, the full path of the share is displayed as the name of the drive. We have some very long path names and didn’t want our users to see the details they didn’t need. So I had to write a script to give those drives custom names.

Our login scripts contained lots of net use statements in *.BAT or *.CMD files. The command looked like this:

NET USE H: //server/share/directory1/directory2/directory3

and it would show in explorer like this:

directory3 on //server/share/directory1/directory2 (H:)

My goal was to make a script just as easy to use at NET USE. That is exactly what I ended up with. The new command looks like this:

Map.vbs H: //server/share/directory1/directory2/directory3 "My directory3"

and it would map like this:
My directory3 (H:)

By making the command simple the scripts are easy to read and modify by others on my team. Now that you know what we are doing, lets take a look at the code needed to make this work.

We are going to save this code with the name Map.vbs. Its a VBScript file executed by the windows scripting host. To make the script more usable, it needs to read the variables from the command line. The first 3 lines populate the variables we will use later.

strDriveLetter = WScript.Arguments(0)strPath = WScript.Arguments(1)strDisplayName = WScript.Arguments(2)

The next 2 lines I am going to show you display how to map the drive.

Set objNetwork = CreateObject("WScript.Network") objNetwork.MapNetworkDrive strDriveLetter, strPath, true

This will map the path strPath to the drive strDriveLetter. The true as the 3rd param is the same as using the /PERSIST param of NET USE. It saves the mapping in the profile.

Now we need to change the name of the mapping. This takes an existing share by drive letter and gives it a custom display name. This was one of the hardest pieces of code to find. The next 2 lines do just that.

Set oShell = CreateObject("Shell.Application") oShell.NameSpace(strDriveLetter & "\").Self.Name = strDisplayName

If you put that all together you have a bare bones script to map a drive and rename it from the command line via a VBScript. In my next post, I plan on going more in depth into my map.vbs. I will show you how to check for an existing mapping on that letter and all the validation I added.

December 9, 2007

Running vbs from .net code

Filed under: .NET,Script,Solutions — Tags: — Kevmar @ 6:00 pm

There are a few ways to run vbscript inside vb.net. If you just need the script to run, you can use the process object.

Dim oProcess as new ProcessTry   oProcess.StartInfo.UseShellExecute = True   oProcess.StartInfo.FileName = "CScript c:\script.vbs //nologo"   oProcess.Start()   oProcess.WaitForExit()Finally   oProcess.Dispose()End Try

Process Class

If you have some VBScript that you want to intereact with variables or run on the fly. Microsoft has a ScriptControl that allows you to do just that. The script control has 3 options of running code.

  • Eval: Evaluates a text expression.
  • Run: Runs a named Sub or Function.
  • Execute: Executes a script statement.

You can find more information on the ScriptControl at Microsoft.
Q184740: How To Call Functions Using the Script Control
Q184739: INFO: Where to Obtain the Script Control

If you are looking to run vb.net code inside vbscript, see my other post:
Running VB.NET code in VBScript or other apps

October 19, 2007

Running VB.NET code in VBScript or other apps

Filed under: .NET,Script,Solutions — Tags: — Kevmar @ 8:54 am

Here is how you can write a .NET component and use it in a script. First, create a library that contains the code you want to run.

Public Class FileWriter    Public Sub Save(ByVal PathAndFileName As String)        Try            Dim FileStream As New System.IO.StreamWriter(PathAndFileName, False)                  FileStream.WriteLine("Hello World")            FileStream.Flush()            FileStream.Close()     FileStream.Dispose()

        Catch e As Exception            Dim fs As New System.IO.StreamWriter("C:\error.txt", True)            fs.WriteLine("Exception: {1}", 1, e.Message)            fs.Flush()            fs.Close()            fs.Dispose()            Throw e        End Try

    End SubEnd Class

Then compile the library and run regasm c:\project\bin\NameOfDLL.dll /CODEBASE to register it. Regasm is in your .net folder. That will register the dll so you can use it later. Regsvr32 is for non .NET dlls. Your script is next. Save it as a .vbs file.

dim fs
set fs = CreateObject(“Project1.FileWriter”)
fs.save “c:\file.txt”
set fs = nothing

Anyplace you can call CreateObject, you should be able to use your class. VBA in office is one such place. And I did not test this code, I just gutted another project to have some examples.

Related: Running vbs from .net code

Older Posts »

Powered by WordPress