Posted by

Add local user to windows server 2012

To add a local users/users account to a Windows Server 2012 remotely or locally via PowerShell it is basically the same process that works for Server 2003/2008.

First create a CSV file containing the fullname/password/userid details.

image

Next create the script.

 1:

 2: $ComputerName = 'localhost'

 3:

 4: $computer = [ADSI]"WinNT://$ComputerName"

 5:

 6:

 7: Import-Csv C:\smbshare\userlist.csv | ForEach-Object {

 8:

 9:     $user = $computer.Create("User",$_.userid)

 10:

 11:     $user.setpassword($_.password)

 12:

 13:     $user.put("fullname",$_.Fullname)

 14:

 15:     $user.SetInfo()

 16:

 17:     $User.UserFlags[0] = $User.UserFlags[0] -bor 0x10000  #ADS_UF_DONT_EXPIRE_PASSWD flag is 0x10000

 18:

 19:     $User.SetInfo()

 20:

 21: }

Notice line 17, this sets the password to “Do Not Expire”

 1: $User.UserFlags[0] = $User.UserFlags[0] -bor 0x10000  #ADS_UF_DONT_EXPIRE_PASSWD flag is 0x10000

Here are the users visible in server manager.

image

Thanks

Billy

Powershell v3–new feature

Powershell V3 comes with many new features and improvement’s, one new feature that recently caught my eye is Default Parameter Sets, Steve Murawski has an excellent blog post on the subject (http://blog.usepowershell.com/category/powershell/powershell-version-3/powershell-version-3-ctp-2/).

On my local machine which is running the Powershell V3 Beta, I use this feature to set the default credential for connecting to remote machines

$cred = Get-Credential domain\user


$PSDefaultParameterValues = @{"*:Credential" = $cred}

By doing this I don’t need to enter the credentials every time i want to run PowerShell against a remote machine.

Billy

Insert Directory structure into sql ce

I recently had to store the structure of a directory in a SQL CE database using PowerShell.

The database had to store the directory name and the name, length and last write time of the files in the directory.

So first i had to create a new SQL CE database and table.

 1: $binpath = "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\";

 2: [Reflection.Assembly]::LoadFile("$binpath\System.Data.SqlServerCe.dll")

 3: #$connectionString = "Data Source='C:\Dropbox\MyWebSites\sciArchive\App_Data\ArchiveList.sdf';"

 4:

 5: $connectionString = "Data Source='C:\DB_Archives-01.sdf';"

 6:

 7: $engine = New-Object "System.Data.SqlServerCe.SqlCeEngine" $connectionString

 8: $engine.CreateDatabase()

 9: $engine.Dispose()

 10:

 11: $connection = New-Object "System.Data.SqlServerCe.SqlCeConnection" $connectionString

 12: $command = New-Object "System.Data.SqlServerCe.SqlCeCommand"

 13: $command.CommandType = [System.Data.CommandType]"Text"

 14: $command.Connection = $connection

 15:

 16: $connection.Open()

 17:

 18: $command.CommandText = "CREATE TABLE [tbl_Archives] (

 19:                           [DirectoryName] nvarchar(255) NOT NULL

 20:                         , [Name] nvarchar(255) NOT NULL

 21:                         , [Length] int NOT NULL

 22:                         , [LastWriteTime] nvarchar(100)  NOT NULL

 23:                         );"

 24: $command.ExecuteNonQuery()

Next step was to create a script to get the contents of the directory and insert the information into the table.

 1:

 2: Add-Type -Path "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\System.Data.SqlServerCe.dll";

 3:

 4: $connectionString = "Data Source=C:\DB_Archives-01.sdf;"

 5:

 6: $connection = New-Object "System.Data.SqlServerCe.SqlCeConnection" $connectionString

 7: $command = New-Object "System.Data.SqlServerCe.SqlCeCommand"

 8: $command.CommandType = [System.Data.CommandType]"Text"

 9: $command.Connection = $connection

 10:

 11: $connection.Open()

 12:

 13: Set-location -Path "C:\20100824"

 14: $list = Get-ChildItem

 15:

 16:

 17: $things = $list | select @{Name="DirectoryName";Expression={$_.DirectoryName.substring($_.DirectoryName.Length – 8, 8)}},

 18:                          Name,

 19:                          LastWriteTime,

 20:                          Length

 21:

 22: foreach ($item in $things ){

 23:     [string]$xDirectoryName = $item.DirectoryName

 24:     [string]$xName = $item.Name

 25:     [int]$xLength = $item.Length

 26:     $xLastWriteTime = $item.LastWriteTime

 27:

 28:     $command.CommandText = "

 29:         INSERT INTO [tbl_Archives]

 30:             ([DirectoryName],

 31:             [Name],

 32:             [Length],

 33:             [LastWriteTime])

 34:         VALUES (N'$xDirectoryName',N'$xName',N'$xLength ',N'$xLastWriteTime');"

 35:     $command.ExecuteNonQuery()

 36: }

Hope this is of use to you.

Billy

Tagged , ,

Powershell + sql ce database

Recently I start using WebMatrix (http://www.microsoft.com/web/webmatrix/) to develop a app that would allow users to request the restore of certain backed up archive files.

WebMatrix uses SQL Compact Edition as it’s database backend and as the archive system is built using PowerShell, I needed away to write to the database when ever a new archive was created.

After some research I had enough information to create a few functions that would allow me to:

  • Create a new SQL CE Database.
  • Create a new SQL CE Table.
  • Create a new SQL CE Row.

The functions are written for my particular needs but with a little bit of tweaking you could tailor them to your needs.

Function’s

New-DB-sqlCE

 1: function New-DB-sqlCE {

 2:     <#

 3:         .SYNOPSIS

 4:             Create a new SQL CE Database.

 5:

 6:         .DESCRIPTION

 7:             Create a new SQL CE Database.

 8:

 9:         .PARAMETER  dbName

 10:             The value for the dbName field.

 11:

 12:         .PARAMETER  dbPath

 13:             The value for the dbPath field, if blank the current location

 14:             will be used.

 15:

 16:         .EXAMPLE

 17:             PS C:\> New-sqlCEDB -dbName "testDB101" -dbPath "c:\"

 18:

 19:         .NOTES

 20:

 21:             You must have Microsoft SQL CE Server installed.

 22:             you can download it from here.

 23:

 24:             http://www.microsoft.com/en-us/download/details.aspx?id=17876

 25:     #>

 26:     [CmdletBinding()]

 27:     param(

 28:         [Parameter(Position=0, Mandatory=$true)]

 29:         [ValidateNotNullOrEmpty()]

 30:         [System.String]

 31:         $dbName,

 32:

 33:         [Parameter(Position=1, Mandatory=$false)]

 34:         [System.String]

 35:         $dbPath

 36:     )

 37:

 38:         Add-Type -Path "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\System.Data.SqlServerCe.dll";

 39:

 40:         $connectionString = "Data Source=$dbPath$dbName.sdf;"

 41:

 42:         $engine = New-Object "System.Data.SqlServerCe.SqlCeEngine" $connectionString

 43:         $engine.CreateDatabase()

 44:         $engine.Dispose()

 45:

 46: }

New-Table-sqlCE

 1: function New-Table-sqlCE {

 2:     <#

 3:         .SYNOPSIS

 4:             Create a new SQL CE Table.

 5:

 6:         .DESCRIPTION

 7:             Create a new SQL CE Table.

 8:

 9:         .PARAMETER  dbName

 10:             The value for the dbName field.

 11:

 12:         .PARAMETER  dbPath

 13:             The value for the dbPath field, if blank the current location

 14:             will be used.

 15:

 16:         .PARAMETER  tblName

 17:             The value for the tblName field, if blank the current location

 18:             will be used.

 19:

 20:         .EXAMPLE

 21:             PS C:\> New-sqlCEDB -dbName "testDB101" -dbPath "c:\"

 22:

 23:         .NOTES

 24:             You must have Microsoft SQL CE Server installed.

 25:             you can download it from here.

 26:

 27:             http://www.microsoft.com/en-us/download/details.aspx?id=17876

 28:     #>

 29:     [CmdletBinding()]

 30:     param(

 31:         [Parameter(Position=0, Mandatory=$true)]

 32:         [ValidateNotNullOrEmpty()]

 33:         [System.String]

 34:         $dbName,

 35:

 36:         [Parameter(Position=1, Mandatory=$false)]

 37:         [System.String]

 38:         $dbPath,

 39:

 40:         [Parameter(Position=3, Mandatory=$true)]

 41:         [ValidateNotNullOrEmpty()]

 42:         [System.String]

 43:         $tblName

 44:     )

 45:

 46:         Add-Type -Path "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\System.Data.SqlServerCe.dll";

 47:

 48:         $connectionString = "Data Source=$dbPath$dbName.sdf;"

 49:

 50:         $connection = New-Object "System.Data.SqlServerCe.SqlCeConnection" $connectionString

 51:         $command = New-Object "System.Data.SqlServerCe.SqlCeCommand"

 52:         $command.CommandType = [System.Data.CommandType]"Text"

 53:         $command.Connection = $connection

 54:

 55:         $connection.Open()

 56:

 57:         $command.CommandText = "CREATE TABLE [$tblName] (

 58:                           [ArchiveName] int NOT NULL

 59:                         , [FileName] nvarchar(255) NOT NULL

 60:                         , [FileSizeKB] int NOT NULL

 61:                         , [FileLastWriteTime] nvarchar(25) NOT NULL

 62:                         );"

 63:         $command.ExecuteNonQuery()

 64:

 65:         $command.Dispose()

 66:         $connection.Close();

 67:         $connection.Dispose;

 68:

 69: }

New-Row-sqlCE

 1: function New-Row-sqlCE {

 2:     <#

 3:         .SYNOPSIS

 4:             Insert a row into a SQL CE table.

 5:

 6:         .DESCRIPTION

 7:             Insert a row into a SQL CE table.

 8:

 9:         .PARAMETER  dbName

 10:             The value for the dbName field.

 11:

 12:         .PARAMETER  dbPath

 13:             The value for the dbPath field, if blank the current location

 14:             will be used.

 15:

 16:         .PARAMETER  tblName

 17:             The value for the tblName field, if blank the current location

 18:             will be used.

 19:

 20:         .PARAMETER  ArchiveName

 21:             The value for the ArchiveName field.

 22:

 23:         .PARAMETER  FileName

 24:             The value for the FileName field.

 25:

 26:         .PARAMETER  FileSizeKB

 27:             The value for the FileSizeKB field.

 28:

 29:         .PARAMETER  FileLastWriteTime

 30:             The value for the FileLastWriteTime field.

 31:

 32:         .EXAMPLE

 33:             PS C:\> insert-sqlCEDB -ArchiveName 20120909 -FileLastWriteTime "09/09/2012" -FileName "file2" -FileSizeKB 1024

 34:     #>

 35:     [CmdletBinding()]

 36:     param(

 37:         [Parameter(Position=0, Mandatory=$true)]

 38:         [ValidateNotNullOrEmpty()]

 39:         [System.String]

 40:         $dbName,

 41:

 42:         [Parameter(Position=1, Mandatory=$false)]

 43:         [System.String]

 44:         $dbPath,

 45:

 46:         [Parameter(Position=3, Mandatory=$true)]

 47:         [ValidateNotNullOrEmpty()]

 48:         [System.String]

 49:         $tblName,

 50:

 51:         [Parameter(Position=4, Mandatory=$true)]

 52:         [ValidateNotNullOrEmpty()]

 53:         [System.Int32]

 54:         $ArchiveName,

 55:

 56:         [Parameter(Position=5, Mandatory=$true)]

 57:         [ValidateNotNullOrEmpty()]

 58:         [System.String]

 59:         $FileName,

 60:

 61:         [Parameter(Position=6, Mandatory=$true)]

 62:         [ValidateNotNullOrEmpty()]

 63:         [System.Int32]

 64:         $FileSizeKB,

 65:

 66:         [Parameter(Position=7, Mandatory=$true)]

 67:         [ValidateNotNull()]

 68:         [System.String]

 69:         $FileLastWriteTime

 70:     )

 71:

 72:         Add-Type -Path "C:\Program Files\Microsoft SQL Server Compact Edition\v4.0\Desktop\System.Data.SqlServerCe.dll";

 73:

 74:         $connectionString = "Data Source=$dbPath$dbName.sdf;"

 75:

 76:         $connection = New-Object "System.Data.SqlServerCe.SqlCeConnection" $connectionString

 77:         $command = New-Object "System.Data.SqlServerCe.SqlCeCommand"

 78:         $command.CommandType = [System.Data.CommandType]"Text"

 79:         $command.Connection = $connection

 80:

 81:         $connection.Open()

 82:

 83:         $command.CommandText = "INSERT INTO [$tblName] ([ArchiveName],[FileName],[FileSizeKB],[FileLastWriteTime]) VALUES ($ArchiveName,N'$FileName',$FileSizeKB,N'$FileLastWriteTime');"

 84:         $command.ExecuteNonQuery()

 85:

 86:

 87:         $command.Dispose()

 88:         $connection.Close();

 89:         $connection.Dispose;

 90: }

I hope you will find these functions useful.

For more info check out this on MSDN

http://blogs.msdn.com/b/miah/archive/2011/08/08/powershell-and-sql-server-compact-4-0-a-happy-mix.aspx

This is also useful.

http://erikej.blogspot.co.uk/2011/07/using-powershell-to-manage-sql-server.html

Billy

Tagged , , ,

PowerShell + WPF + XAML = Cool

To create a GUI for your script try using WPF + XAML.

Here is a few things that worked for me.

Lets start with a basic script.

 1: Add-Type -AssemblyName presentationframework
 2:
 3: [xml]$XAML = @"
 4: <Window
 5:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 6:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 7:   Height="150" Width="150">
 8:
 9: </Window>
 10: "@
 11:
 12: $Reader=(New-Object System.Xml.XmlNodeReader $xaml)
 13: $Window=[Windows.Markup.XamlReader]::Load( $Reader )
 14:
 15:
 16: $Window.ShowDialog() | out-null

That should make a small blank window appear.

image

So what you may be thinking! what good is that?

But be patient please this is only the beginning.

Lets make some text appear in the window.

 1: Add-Type -AssemblyName presentationframework
 2:
 3: [xml]$XAML = @"
 4: <Window
 5:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 6:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 7:   Height="150" Width="150">
 8:
 9:     <Label Content="Hello World!"/>
 10:
 11: </Window>
 12: "@
 13:
 14: $Reader=(New-Object System.Xml.XmlNodeReader $xaml)
 15: $Window=[Windows.Markup.XamlReader]::Load( $Reader )
 16:
 17:
 18: $Window.ShowDialog() | out-null

So guess what might happen?

image

So have I got your attention yet?

Ok it’s still not that exciting but hopefully you are following along.

To make it a tiny bit better to look at lets center the label in the window.and add a bit of colour.

 1: Add-Type -AssemblyName presentationframework
 2:
 3: [xml]$XAML = @"
 4: <Window
 5:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 6:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 7:   Height="150" Width="150"
 8:   Background="lightblue">
 9:
 10:    <Label HorizontalAlignment="Center"
 11:           VerticalAlignment="Center"
 12:           FontSize="18"
 13:           Foreground="White"
 14:           Content="Hello World!"/>
 15:
 16: </Window>
 17: "@
 18:
 19: $reader=(New-Object System.Xml.XmlNodeReader $xaml)
 20: $Window=[Windows.Markup.XamlReader]::Load( $reader )
 21:
 22: $Window.ShowDialog() | out-null

image

Now that we have it looking a bit better lets change the content of our label via PowerShell.

To be able to change the content of the label we have to do three things:

Give the label a name, find the label in the xaml and then set the content to the new value.

 1: Add-Type -AssemblyName presentationframework
 2:
 3: [xml]$XAML = @"
 4: <Window
 5:   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 6:   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 7:   Height="150" Width="150"
 8:   Background="lightblue">
 9:
 10:    <Label HorizontalAlignment="Center"
 11:           VerticalAlignment="Center"
 12:           FontSize="18"
 13:           Foreground="White"
 14:           Content="Hello World!"
 15:           Name="myHostName" />
 16:
 17: </Window>
 18: "@
 19:
 20: $reader=(New-Object System.Xml.XmlNodeReader $xaml)
 21: $Window=[Windows.Markup.XamlReader]::Load( $reader )
 22:
 23: $myHostName = $Window.findname("myHostName")
 24:
 25: $myHostName.Content = $env:computername
 26:
 27: $Window.ShowDialog() | out-null

image

The change to the script will display you computer name in the window.

 

This has been a very basic intro but it should be enough to get you going.

Tagged , , ,

Search an XML Document for a Specific Value

Here is an example of how to search through an XML document for a value of an attribute:

Here is the XML file:

<?xml version="1.0" encoding="utf-8"?>
<root>
 <archive Name="20100821">
 <File Name="Log20100821.log" SizeKB="117727" LastWriteTime="08/21/2010 06:33:35" />
 <File Name="Archive20100821.log" SizeKB="3" LastWriteTime="08/21/2010 06:33:35" />
 <File Name="Routine20100821.log" SizeKB="74" LastWriteTime="08/21/2010 06:33:36" />
 </archive>
 <archive Name="20100828">
 <File Name="Log20100828.log" SizeKB="148740" LastWriteTime="08/28/2010 06:34:14" />
 <File Name="Archive20100828.log" SizeKB="4" LastWriteTime="08/28/2010 06:34:15" />
 <File Name="Routine20100828.log" SizeKB="90" LastWriteTime="08/28/2010 06:34:15" />
 </archive>
</root>

To find <archive Name=”20100828″> try this:

$xml = [xml](get-content xml.xml)
$searchItem = "20100828"
$xml.SelectNodes("root/archive") | ? { $_.Name -eq $searchItem} | % {$_.File } | ft -AutoSize

This should return these results:

Tagged ,

How to initiate a Remote Desktop Session from Powershell

To initiate a RDP session from a script try this:

Create a new RDP Connection

Enter all the required details and then save the connection

Then you can run it from you script using this:


$RDPServer = "c:\RDP\Server1.rdp"
Write-Verbose " Invokeing $RDPServer Session"
invoke-Expression "mstsc.exe '$RDPServer'"

If you want your script to wait for the RDP session to exit before it continues then add this:

$mstscProcess = (Get-Process | Where-Object { $_.ProcessName -ieq "mstsc" })
Write-verbose "Waiting for MSTSC.EXE to exit"
$mstscProcess.WaitForExit()
Write-verbose "MSTSC.EXE ended"

Get a test page from your printers

Here is a little function to request a test page from each of the printers you are connected to.

# Get Printer Objects for this computer from WMI

$vPrinters = Get-WmiObject -Class Win32_printer

# Print a test page for each printer

foreach ($vPrinter in $vPrinters)

{ $vPrinter.PrintTestPage() }

CREATE NEW XML FILE

Here is a little function i created to create an XML file from the structure of a folder.

The folder structure looks like this:

E:\Archives\LatestArchiveFiles

20100821

Log20100821.log
Archive20100821.log
Routine20100821.log

20100828

Log20100828.log
Archive20100828.log
Routine20100828.log

It works by doing a Get-ChildItem on the folder and creating the XML file based on the folder structure.


Function New-XMLFile ($Path = "E:\Gateway\Archives")
 {
Set-Location $path
Write-Verbose "Path has been set to $path"
$VerbosePreference = "Continue"
#$VerbosePreference = "silentlyContinue"
Write-Verbose $pwd
$xml = New-Object xml
$rootElements = gci
$root = $xml.CreateElement("root")
[void]$xml.AppendChild($root)

foreach($archiveElement in $rootElements ){
 Write-Verbose "Archive Loop, for $archiveElement "
 Write-Verbose "Setting location to $archiveElement"
 set-location $path\$archiveElement
 Write-Verbose "location Set to $pwd"
 $archive = $xml.CreateElement("archive")
 [void]$root.AppendChild($archive)
 $archive.SetAttribute("Name", $archiveElement)
 $fileElements = gci
 foreach ($fileElement in $fileElements){
 Write-Verbose "File Loop"
 Write-Verbose "Looking at $fileElement`n"
 $fileSize = ($fileElement.Length/1KB).tostring("0")
 $file = $xml.CreateElement("File")
 [void]$archive.AppendChild($file)
 $file.SetAttribute("Name", $fileElement)
 $file.SetAttribute("SizeKB", $fileSize )
 $file.SetAttribute("LastWriteTime", $fileElement.LastWriteTime)
 }
 }
$xml.save("E:\Gateway\Archives")
}

New-XMLfile "C:\Documents and Settings\psuser"

The XML File created would look like this

<root>
 <archive Name="20100821">
 <File Name="Log20100821.log" SizeKB="117727" LastWriteTime="08/21/2010 06:33:35" />
 <File Name="Archive20100821.log" SizeKB="3" LastWriteTime="08/21/2010 06:33:35" />
 <File Name="Routine20100821.log" SizeKB="74" LastWriteTime="08/21/2010 06:33:36" />
 </archive>
 <archive Name="20100828">
 <File Name="Log20100828.log" SizeKB="148740" LastWriteTime="08/28/2010 06:34:14" />
 <File Name="Archive20100828.log" SizeKB="4" LastWriteTime="08/28/2010 06:34:15" />
 <File Name="Routine20100828.log" SizeKB="90" LastWriteTime="08/28/2010 06:34:15" />
 </archive>
</root>


Tagged , ,

create new folder structure

Here is a little function to create a new folder structure from a bunch of files.

The folder structure looks like this:

E:\Archives\LatestArchiveFiles

Log20100821.log
Archive20100821.log
Routine20100821.log
Log20100828.log
Archive20100828.log
Routine20100828.log

After running the function the folder structure looks like this:

E:\Archives\LatestArchiveFiles

20100821

Log20100821.log
Archive20100821.log
Routine20100821.log

20100828

Log20100828.log
Archive20100828.log
Routine20100828.log

It works by doing a Get-ChildItem on the folder and grouping the files by the date part of the file name, then it creates new folders based on the group name and moves the relevant files in to the new folder.

Function Create-New-Folder-Structure{
param($path = 'E:\Archives\LatestArchiveFiles')
$VerbosePreference = "Continue"
$ArchivePath = $null
Set-Location $path

$GroupByDate = {$z =($_.name).ToString(); $z.Substring($z.Length – 12, 8)}

$archiveGroups = Get-ChildItem '*.log' | Group-Object $GroupByDate | select group,name
write-verbose "The current folder is $pwd"
write-verbose "Start of Date Group Processing`n"

foreach ($archiveGroup in $archiveGroups){
 Set-Location $path
 $thisName = $archiveGroup.name
 write-verbose "Create new sub folder for archive $thisName"
 New-Item -Name $thisName -itemType directory
 # Copy logs to relevant year folder
 Write-Verbose "Moving archive files $thisName to $pwd\$thisName"
 $archiveGroup | % {$_.Group | % {move-item $_ -destination ($archiveGroup.name)}}
 }

Write-Verbose "$ArchivePath = $pwd"
#$global:ArchivePath = $pwd.path
Write-Verbose "$global:ArchivePath = $pwd"
return $ArchivePath
}

Create-New-Folder-Structure E:\Archives\LatestArchiveFiles

Write-Verbose $ArchivePath

Tagged ,
Follow

Get every new post delivered to your Inbox.