Showing posts with label windows. Show all posts
Showing posts with label windows. Show all posts

Thursday, May 29, 2014

Change server for installed printers

While changing our printserver we needed a way to update configuration on all machines in the domain.
First, the printers were migrated from old server to new with exactly the same configuration.

To update workstations, Configuration Baseline was created in SCCM.

Discovery script (returning something else than 0 = not compliant):
Get-WmiObject -Class Win32_Printer | where { $_.SystemName -like "*OLDSERVER*" } | Measure-Object | select -ExpandProperty Count

Remediation script (returning $true will mean failure in process):
$fail = $false
Get-WmiObject -Class Win32_Printer | where { $_.SystemName -like "*OLDSERVER*" } | select Name, Default | foreach {
    $newname = $($($_.name) -replace "OLDSERVER", "NEWSERVER")
    write-host "Replacing $($_.name) with $newname"
    #ADD NEW PRINTER
    (New-Object -ComObject WScript.Network).AddWindowsPrinterConnection($newname)
    if ($($_.default)) {
        write-host "Above is default printer"
        $default = $newname
    }
   
    #WAIT AND CHECK FOR SUCCESS
    write-host "Waiting 30 seconds to check for success"
    Start-Sleep 30
    if ( $(Get-WmiObject -Class Win32_Printer | where { $_.Name -eq $newname } | Measure-Object | select -ExpandProperty Count) -gt 0 ) {
        write-host "SUCCESS, removing old"
        (New-Object -ComObject WScript.Network).RemovePrinterConnection($($_.name))
        write-host "Setting printer as default"
        if ($default) {
            (New-Object -ComObject WScript.Network).SetDefaultPrinter($default)
            $default = $null
        }
    } else {
        write-host "FAIL, keeping old"
        $fail = $true
    }
}
write-host "Next line is True if errors, False if no errors:"
return $fail


The scripts were made quite fast and are not optimized, it is not needed as this is only a temporary configuration baseline. After old printserver is decommissioned, this baseline will be disabled.

Could this be done in a single line of code? :)

Thursday, January 2, 2014

Get AD user groups with managers

Because we have implemented groups with managers in Active Directory, there is a need to take reports on user group memberships and also the owners of the groups the user belongs to.

I had a really long script for a while but I've got a bit better and pipe things shorter (should be a trademark), so here is my new attempt on this topic:
  1. $list = @()
  2. Get-ADUser -Filter "Name -like ""*""" -SearchBase "OU=Users,DC=contoso,DC=eu" -Properties name | % {
  3.     $name = $_.name
  4.     $_ | Get-ADPrincipalGroupMembership | % {
  5.         $line = New-Object PSObject
  6.         $line | Add-Member -MemberType NoteProperty -Name "Name" -Value $name
  7.         $line | Add-Member -MemberType NoteProperty -Name "Group" -Value $($_.name)
  8.         $line | Add-Member -MemberType NoteProperty -Name "Manager" -Value $($_ | Get-ADGroup -Properties managedBy | Select -ExpandProperty managedBy | Get-ADObject | Select -ExpandProperty Name)
  9.         $list = $list + $line
  10.     }
  11. }
  12. $list | export-csv "c:\temp\usergroups.csv" -Encoding Unicode 
Instead of 68 lines I now get things done in 10 12 lines (gave a little edit for better reports). The original script had some comments and extra stuff in it, but it wont be missed.

If anyone has good hints on creating PSObjects with many properties in one line, let me know in comments ;)

Tuesday, December 18, 2012

Run powershell in windows batch file

I needed to run a powershell script in batch file so it would be executed as one line of commands, without requiring to run .ps1 file directly.
The task is fairly simple, I've done this before. But this time I ran into another problem, because the need of using " signs inside " signs that were actually around -command argument.
This leaded me to a problem that I couldn't use escape chars for " because it would escape it from script altogether.
I couldn't use ' signs either, because that would turn variable names into direct strings.

Here is what I had at start (works within powershell):

$date = Get-Content '.\card_dates.txt' | Select-Object -last 1;
Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) {
   Get-Content $_.FullName | Foreach-Object {
      $_ -replace '#PARAM_1', $date
   } | Set-Content "$($_.FullName).parsed"
}

Here is the modification that gave me the error (if running from batch):

powershell -Command "& { $date = Get-Content '.\card_dates.txt' | Select-Object -last 1; Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) { Get-Content $_.FullName | Foreach-Object {$_ -replace '#PARAM_1', $date} | Set-Content "$($_.FullName).parsed" } } "

This is the error:

Set-Content : Cannot bind argument to parameter 'Path' because it is null.
At line:1 char:222
+ ...  | Set-Content $($_.FullName).parsed } }
+                    ~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo          : InvalidData: (:) [Set-Content], ParameterBinding
   ValidationException
    + FullyQualifiedErrorId : ParameterArgumentValidationErrorNullNotAllowed,M
   icrosoft.PowerShell.Commands.SetContentCommand

So what did I change to make it work?
The solution was actually really simple.
Instead of using:
"$($_.FullName).parsed"

I had to use:
$($($_.FullName) + '.parsed')

And here is the solution that works directly from commandline

powershell -Command "& { $date = Get-Content '.\card_dates.txt' | Select-Object -last 1; Get-ChildItem '.\sql' -Exclude '*.parsed' | ForEach-Object ($_) { Get-Content $_.FullName | Foreach-Object {$_ -replace '#PARAM_1', $date} | Set-Content $($($_.FullName) + '.parsed') } } "

What this script does?
  1. Read last line from textfile (it is populated there by other scripts)
  2. Read all SQL files inside SQL folder
  3. Withing every file, change #PARAM_1 to be the last line from textfile
  4. Save the file with .parsed extension
Basically we have templates for SQL sentences and historically all the jobs run as BATCH files.
I'm better with Powershell so I wanted to do it in powershell but at the same time keep the old BATCH-es.

Hopefully this information is a bit helpful for you, I spent quite some time to figure out the simple solution.